Bake window derives itself: %-knob fold, declick pad, Gate held to exhaustion, preview velocity; Hold is the one knob a loop needs

This commit is contained in:
2026-08-01 20:26:04 -04:00
parent d3894dae6d
commit 19aeb92775
36 changed files with 1040 additions and 274 deletions
+7 -7
View File
@@ -6,6 +6,8 @@
#include <algorithm>
#include "core/instrument/map/trigger_seam.h" // effectiveLengthFraction (the one %-length rule)
namespace reasampler {
void Voice::presizePreserveShifters(std::int64_t windowFrames) {
@@ -101,13 +103,11 @@ void Voice::start(int note, int velocity, const SampleData& sample, bool declick
env_.noteOn();
playEnd_ = 0; // unused in Gate
} else {
// Trigger: play [start, playEnd) where
// playEnd = start + round(lengthFraction*(frames-start)) — except kTrigLength is INERT
// while any spline EG is active (splineActive, play_params.h): a contour is a pure
// function over the FULL sample length, so truncating playEnd_ to a %-length would
// hard-cut it mid-shape. The staged Trigger AHD below (trigSpan) plays the same full
// span in that case, matching the "drawn-but-dead" treatment of the other staged knobs.
double frac = splineActive(p) ? 1.0 : p.trigger.lengthFraction;
// Trigger: play [start, playEnd) where playEnd = start + round(frac*(frames-start)).
// The spline fold lives in effectiveLengthFraction (trigger_seam.h), which the bake's
// window derivation reads too — a second copy of it here is what let a stored-but-inert
// %-knob shorten the bake while the voice played the whole take.
double frac = instrument::map::effectiveLengthFraction(p);
if (frac <= 0.0) frac = 0.0; // %=0 -> zero play length (finishes immediately)
if (frac > 1.0) frac = 1.0;
std::int64_t playLen = static_cast<std::int64_t>(