instrument: fix AHD node-tracking/tie-break/live-latch defects and close staged-envelope-curve test gaps
This commit is contained in:
@@ -474,6 +474,62 @@ static void testEveryEnvelopeStageTimeAndLevelMovesTheSoundingNote() {
|
||||
s.play.pitchEnv.peakSemitones = 12.0;
|
||||
},
|
||||
[](LiveValues& v) { v.pitchEnv.peakSemitones = 0.0; }, -1},
|
||||
// A small hold that finishes the envelope well inside the render window (Hold ends at
|
||||
// frame ~5090, comfortably short of the window) vs. a live move that opens the hold out
|
||||
// near the whole span: with the fraction alone unmoved, the boundary the two renders
|
||||
// cross (or don't) inside the observed tail is what makes this audible, not a level
|
||||
// change — Hold's own output is flat regardless of exactly where inside it pos_ sits.
|
||||
{"pitch env hold fraction",
|
||||
[](SampleData& s) {
|
||||
s.play.pitchEnv.enabled = true;
|
||||
s.play.pitchEnv.peakSemitones = 12.0;
|
||||
s.play.pitchEnv.shape.attackFrames = 100;
|
||||
s.play.pitchEnv.shape.decayFrames = 100;
|
||||
s.play.pitchEnv.shape.holdFraction = 0.05;
|
||||
},
|
||||
[](LiveValues& v) { v.pitchEnv.shape.holdFraction = 1.0; }, -1},
|
||||
|
||||
// The Trigger AHDs — Voice::applyLive's ampAhd_/filterAhd_ branches, otherwise
|
||||
// unexercised by this table (every case above is Gate/AdsrEnvelope).
|
||||
{"trigger amp attack (AHD)",
|
||||
[](SampleData& s) {
|
||||
s.play.playMode = PlayMode::Trigger;
|
||||
s.play.trigger.lengthFraction = 1.0;
|
||||
s.play.trigAhd.attackFrames = 48000;
|
||||
},
|
||||
[](LiveValues& v) { v.ampAhd.attackFrames = 4000; }, -1},
|
||||
{"trigger filter attack (AHD)",
|
||||
[](SampleData& s) {
|
||||
s.play.playMode = PlayMode::Trigger;
|
||||
s.play.trigger.lengthFraction = 1.0;
|
||||
filterSweep(s);
|
||||
s.play.filter.trigEnv.attackFrames = 48000;
|
||||
},
|
||||
[](LiveValues& v) { v.filterAhd.attackFrames = 4000; }, -1},
|
||||
|
||||
// One curve exponent per envelope (amp/pitch/filter), reusing each envelope's own
|
||||
// attack/decay rig above so only the mutated field differs.
|
||||
{"amp attack curve",
|
||||
[](SampleData& s) { s.play.adsr.attackFrames = 48000; },
|
||||
[](LiveValues& v) { v.adsr.attackCurve = 5.0; }, -1},
|
||||
{"amp release curve",
|
||||
[](SampleData& s) { s.play.adsr.releaseFrames = 48000; },
|
||||
[](LiveValues& v) { v.adsr.releaseCurve = 5.0; }, 2},
|
||||
{"pitch env attack curve",
|
||||
[](SampleData& s) {
|
||||
s.play.pitchEnv.enabled = true;
|
||||
s.play.pitchEnv.shape.attackFrames = 48000;
|
||||
s.play.pitchEnv.shape.decayFrames = 48000;
|
||||
s.play.pitchEnv.peakSemitones = 12.0;
|
||||
},
|
||||
[](LiveValues& v) { v.pitchEnv.shape.attackCurve = 5.0; }, -1},
|
||||
{"filter env decay curve",
|
||||
[](SampleData& s) {
|
||||
filterSweep(s);
|
||||
s.play.filter.env.decayFrames = 48000;
|
||||
s.play.filter.env.sustainLevel = 0.0;
|
||||
},
|
||||
[](LiveValues& v) { v.filterEnv.decayCurve = 5.0; }, -1},
|
||||
};
|
||||
for (const Case& c : cases) {
|
||||
assertLiveFieldMovesTheSoundingNote(c.name, c.rig, c.mutate, c.noteOffBlock);
|
||||
|
||||
Reference in New Issue
Block a user