pS-usage: captures held by live ReaSampler 9000 instances are un-prunable — instances publish usage_<guid> ext-state records (ComponentState v11), prune unions live holds into referenced
This commit is contained in:
@@ -2272,6 +2272,79 @@ static void testComponentStateV9LiftsToEmptyRefs() {
|
||||
CHECK(back.map.zones.empty());
|
||||
}
|
||||
|
||||
static void testInstanceGuidRoundTripV11() {
|
||||
// v11 (pS-usage): the minted publish identity round-trips with the envelope
|
||||
// neighbours (refs table before it, selection/zones after it) intact — the guid
|
||||
// read consumed exactly its own bytes. An empty guid (never published) is legal
|
||||
// and round-trips empty.
|
||||
ComponentState s;
|
||||
s.selectionId = "kick";
|
||||
s.instanceGuid = "0123456789abcdef0123456789abcdef";
|
||||
s.sampleRefs.push_back(refEntry("kick", "reasampler_bank/kick.wav", 36));
|
||||
s.map.zones.push_back(zone("kick", 0, 127));
|
||||
const ComponentState back =
|
||||
deserializeComponentState(serializeComponentState(s), 44100.0);
|
||||
CHECK(back.instanceGuid == "0123456789abcdef0123456789abcdef");
|
||||
CHECK(back.sampleRefs.size() == 1);
|
||||
CHECK(back.selectionId == "kick");
|
||||
CHECK(back.map.zones.size() == 1);
|
||||
|
||||
ComponentState fresh;
|
||||
fresh.selectionId = "s";
|
||||
const ComponentState freshBack =
|
||||
deserializeComponentState(serializeComponentState(fresh), 44100.0);
|
||||
CHECK(freshBack.instanceGuid.empty());
|
||||
CHECK(freshBack.selectionId == "s");
|
||||
}
|
||||
|
||||
static void testComponentStateV10LiftsToEmptyGuid() {
|
||||
// OLD-BLOB FALLBACK: a genuine v10 blob (refs table but no instance guid) restores
|
||||
// with an EMPTY guid — the processor mints one on first publish — and every other
|
||||
// field intact. Hand-built (serializeComponentState now emits v11, so it cannot
|
||||
// make a v10 blob).
|
||||
std::vector<std::uint8_t> v10;
|
||||
v10.push_back(10); v10.push_back(0); v10.push_back(0); v10.push_back(0); // version 10
|
||||
v10.push_back(0); // mode = mono
|
||||
for (int i = 0; i < 8; ++i) v10.push_back(0); // marker = 0
|
||||
v10.push_back(88); // preview velocity
|
||||
v10.push_back(7); // voice count
|
||||
v10.push_back(0); // voice mode = poly
|
||||
v10.push_back(0); // trigger = retrigger
|
||||
for (int i = 0; i < 8; ++i) v10.push_back(0); // gain double bytes...
|
||||
v10[17 + 6] = 0xF0; v10[17 + 7] = 0x3F; // ...= 1.0 (LE IEEE-754)
|
||||
v10.push_back(1); // explicit flag = true
|
||||
// The v10 refs table: ONE entry {id "a", path "b/a.wav", root 36, no loop, ch 0, no name}.
|
||||
v10.push_back(1); v10.push_back(0); v10.push_back(0); v10.push_back(0); // ref count 1
|
||||
v10.push_back(1); v10.push_back(0); v10.push_back(0); v10.push_back(0); // id len 1
|
||||
v10.push_back('a');
|
||||
const std::string relPath = "b/a.wav";
|
||||
v10.push_back(static_cast<std::uint8_t>(relPath.size()));
|
||||
v10.push_back(0); v10.push_back(0); v10.push_back(0);
|
||||
v10.insert(v10.end(), relPath.begin(), relPath.end());
|
||||
v10.push_back(36); v10.push_back(0); v10.push_back(0); v10.push_back(0); // root 36
|
||||
v10.push_back(0); // hasLoop = false
|
||||
for (int i = 0; i < 16; ++i) v10.push_back(0); // loop start+end
|
||||
v10.push_back(0); v10.push_back(0); v10.push_back(0); v10.push_back(0); // channels 0
|
||||
v10.push_back(0); v10.push_back(0); v10.push_back(0); v10.push_back(0); // name len 0
|
||||
// NO guid field (the v11 addition) — the selection id follows directly.
|
||||
const std::string id = "saved";
|
||||
v10.push_back(static_cast<std::uint8_t>(id.size()));
|
||||
v10.push_back(0); v10.push_back(0); v10.push_back(0);
|
||||
v10.insert(v10.end(), id.begin(), id.end());
|
||||
v10.push_back(0); v10.push_back(0); v10.push_back(0); v10.push_back(0); // zone count 0
|
||||
const ComponentState back = deserializeComponentState(v10, 44100.0);
|
||||
CHECK(back.instanceGuid.empty()); // pre-v11 blob -> empty guid (minted on publish)
|
||||
CHECK(back.sampleRefs.size() == 1);
|
||||
CHECK(back.sampleRefs.size() == 1 && back.sampleRefs[0].sampleId == "a");
|
||||
CHECK(back.sampleRefs.size() == 1 &&
|
||||
back.sampleRefs[0].ref.relativePath == "b/a.wav");
|
||||
CHECK(back.selectionId == "saved");
|
||||
CHECK(back.channelModeExplicit);
|
||||
CHECK(back.previewVelocity == 88);
|
||||
CHECK(back.voiceCount == 7);
|
||||
CHECK(back.map.zones.empty());
|
||||
}
|
||||
|
||||
static void testReferencedSampleIdsDedup() {
|
||||
// Selection first, then map order, duplicates collapsed; an empty selection contributes
|
||||
// nothing (no phantom "" id in the refs table).
|
||||
@@ -2524,6 +2597,8 @@ int main() {
|
||||
testResolveFromRefsMissingRefDrops();
|
||||
testResolveFromRefsMatchesBankResolve();
|
||||
testComponentStateV9LiftsToEmptyRefs();
|
||||
testInstanceGuidRoundTripV11();
|
||||
testComponentStateV10LiftsToEmptyGuid();
|
||||
testReferencedSampleIdsDedup();
|
||||
testRefreshRefsFromBankUpsertAndOwnership();
|
||||
testRetainRefsFiltersToPlayedSet();
|
||||
|
||||
Reference in New Issue
Block a user