fix: close review findings on spline EGs — engine, codec, and popup/overlay UI grammar
Live pitch depth, Gate/Spline enable-rule agreement, inert kTrigLength, NaN wire guards, hard-flag-tail corruption no longer wipes the record, RT/cold spline tie-break, retired alt-click, marker-shadow fix, plus new test coverage.
This commit is contained in:
@@ -102,8 +102,12 @@ void Voice::start(int note, int velocity, const SampleData& sample, bool declick
|
||||
playEnd_ = 0; // unused in Gate
|
||||
} else {
|
||||
// Trigger: play [start, playEnd) where
|
||||
// playEnd = start + round(lengthFraction*(frames-start)).
|
||||
double frac = p.trigger.lengthFraction;
|
||||
// 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;
|
||||
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>(
|
||||
@@ -258,6 +262,12 @@ void Voice::applyLive(const instrument::engine::LiveValues& live, bool snap) {
|
||||
else ampAhd_.applyLive(sourceOffset(), live.ampAhd);
|
||||
pitchEnv_.applyLive(live.pitchEnv);
|
||||
}
|
||||
// The pitch DEPTH knob stays live under a spline (core/instrument/CLAUDE.md), but
|
||||
// pitchSplineDepth_ is a plain member latched at note-on — unlike filter's modAmount_,
|
||||
// which already glides through rModAmount_'s live ramp regardless of spline state (below),
|
||||
// this is the one place a live pitch-depth move must be re-applied by hand. Only meaningful
|
||||
// while pitchSplineCur_ is bound; harmless (and cheap) to set otherwise.
|
||||
pitchSplineDepth_ = live.pitchEnv.peakSemitones;
|
||||
if (!filterOn_) return; // filter enable is a discrete toggle: it travels by reload
|
||||
|
||||
if (snap) {
|
||||
|
||||
Reference in New Issue
Block a user