Γ-W1-T7: make Preserve's splices pitch-synchronous — the jump is a whole number of the source's own period, detected once at load

30 Hz out-of-band energy 15.45% -> 0.00%; the 29 Hz rate-2.0 detune -133 -> +0 cents.
An unknown period keeps the fixed-window geometry bit for bit. The detector cannot
reach process(): sampler_core does not link it.
This commit is contained in:
2026-08-01 23:19:16 -04:00
parent 163ab11e05
commit 93230208ff
17 changed files with 1085 additions and 137 deletions
+7
View File
@@ -3,6 +3,8 @@
#include "core/instrument/map/sample_map.h"
#include "core/instrument/engine/period_detect.h" // the load-time Preserve source period
#include <algorithm> // std::remove_if
#include <cassert> // assert
#include <utility> // std::move
@@ -325,6 +327,11 @@ SampleData buildSampleData(const ResolvedCapture& resolved, DecodedPcm decoded)
// Resolve the stored wall-clock SECONDS (AHDSR, pitch env A/D) to frames at THIS WAV's
// actual rate; source-timeline params (trigger %-length + fades, start) carry through.
data.play = resolvePlay(resolved.play, data.sampleRate);
// The one place Preserve's source period is computed: the load, off the audio thread.
// Channel 0 only — a stereo pair's two channels share a fundamental, and the splice
// schedule is linked across them anyway.
data.sourcePeriodFrames =
instrument::engine::detectPeriod(data.frames, data.sampleRate).frames;
return data;
}