test: S7xS11 compose — stereo+startFrame+loop share one read head; v4 stereo envelope + v2 zone overrides round-trip together
This commit is contained in:
@@ -941,6 +941,44 @@ static void testComponentStateV4TruncatedModeByte() {
|
||||
CHECK(back.selectionId.empty() && back.map.zones.empty());
|
||||
}
|
||||
|
||||
static void testComponentStateV4StereoWithZoneOverridesRoundTrip() {
|
||||
// The MERGE composition property (S7 v4 envelope x S11 v2 zones payload): a v4 blob carrying
|
||||
// channelMode = STEREO AND zones with loopOverride + startPoint must round-trip ALL of it
|
||||
// losslessly. The channel-mode byte lives on the envelope; the loop/start overrides live in
|
||||
// the self-versioned zones payload — the two tracks are orthogonal, so both survive one
|
||||
// serialize/deserialize. (V4RoundTripStereo covers mode with a bare zone; LoopStartRoundTrip
|
||||
// covers overrides at the default mono mode; this asserts them TOGETHER.)
|
||||
ComponentState s;
|
||||
s.selectionId = "pick";
|
||||
s.channelMode = ChannelMode::Stereo;
|
||||
PerformanceZone z0 = zone("z0", 12, 48, /*override=*/36);
|
||||
SampleLoop lp0; lp0.hasLoop = true; lp0.start = 500; lp0.end = 9000;
|
||||
z0.loopOverride = lp0;
|
||||
z0.startPoint = 128;
|
||||
PerformanceZone z1 = zone("z1", 49, 127); // second zone: no overrides (mixed payload)
|
||||
s.map.zones.push_back(z0);
|
||||
s.map.zones.push_back(z1);
|
||||
|
||||
const ComponentState back = deserializeComponentState(serializeComponentState(s));
|
||||
CHECK(back.channelMode == ChannelMode::Stereo); // envelope field survives
|
||||
CHECK(back.selectionId == "pick");
|
||||
CHECK(back.map.zones.size() == 2);
|
||||
CHECK(back.map.zones.size() == 2 && back.map.zones[0].sampleId == "z0" &&
|
||||
back.map.zones[0].lowNote == 12 && back.map.zones[0].highNote == 48);
|
||||
CHECK(back.map.zones.size() == 2 && back.map.zones[0].rootOverride.has_value() &&
|
||||
*back.map.zones[0].rootOverride == 36);
|
||||
CHECK(back.map.zones.size() == 2 && back.map.zones[0].loopOverride.has_value() &&
|
||||
back.map.zones[0].loopOverride->hasLoop &&
|
||||
back.map.zones[0].loopOverride->start == 500 &&
|
||||
back.map.zones[0].loopOverride->end == 9000);
|
||||
CHECK(back.map.zones.size() == 2 && back.map.zones[0].startPoint.has_value() &&
|
||||
*back.map.zones[0].startPoint == 128);
|
||||
// The override-free second zone stays override-free (the payload framing per zone is intact).
|
||||
CHECK(back.map.zones.size() == 2 && back.map.zones[1].sampleId == "z1" &&
|
||||
!back.map.zones[1].loopOverride.has_value() &&
|
||||
!back.map.zones[1].startPoint.has_value());
|
||||
}
|
||||
|
||||
int main() {
|
||||
testSelectByIdHit();
|
||||
testSelectEmptyIdIsSilence();
|
||||
@@ -1010,6 +1048,7 @@ int main() {
|
||||
testComponentStateV3LiftsToMono();
|
||||
testComponentStateV1V2LiftToMono();
|
||||
testComponentStateV4TruncatedModeByte();
|
||||
testComponentStateV4StereoWithZoneOverridesRoundTrip();
|
||||
|
||||
if (g_fail == 0) std::printf("sample_map: all tests passed\n");
|
||||
return g_fail != 0;
|
||||
|
||||
Reference in New Issue
Block a user