Fix spline-drag rollback, bake contour leak, held-note live miss, amp clamp
Editor close mid-drag now rolls back published contours like capture-loss does; bake detaches liveContours so a printed capture can't observe a live drag; a held note now receives a live publish that lands in the same block as a note-on; amp spline read clamped to [0,1].
This commit is contained in:
@@ -1167,6 +1167,38 @@ static void testVelocityGainSurvivesAHostilePublishThatReallyLands() {
|
||||
CHECK(proportional);
|
||||
}
|
||||
|
||||
// A note-on that lands in the same block boundary as a publish must not let the already-
|
||||
// sounding voice miss it: startVoice used to call refreshLive() bare, which consumes the
|
||||
// generation stamp without applying it to the voices already active — a held note that shared
|
||||
// a block with a note-on then never saw the publish at all (not merely delayed a block).
|
||||
static void testHeldVoiceReceivesALivePublishThatCoincidesWithANoteOn() {
|
||||
SampleData s;
|
||||
s.frames.assign(200000, 1.0f); // DC: the envelope alone shapes the output
|
||||
s.sampleRate = kRate;
|
||||
s.rootNote = 60;
|
||||
s.play.adsr.attackFrames = 0;
|
||||
s.play.adsr.sustainLevel = 1.0;
|
||||
s.play.adsr.releaseFrames = 480000; // long enough that release never intrudes
|
||||
|
||||
LiveParams block;
|
||||
s.live = █
|
||||
VoiceEngine engine(2, s);
|
||||
engine.noteOn(60, 100); // voice A, sustaining at the dialed 1.0
|
||||
|
||||
LiveValues quieter = foldLive(s.play, s.keyTrack);
|
||||
quieter.adsr.sustainLevel = 0.2;
|
||||
block.publish(quieter);
|
||||
|
||||
engine.noteOn(61, 100); // voice B starts in the SAME generation as the publish
|
||||
|
||||
std::vector<AudioSample> out;
|
||||
for (int i = 0; i < 20; ++i) engine.render(out, 512); // let voice A's glide settle
|
||||
|
||||
// Both voices settle at 0.2 — a held voice that missed the publish would still sit at 1.0,
|
||||
// for a combined 1.2 rather than 0.4.
|
||||
CHECK(std::fabs(static_cast<double>(out.back()) - 0.4) < 0.01);
|
||||
}
|
||||
|
||||
int main() {
|
||||
testStageDurationChangeHoldsPhase();
|
||||
testShortenedStageStillLandsContinuously();
|
||||
@@ -1189,6 +1221,7 @@ int main() {
|
||||
testAPublishedPitchOffsetRefitsThePitchEnvelopeSpan();
|
||||
testPitchRatioAndVelocityGainStayLatched();
|
||||
testVelocityGainSurvivesAHostilePublishThatReallyLands();
|
||||
testHeldVoiceReceivesALivePublishThatCoincidesWithANoteOn();
|
||||
if (g_fail == 0) std::printf("live_delivery tests passed\n");
|
||||
return g_fail == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user