instrument: one staged-envelope system — per-segment curves, the sustain-less AHD, and a shared overlay for all three envelopes

Trigger's fade pair folds into the AHD (and goes live); the release anchors right;
Preserve rings its synthetic tail out instead of cutting it. Payload v10.
This commit is contained in:
2026-07-31 08:37:57 -04:00
parent 87d7ceb066
commit 13e8c5c4d9
51 changed files with 3406 additions and 1812 deletions
+4 -12
View File
@@ -1,8 +1,7 @@
// trigger_seam — converts Trigger fade lengths between the engine domain (TriggerParams:
// SOURCE FRAMES, anchored to the source-timeline read pointer) and the overlay domain
// (AmpEnvelope: FRACTIONS in [0,1] of the played span, so the drawn shape stays invariant
// across sample-rate changes). Owns the one shared pack/unpack formula so both directions
// stay consistent; reasampler_editor calls these from packEnvelope/unpackEnvelope.
// trigger_seam — the shared Trigger play-span formula: how the stored %-length becomes the
// source-frame span the voice plays and the overlay draws over. One home so the engine's
// note-on resolve and the editor's overlay pack cannot disagree about where a Trigger note
// ends.
//
// playLengthFrames = round(lengthFraction * (frameCount - startFrame))
@@ -19,11 +18,4 @@ std::int64_t triggerPlayLength(double lengthFraction,
std::int64_t frameCount,
std::int64_t startFrame);
// PACK direction (draw path): frames -> fraction of play span. Not clamped here — the
// caller clamps to [0,1] when filling AmpEnvelope (envelope_edit owns that logic).
double framesToFadeFraction(std::int64_t fadeFrames, std::int64_t playLength);
// UNPACK direction (commit path): fraction -> nearest source frame.
std::int64_t fadeFractionToFrames(double fadeFraction, std::int64_t playLength);
} // namespace reasampler::instrument::map