instrument: spline EGs — hard points on the one shared spline, a drawn contour per envelope beside its staged state, payload v13
This commit is contained in:
@@ -72,6 +72,26 @@ void Voice::start(int note, int velocity, const SampleData& sample, bool declick
|
||||
loop_ = instrument::engine::loop::resolveLoop(sample.loop, sample.loopCrossfadeFrames,
|
||||
frameCount, playMode_ == PlayMode::Gate);
|
||||
|
||||
// Bind whichever EGs are drawn. Rebound on EVERY note-on rather than cached: a reload hands
|
||||
// the engine a fresh SampleData, so a stale pointer into the previous one is the bug this
|
||||
// avoids. A Staged EG clears its cursor, which is what keeps the per-sample path off the
|
||||
// spline branch entirely.
|
||||
splineScale_ = frameCount > 0 ? 1.0 / static_cast<double>(frameCount) : 0.0;
|
||||
if (p.ampSpline.mode == EnvMode::Spline) ampSplineCur_.bind(p.ampSpline.contour);
|
||||
else ampSplineCur_.clear();
|
||||
if (p.pitchEnv.enabled && p.pitchSpline.mode == EnvMode::Spline) {
|
||||
pitchSplineCur_.bind(p.pitchSpline.contour);
|
||||
pitchSplineDepth_ = p.pitchEnv.peakSemitones;
|
||||
} else {
|
||||
pitchSplineCur_.clear();
|
||||
pitchSplineDepth_ = 0.0;
|
||||
}
|
||||
if (p.filter.enabled && p.filterSpline.mode == EnvMode::Spline) {
|
||||
filterSplineCur_.bind(p.filterSpline.contour);
|
||||
} else {
|
||||
filterSplineCur_.clear();
|
||||
}
|
||||
|
||||
// Amplitude envelope: Gate = AHDSR (all five fields read from play.adsr, resolved to
|
||||
// frames from stored seconds at load time); Trigger = the staged AHD over the % play span.
|
||||
const std::int64_t postStart = frameCount - start; // >= 1 (start clamped < frameCount)
|
||||
|
||||
Reference in New Issue
Block a user