instrument: latch the note done at the read-head run-off, fit the migrated fades, and lift the curve dial and overlay selection into pure modules

This commit is contained in:
2026-07-31 09:17:04 -04:00
parent 13e8c5c4d9
commit d60ab1524a
18 changed files with 575 additions and 129 deletions
+5 -3
View File
@@ -61,15 +61,17 @@ void putAhd(std::vector<std::uint8_t>& out, const AhdSeconds& a) {
}
// THE lift of the retired Trigger fade pair onto the AHD that replaced it: Attack takes the
// fade-in, Decay the fade-out, Hold the whole remainder — so a zero fade-out lands Decay = 0
// and the abrupt end an old instance could express stays representable. The fades were SOURCE
// frames and the AHD stores wall-clock seconds, so the conversion goes through the same
// project rate the v3 lift already uses. A v10-or-newer blob overwrites this from its own tail.
// and the abrupt end an old instance could express stays representable. The seconds conversion
// and its rate-mismatch bound, and the two fitted exponents, are documented in
// component_state_io.h. A v10-or-newer blob overwrites all five fields from its own tail.
void liftTriggerFades(std::int64_t fadeInFrames, std::int64_t fadeOutFrames, double projectRate,
AhdSeconds& out) {
const double rate = projectRate > 0.0 ? projectRate : 1.0;
out.attackSeconds = static_cast<double>(fadeInFrames > 0 ? fadeInFrames : 0) / rate;
out.decaySeconds = static_cast<double>(fadeOutFrames > 0 ? fadeOutFrames : 0) / rate;
out.holdFraction = 1.0;
out.attackCurve = kTriggerFadeLiftAttackCurve;
out.decayCurve = kTriggerFadeLiftDecayCurve;
}
// Read the play tail (v5 shape onward) into `p`. Shared by the legacy zone reader and the