Close Γ-W1-T7 re-review: pitch-sync cadence math, floor-model regression check, evidence-count fix, one-home comments

New cadence-collapse-band test at P=1470 shows PSOLA eliminates the corner rather than regressing it (18.52% -> 0.00%).
This commit is contained in:
2026-08-02 05:34:43 -04:00
parent ef59265e7a
commit f1168e16eb
9 changed files with 249 additions and 40 deletions
+106
View File
@@ -0,0 +1,106 @@
// The one gated case that runs the WHOLE load->voice wire through REAL detection, closing the
// gap between two halves proven separately: testBuildSampleDataDetectsThirtyHertzSourcePeriod
// (test_sample_map.cpp, detectPeriod -> SampleData) never renders, and
// testSourcePeriodChangesTheRenderedStream (test_sampler_core.cpp, SampleData -> Voice -> audio)
// sets sourcePeriodFrames by hand rather than detecting it from PCM. Deliberately its own
// target: sample_map_tests and sampler_core_tests each keep their one-lib-only structural proof
// (map doesn't link the voice engine, the engine doesn't link period_detect), so bridging the
// two lives here instead of extending either.
#include "../src/core/instrument/map/sample_map.h"
#include "../src/core/instrument/engine/voice_engine.h"
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace reasampler;
using namespace reasampler::instrument::engine;
using namespace reasampler::instrument::map;
static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
constexpr double kPi = 3.14159265358979323846;
// An ADSR that stays fully open (level 1) forever while held — isolates the render from
// envelope shaping (matches test_sampler_core.cpp's flatAdsr; not shared, both files stand
// alone).
static AdsrParams flatAdsr() {
AdsrParams a;
a.attackFrames = 0;
a.decayFrames = 0;
a.sustainLevel = 1.0;
a.releaseFrames = 0;
return a;
}
// FNV-1a over the raw float bits (matches test_sampler_core.cpp's hashStream).
static std::uint64_t hashStream(const std::vector<AudioSample>& v) {
std::uint64_t h = 1469598103934665603ull;
for (const AudioSample s : v) {
std::uint32_t bits = 0;
std::memcpy(&bits, &s, sizeof(bits));
for (int b = 0; b < 4; ++b) {
h ^= static_cast<std::uint64_t>((bits >> (8 * b)) & 0xffu);
h *= 1099511628211ull;
}
}
return h;
}
static void renderVoice(const SampleData& s, int note, std::int64_t window,
std::size_t outFrames, std::vector<AudioSample>& out) {
Voice v;
v.presizePreserveShifters(window);
v.start(note, 127, s, /*declickTakeover=*/false, /*rate=*/1.0);
out.resize(outFrames);
for (std::size_t i = 0; i < outFrames; ++i) out[i] = v.renderFrame();
}
// 30 Hz @ 44.1k through the REAL wire: buildSampleData (sample_map.cpp:333-334) calls
// detectPeriod itself, so this proves the detected period actually reaches and moves the
// Preserve render — not just that a hand-set sourcePeriodFrames does (that is the sampler_core
// half; this is the missing map->engine seam).
static void testDetectedPeriodReachesAndMovesThePreserveRender() {
const std::int64_t w = 2205; // the product window at 44.1k
const int rate = 44100;
const std::size_t frames = 30000;
std::vector<AudioSample> pcm(frames);
for (std::size_t i = 0; i < frames; ++i) {
pcm[i] = static_cast<float>(
std::sin(2.0 * kPi * 30.0 * static_cast<double>(i) / rate));
}
SelectedSample ref;
ref.relativePath = "b/a.wav";
ref.rootNote = 60;
SampleData on = buildSampleData(resolveCapture(ref, InstrumentParams{}),
DecodedPcm{pcm, rate, {}});
CHECK(std::fabs(on.sourcePeriodFrames - 1470.0) < 2.0); // 44100 / 30 Hz, real detection
on.play.adsr = flatAdsr();
on.play.pitchEngine = PitchEngine::Preserve;
SampleData off = on;
off.sourcePeriodFrames = 0.0; // the fixed-window fallback the pre-wire render used
std::vector<AudioSample> outOn, outOff;
renderVoice(on, /*note=*/67, w, 6000, outOn); // +7 st: real splices
renderVoice(off, 67, w, 6000, outOff);
for (AudioSample v : outOn) CHECK(std::isfinite(v));
CHECK(hashStream(outOn) != hashStream(outOff)); // the detected period actually moved the render
}
int main() {
testDetectedPeriodReachesAndMovesThePreserveRender();
if (g_fail == 0) {
std::printf("all period_render_integration tests passed\n");
return 0;
}
std::printf("%d period_render_integration check(s) failed\n", g_fail);
return 1;
}