Measure Preserve's splice-alignment geometry on low-frequency material
A splice can only relocate by [0.75, 1.25]*window, so periods with no multiple in that interval never phase-align — at 50 ms, f < 16 Hz and 26.7-32 Hz. Harness runs by hand; too slow to gate.
This commit is contained in:
@@ -50,6 +50,16 @@ reasampler_test(live_delivery LINK sampler_core)
|
||||
# both mode shapes share, and the Trigger tail's terminal behaviour.
|
||||
reasampler_test(staged_envelopes LINK sampler_core)
|
||||
|
||||
# Measurement harness for Preserve on low-frequency material: how the splice search's
|
||||
# reachable relocation interval interacts with a long source period. Written longhand and
|
||||
# deliberately NOT add_test()'d — it sweeps frequencies, windows and spectra and takes ~2m40s
|
||||
# in Debug, which does not belong in a gate whose other targets run in seconds. It still
|
||||
# builds with everything else, so it cannot rot into non-compilation. Run it by hand, in
|
||||
# Release, when the question is what Preserve does to a given frequency.
|
||||
add_executable(preserve_low_frequency_tests
|
||||
${REASAMPLER_TESTS_DIR}/test_preserve_low_frequency.cpp)
|
||||
target_link_libraries(preserve_low_frequency_tests PRIVATE sampler_core)
|
||||
|
||||
# The Preserve read's source-feed schedule — the TIME half beside pitch_shift's PITCH half.
|
||||
# Header-only (it sits on the per-sample feed), hence INTERFACE.
|
||||
add_library(time_stretch INTERFACE)
|
||||
|
||||
@@ -27,6 +27,21 @@ namespace reasampler::instrument::engine {
|
||||
// -24 st is reachable from the Pitch knob alone. (The pre-stretch rate-1.0 engine's floor by
|
||||
// the same inequality is P > 735, ~60 Hz — what this range raises the floor from, not what
|
||||
// it removes.)
|
||||
//
|
||||
// A SECOND, INDEPENDENT limit binds the same material, and no rate bound touches it. A splice
|
||||
// relocates the tap by the nominal window refined by a search over +/- window/4, so the
|
||||
// reachable relocation distances are exactly [0.75, 1.25] * window; a phase-aligned splice
|
||||
// needs a WHOLE NUMBER of source periods inside that one interval. The interval is 0.5*window
|
||||
// wide, so any period <= window/2 always has a multiple in it — but above that, coverage
|
||||
// breaks into disjoint bands (n=1 covers periods [0.75, 1.25]*window, n=2 covers
|
||||
// [0.375, 0.625]*window) and the gap between them is reachable by nothing. Because both the
|
||||
// interval and the period scale with the sample rate, the unalignable set is fixed in Hz by
|
||||
// the window's MILLISECONDS: at 50 ms that is f < 16 Hz and 26.7 Hz < f < 32 Hz. Measured
|
||||
// (Release, 44.1k and 48k) at 30 Hz: the rendered pitch stays correct, but energy outside the
|
||||
// fundamental is 3.6% at +2 st / rate 1.0 and 15.5% at rate 2.0, against 0.00% at 34 Hz under
|
||||
// identical conditions; at 29 Hz / rate 2.0 the tone itself lands 7.4% flat. Unlike the
|
||||
// cadence inequality above, this one is not about how OFTEN a splice fires — a window of at
|
||||
// least two source periods removes it outright, and nothing else does.
|
||||
inline constexpr double kStretchRateMin = 0.5;
|
||||
inline constexpr double kStretchRateMax = 2.0;
|
||||
inline constexpr int kMaxFeedPerFrame = 2; // ceil(kStretchRateMax)
|
||||
|
||||
Reference in New Issue
Block a user