instrument: one VELOCITY deck for all three velocity curves, bipolar and off by default for pitch and filter

Payload v12 appends the new velocity->pitch curve and folds the retired filter velAmount into its now-bipolar curve, so pre-v12 projects reopen sounding identical. Preview button takes a drawn play triangle.
This commit is contained in:
2026-07-31 19:15:17 -04:00
parent 4fecb58c0a
commit 9d38f87a2d
37 changed files with 1020 additions and 320 deletions
+11 -2
View File
@@ -48,6 +48,14 @@ inline double keyTrackedRatio(int note, int rootNote, double keyTrack) {
return std::pow(2.0, semis / 12.0);
}
// 2^(curve(velocity) * kVelocityPitchRangeSemitones / 12): the velocity->pitch transpose, which
// the voice folds into baseRatio_ once at note-on. A curve flat at 0 — the default — yields
// EXACTLY 1.0 at every velocity and skips the pow, so an undrawn curve transposes nothing.
inline double velocityPitchRatio(const VelocityCurve& curve, int velocity) {
const double semis = curve.eval(static_cast<double>(velocity)) * kVelocityPitchRangeSemitones;
return (semis == 0.0) ? 1.0 : std::pow(2.0, semis / 12.0);
}
// One octave expressed in the cutoff control's normalized domain, read out of the filter
// module's OWN inverse rather than re-derived from its endpoints — the log law belongs to
// filter_params, and a second copy here could drift from it. Evaluated at note-on only.
@@ -561,7 +569,8 @@ private:
bool releasing_ = false;
int note_ = 0;
double velocityGain_ = 1.0;
double baseRatio_ = 1.0; // 2^((note-root)/12): the un-modulated repitch ratio
double baseRatio_ = 1.0; // key-tracked repitch ratio, with velocity->pitch folded in
double velPitchRatio_ = 1.0; // the velocity->pitch factor alone; retune re-applies it
double ratio_ = 1.0; // fractional source frames advanced per output frame (this frame)
double readPos_ = 0.0; // fractional frame index into the sample
const SampleData* sample_ = nullptr;
@@ -593,7 +602,7 @@ private:
double filterRate_ = 0.0;
double filterCutoffNorm_ = 1.0;
double filterModAmount_ = 0.0;
double filterVelOffset_ = 0.0; // velAmount * velocityCurve.eval(velocity), fixed per note
double filterVelOffset_ = 0.0; // velocityCurve.eval(velocity), fixed per note
double filterKeyTrack_ = 0.0;
instrument::engine::filter::FilterSettings filterSettings_{}; // the note's tone controls
float filterBaseCutoff_ = 1.0f; // cutoff before the envelope, clamped