Q-W1 pt2: core/shell/app relocation + sub-namespaces; one concrete ui::Rect (LTRB fork retired); slot_map split from bank_book; BankIndex→BankModel; 59/59 green

This commit is contained in:
2026-07-28 20:48:56 -04:00
parent 67a41728f3
commit 847936f813
222 changed files with 2247 additions and 2079 deletions
+18 -15
View File
@@ -22,7 +22,7 @@
// stride contract across the seam (that the byte stride wav_trim reports matches the
// channel-count stride downmixToMono divides by).
#include "../src/vst/sample_map.h"
#include "../src/core/instrument/map/sample_map.h"
#include <cmath>
#include <cstdio>
@@ -30,18 +30,21 @@
#include <string>
#include <vector>
#include "../src/bank_book.h"
#include "../src/bank_model.h"
#include "../src/vst/master_gain.h" // masterGainMaxLinear (the v8 master-gain wire cap)
#include "../src/core/model/bank_book.h"
#include "../src/core/model/bank_model.h"
#include "../src/core/instrument/engine/master_gain.h" // masterGainMaxLinear (the v8 master-gain wire cap)
using namespace reasampler;
using namespace reasampler::instrument::engine;
using namespace reasampler::capture; // wav_trim (WavLayout) — sample_map re-exports live in reasampler until Q-W2v
using namespace reasampler::model;
static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
// Build a Sample with the fields sample_map reads. Relative path is required by
// BankIndex::add (relative-only invariant); a content hash is set so dedup does not
// BankModel::add (relative-only invariant); a content hash is set so dedup does not
// collapse distinct entries.
static Sample makeSample(const std::string& id, const std::string& name,
const std::string& rel, std::optional<int> root) {
@@ -62,7 +65,7 @@ static std::string bookJson(const std::vector<Sample>& poolSamples,
for (const Sample& s : poolSamples) book.pool().index.add(s);
if (!drumSamples.empty()) {
book.createBank("drums-id", "Drums");
BankIndex* di = book.index("drums-id");
BankModel* di = book.index("drums-id");
for (const Sample& s : drumSamples) di->add(s);
}
return book.serialize();
@@ -1305,7 +1308,7 @@ static void testComponentStateMasterGainWriterClamps() {
hi.masterGainLinear = 1000.0;
CHECK(std::fabs(deserializeComponentState(serializeComponentState(hi), 44100.0)
.masterGainLinear -
vst::masterGainMaxLinear()) < 1e-9);
instrument::engine::masterGainMaxLinear()) < 1e-9);
ComponentState lo;
lo.masterGainLinear = -5.0;
CHECK(deserializeComponentState(serializeComponentState(lo), 44100.0).masterGainLinear ==
@@ -1686,7 +1689,7 @@ static void testVelocityCurveRoundTrip() {
// A second zone left at the flat default proves the field is per-record and defaults to flat y=1.
PerformanceMap m;
PerformanceZone z = zone("lead", 20, 100);
z.velocityCurve = vst::VelocityCurve::linear();
z.velocityCurve = VelocityCurve::linear();
z.velocityCurve.addPoint(60.0, 0.3); // an interior knot to exercise multi-point round-trip
m.zones.push_back(z);
m.zones.push_back(zone("pad", 0, 19)); // default flat curve
@@ -1694,7 +1697,7 @@ static void testVelocityCurveRoundTrip() {
CHECK(back.zones.size() == 2);
if (back.zones.size() != 2) return;
CHECK(back.zones[0].velocityCurve.equals(z.velocityCurve)); // exact point round-trip
CHECK(back.zones[1].velocityCurve.equals(vst::VelocityCurve::flat())); // default preserved
CHECK(back.zones[1].velocityCurve.equals(VelocityCurve::flat())); // default preserved
// And the flat default really is unity everywhere (R10-F1 Option A), not the old linear ramp.
CHECK(back.zones[1].velocityCurve.eval(1.0) == 1.0);
CHECK(back.zones[1].velocityCurve.eval(64.0) == 1.0);
@@ -1706,12 +1709,12 @@ static void testVelocityCurveThroughComponentEnvelope() {
ComponentState s;
s.selectionId = "pick";
PerformanceZone z = zone("pick", 0, 127);
z.velocityCurve = vst::VelocityCurve::linear();
z.velocityCurve = VelocityCurve::linear();
s.map.zones.push_back(z);
const ComponentState back = deserializeComponentState(serializeComponentState(s), 44100.0);
CHECK(back.map.zones.size() == 1);
if (back.map.zones.size() != 1) return;
CHECK(back.map.zones[0].velocityCurve.equals(vst::VelocityCurve::linear()));
CHECK(back.map.zones[0].velocityCurve.equals(VelocityCurve::linear()));
}
static void testVelocityCurveResolvesToZone() {
@@ -1720,12 +1723,12 @@ static void testVelocityCurveResolvesToZone() {
const std::string json = bookJson({makeSample("a", "Kick", "b/a.wav", 36)}, {});
PerformanceMap m;
PerformanceZone z = zone("a", 0, 127);
z.velocityCurve = vst::VelocityCurve::linear();
z.velocityCurve = VelocityCurve::linear();
m.zones.push_back(z);
const ResolvedPerformance r = resolvePerformance(json, m);
CHECK(r.zones.size() == 1);
if (r.zones.size() != 1) return;
CHECK(r.zones[0].velocityCurve.equals(vst::VelocityCurve::linear()));
CHECK(r.zones[0].velocityCurve.equals(VelocityCurve::linear()));
}
// FA1 bug 3a — the COMPOSED end-to-end regression, mirroring the processor's reload composition
@@ -1740,7 +1743,7 @@ static void testVelocityCurveEndToEndThroughReloadComposition() {
ComponentState s;
s.selectionId = "a";
PerformanceZone z = zone("a", 0, 127);
z.velocityCurve = vst::VelocityCurve::linear();
z.velocityCurve = VelocityCurve::linear();
s.map.zones.push_back(z);
const ComponentState back = deserializeComponentState(serializeComponentState(s), 48000.0);
CHECK(back.map.zones.size() == 1);
@@ -1817,7 +1820,7 @@ static void testVelocityCurveV6BackCompatLiftsToFlat() {
CHECK(back.zones[0].sampleId == "v6saved");
CHECK(back.zones[0].keyTrack == 0.5); // the v6 field still read correctly
// No curve tail -> flat y=1 default (the deliberate behavior change).
CHECK(back.zones[0].velocityCurve.equals(vst::VelocityCurve::flat()));
CHECK(back.zones[0].velocityCurve.equals(VelocityCurve::flat()));
CHECK(back.zones[0].velocityCurve.eval(20.0) == 1.0); // a soft hit now plays at unity
}