feat(params): add parameters, macros, RAVE controls and resources

This commit is contained in:
2026-09-08 14:55:22 +02:00
parent a9abca9e15
commit 0a94208d0f
12 changed files with 1198 additions and 0 deletions
+362
View File
@@ -0,0 +1,362 @@
#pragma once
#include <JuceHeader.h>
// ===========================================================================
// Central registry of parameter IDs, enums and mapping helpers for SerumAlt.
// Every audio parameter (APVTS) and every modulation destination is declared
// here so that the DSP engine, the mod matrix and the GUI share one source of
// truth.
// ===========================================================================
namespace serum
{
// ---------------------------------------------------------------------------
// Parameter IDs (APVTS)
// ---------------------------------------------------------------------------
namespace ids
{
// Global
inline constexpr const char* master = "master";
inline constexpr const char* uiScale = "uiScale";
inline constexpr const char* rave = "rave";
// Oscillator A / B
inline constexpr const char* oscAOn = "oscAOn";
inline constexpr const char* oscAWave = "oscAWave";
inline constexpr const char* oscAWtPos = "oscAWtPos";
inline constexpr const char* oscAWarp = "oscAWarp";
inline constexpr const char* oscAWarpAmt = "oscAWarpAmt";
inline constexpr const char* oscACoarse = "oscACoarse";
inline constexpr const char* oscAFine = "oscAFine";
inline constexpr const char* oscALevel = "oscALevel";
inline constexpr const char* oscAPan = "oscAPan";
inline constexpr const char* oscAUnison = "oscAUnison";
inline constexpr const char* oscADetune = "oscADetune";
inline constexpr const char* oscASpread = "oscASpread";
inline constexpr const char* oscAPhase = "oscAPhase";
inline constexpr const char* oscARandPh = "oscARandPh";
inline constexpr const char* oscBOn = "oscBOn";
inline constexpr const char* oscBWave = "oscBWave";
inline constexpr const char* oscBWtPos = "oscBWtPos";
inline constexpr const char* oscBWarp = "oscBWarp";
inline constexpr const char* oscBWarpAmt = "oscBWarpAmt";
inline constexpr const char* oscBCoarse = "oscBCoarse";
inline constexpr const char* oscBFine = "oscBFine";
inline constexpr const char* oscBLevel = "oscBLevel";
inline constexpr const char* oscBPan = "oscBPan";
inline constexpr const char* oscBUnison = "oscBUnison";
inline constexpr const char* oscBDetune = "oscBDetune";
inline constexpr const char* oscBSpread = "oscBSpread";
inline constexpr const char* oscBPhase = "oscBPhase";
inline constexpr const char* oscBRandPh = "oscBRandPh";
// Sub oscillator
inline constexpr const char* subOn = "subOn";
inline constexpr const char* subShape = "subShape";
inline constexpr const char* subOct = "subOct";
inline constexpr const char* subLevel = "subLevel";
// Noise
inline constexpr const char* noiseOn = "noiseOn";
inline constexpr const char* noiseType = "noiseType";
inline constexpr const char* noiseLevel = "noiseLevel";
// Filters
inline constexpr const char* f1On = "f1On";
inline constexpr const char* f1Type = "f1Type";
inline constexpr const char* f1Cutoff = "f1Cutoff";
inline constexpr const char* f1Res = "f1Res";
inline constexpr const char* f1Drive = "f1Drive";
inline constexpr const char* f1Key = "f1Key";
inline constexpr const char* f1Slope = "f1Slope";
inline constexpr const char* f2On = "f2On";
inline constexpr const char* f2Type = "f2Type";
inline constexpr const char* f2Cutoff = "f2Cutoff";
inline constexpr const char* f2Res = "f2Res";
inline constexpr const char* f2Drive = "f2Drive";
inline constexpr const char* f2Key = "f2Key";
inline constexpr const char* f2Slope = "f2Slope";
inline constexpr const char* fRoute = "fRoute";
inline constexpr const char* fMix = "fMix";
inline constexpr const char* fOut = "fOut";
// Envelopes 1..4
inline constexpr const char* env1A = "env1A";
inline constexpr const char* env1D = "env1D";
inline constexpr const char* env1S = "env1S";
inline constexpr const char* env1R = "env1R";
inline constexpr const char* env1Curve = "env1Curve";
inline constexpr const char* env2A = "env2A";
inline constexpr const char* env2D = "env2D";
inline constexpr const char* env2S = "env2S";
inline constexpr const char* env2R = "env2R";
inline constexpr const char* env2Curve = "env2Curve";
inline constexpr const char* env3A = "env3A";
inline constexpr const char* env3D = "env3D";
inline constexpr const char* env3S = "env3S";
inline constexpr const char* env3R = "env3R";
inline constexpr const char* env3Curve = "env3Curve";
inline constexpr const char* env4A = "env4A";
inline constexpr const char* env4D = "env4D";
inline constexpr const char* env4S = "env4S";
inline constexpr const char* env4R = "env4R";
inline constexpr const char* env4Curve = "env4Curve";
// LFOs 1..4
inline constexpr const char* lfo1Rate = "lfo1Rate";
inline constexpr const char* lfo1Sync = "lfo1Sync";
inline constexpr const char* lfo1Beat = "lfo1Beat";
inline constexpr const char* lfo1Shape = "lfo1Shape";
inline constexpr const char* lfo1Phase = "lfo1Phase";
inline constexpr const char* lfo1Fade = "lfo1Fade";
inline constexpr const char* lfo1Delay = "lfo1Delay";
inline constexpr const char* lfo2Rate = "lfo2Rate";
inline constexpr const char* lfo2Sync = "lfo2Sync";
inline constexpr const char* lfo2Beat = "lfo2Beat";
inline constexpr const char* lfo2Shape = "lfo2Shape";
inline constexpr const char* lfo2Phase = "lfo2Phase";
inline constexpr const char* lfo2Fade = "lfo2Fade";
inline constexpr const char* lfo2Delay = "lfo2Delay";
inline constexpr const char* lfo3Rate = "lfo3Rate";
inline constexpr const char* lfo3Sync = "lfo3Sync";
inline constexpr const char* lfo3Beat = "lfo3Beat";
inline constexpr const char* lfo3Shape = "lfo3Shape";
inline constexpr const char* lfo3Phase = "lfo3Phase";
inline constexpr const char* lfo3Fade = "lfo3Fade";
inline constexpr const char* lfo3Delay = "lfo3Delay";
inline constexpr const char* lfo4Rate = "lfo4Rate";
inline constexpr const char* lfo4Sync = "lfo4Sync";
inline constexpr const char* lfo4Beat = "lfo4Beat";
inline constexpr const char* lfo4Shape = "lfo4Shape";
inline constexpr const char* lfo4Phase = "lfo4Phase";
inline constexpr const char* lfo4Fade = "lfo4Fade";
inline constexpr const char* lfo4Delay = "lfo4Delay";
// FX slots (8)
inline constexpr const char* fx1Type = "fx1Type";
inline constexpr const char* fx1Mix = "fx1Mix";
inline constexpr const char* fx1P1 = "fx1P1";
inline constexpr const char* fx1P2 = "fx1P2";
inline constexpr const char* fx1P3 = "fx1P3";
inline constexpr const char* fx1P4 = "fx1P4";
inline constexpr const char* fx2Type = "fx2Type";
inline constexpr const char* fx2Mix = "fx2Mix";
inline constexpr const char* fx2P1 = "fx2P1";
inline constexpr const char* fx2P2 = "fx2P2";
inline constexpr const char* fx2P3 = "fx2P3";
inline constexpr const char* fx2P4 = "fx2P4";
inline constexpr const char* fx3Type = "fx3Type";
inline constexpr const char* fx3Mix = "fx3Mix";
inline constexpr const char* fx3P1 = "fx3P1";
inline constexpr const char* fx3P2 = "fx3P2";
inline constexpr const char* fx3P3 = "fx3P3";
inline constexpr const char* fx3P4 = "fx3P4";
inline constexpr const char* fx4Type = "fx4Type";
inline constexpr const char* fx4Mix = "fx4Mix";
inline constexpr const char* fx4P1 = "fx4P1";
inline constexpr const char* fx4P2 = "fx4P2";
inline constexpr const char* fx4P3 = "fx4P3";
inline constexpr const char* fx4P4 = "fx4P4";
inline constexpr const char* fx5Type = "fx5Type";
inline constexpr const char* fx5Mix = "fx5Mix";
inline constexpr const char* fx5P1 = "fx5P1";
inline constexpr const char* fx5P2 = "fx5P2";
inline constexpr const char* fx5P3 = "fx5P3";
inline constexpr const char* fx5P4 = "fx5P4";
inline constexpr const char* fx6Type = "fx6Type";
inline constexpr const char* fx6Mix = "fx6Mix";
inline constexpr const char* fx6P1 = "fx6P1";
inline constexpr const char* fx6P2 = "fx6P2";
inline constexpr const char* fx6P3 = "fx6P3";
inline constexpr const char* fx6P4 = "fx6P4";
inline constexpr const char* fx7Type = "fx7Type";
inline constexpr const char* fx7Mix = "fx7Mix";
inline constexpr const char* fx7P1 = "fx7P1";
inline constexpr const char* fx7P2 = "fx7P2";
inline constexpr const char* fx7P3 = "fx7P3";
inline constexpr const char* fx7P4 = "fx7P4";
inline constexpr const char* fx8Type = "fx8Type";
inline constexpr const char* fx8Mix = "fx8Mix";
inline constexpr const char* fx8P1 = "fx8P1";
inline constexpr const char* fx8P2 = "fx8P2";
inline constexpr const char* fx8P3 = "fx8P3";
inline constexpr const char* fx8P4 = "fx8P4";
// Macros 1..4
inline constexpr const char* macro1 = "macro1";
inline constexpr const char* macro2 = "macro2";
inline constexpr const char* macro3 = "macro3";
inline constexpr const char* macro4 = "macro4";
}
// ---------------------------------------------------------------------------
// Enums
// ---------------------------------------------------------------------------
enum class WarpMode : int { None = 0, BendPlus, BendMinus, Sync, PWM, Asym, Mirror, Fold, Count };
enum class SubShape : int { Sine = 0, Triangle, Count };
enum class NoiseType : int { White = 0, Pink, Count };
enum class FilterModel: int { LadderLP = 0, LadderHP, LadderBP, Diode, Comb, Formant, Screamer, Count };
enum class FilterRoute: int { Serial = 0, Parallel, Split, Count };
enum class LfoShape : int { Sine = 0, Triangle, Saw, Square, SampleHold, StepSeq, Freehand, Count };
enum class FxType : int { Off = 0, Hyper, Chorus, Flanger, Phaser, Distortion, EQ, Compressor, Delay, Reverb, Count };
inline constexpr int kNumOscillators = 2;
inline constexpr int kNumEnvelopes = 4;
inline constexpr int kNumLfos = 4;
inline constexpr int kNumMacros = 4;
inline constexpr int kNumFxSlots = 8;
inline constexpr int kMaxUnison = 16;
inline constexpr int kNumVoices = 32;
// ---------------------------------------------------------------------------
// Modulation sources / destinations
// ---------------------------------------------------------------------------
enum class ModSource : int
{
Lfo1 = 0, Lfo2, Lfo3, Lfo4,
Env1, Env2, Env3, Env4,
Velocity, Note, ModWheel, PitchBend,
Macro1, Macro2, Macro3, Macro4,
Random,
Count
};
enum class ModTarget : int
{
None = -1,
Master = 0,
Pitch,
Amp,
OscALevel, OscAPan, OscAWtPos, OscAUnison, OscADetune, OscASpread, OscAWarpAmt,
OscBLevel, OscBPan, OscBWtPos, OscBUnison, OscBDetune, OscBSpread, OscBWarpAmt,
SubLevel, NoiseLevel,
Filter1Cutoff, Filter1Res, Filter1Drive,
Filter2Cutoff, Filter2Res, Filter2Drive,
FilterMix, FilterOut,
Fx1Mix, Fx2Mix, Fx3Mix, Fx4Mix, Fx5Mix, Fx6Mix, Fx7Mix, Fx8Mix,
Count
};
inline constexpr int kNumModTargets = (int) ModTarget::Count;
inline constexpr int kNumModSources = (int) ModSource::Count;
// Is a given source per-voice (i.e. needs a value for each voice)?
inline bool isPerVoiceSource (ModSource s)
{
switch (s)
{
case ModSource::Env1: case ModSource::Env2:
case ModSource::Env3: case ModSource::Env4:
case ModSource::Velocity: case ModSource::Note:
case ModSource::Random: return true;
default: return false;
}
}
// Does a source already span -1..1 (bipolar range)?
inline bool isBipolarSource (ModSource s)
{
return (s >= ModSource::Lfo1 && s <= ModSource::Lfo4) || s == ModSource::PitchBend;
}
// Is a given target a per-voice parameter?
inline bool isPerVoiceTarget (ModTarget t)
{
switch (t)
{
case ModTarget::Master:
case ModTarget::FilterMix: case ModTarget::FilterOut:
case ModTarget::Fx1Mix: case ModTarget::Fx2Mix:
case ModTarget::Fx3Mix: case ModTarget::Fx4Mix:
case ModTarget::Fx5Mix: case ModTarget::Fx6Mix:
case ModTarget::Fx7Mix: case ModTarget::Fx8Mix:
return false;
default:
return true;
}
}
juce::String modSourceName (ModSource s);
juce::String modTargetName (ModTarget t);
juce::String modTargetParamId(ModTarget t); // APVTS param id for the target
ModTarget modTargetFromParamId (const juce::String& id);
ModSource modSourceFromString (const juce::String& s);
juce::String modSourceToString (ModSource s);
juce::String modTargetToString (ModTarget t);
ModTarget modTargetFromString (const juce::String& s);
// ---------------------------------------------------------------------------
// Mapping helpers (raw 0..1 <-> physical units)
// ---------------------------------------------------------------------------
namespace maps
{
// Envelope times: 0..1 -> 0.5ms .. 12s (cubic taper for fine control at short times)
inline float toSeconds (float x) { return 0.0005f + std::pow (juce::jlimit (0.0f, 1.0f, x), 3.0f) * 12.0f; }
inline float fromSeconds (float s) { return std::pow (juce::jlimit (0.0005f, 12.0f, s) / 12.0f, 1.0f / 3.0f); }
// Cutoff: 0..1 -> 20Hz .. 20kHz (log)
inline float cutoffToHz (float x) { return 20.0f * std::pow (1000.0f, juce::jlimit (0.0f, 1.0f, x)); }
inline float hzToCutoff (float hz) { return std::log (juce::jlimit (20.0f, 20000.0f, hz) / 20.0f) / std::log (1000.0f); }
// LFO rate: 0..1 -> 0.02Hz .. 30Hz (log)
inline float rateToHz (float x) { return 0.02f * std::pow (1500.0f, juce::jlimit (0.0f, 1.0f, x)); }
inline float hzToRate (float hz) { return std::log (juce::jlimit (0.02f, 30.0f, hz) / 0.02f) / std::log (1500.0f); }
// LFO beat division: 0..1 -> 1/32 .. 4 bars (log stepped)
inline float beatToMultiplier (float x)
{
// 0 -> 1/32, 0.5 -> 1/4, 1 -> 4 bars
static constexpr float divisions[16] =
{
1.0f/32.0f, 1.0f/16.0f, 1.0f/8.0f, 1.0f/6.0f, 1.0f/4.0f, 1.0f/3.0f,
1.0f/2.0f, 1.0f, 3.0f/2.0f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 12.0f, 16.0f
};
const int idx = juce::jlimit (0, 15, (int) std::llround (x * 15.0f));
return divisions[idx];
}
// FX delay time: 0..1 -> 1ms .. 2000ms (log)
inline float delayToMs (float x) { return 1.0f * std::pow (2000.0f, juce::jlimit (0.0f, 1.0f, x)); }
inline float msToDelay (float ms) { return std::log (juce::jlimit (1.0f, 2000.0f, ms)) / std::log (2000.0f); }
// Reverb size: 0..1 -> 0.2 .. 0.99
inline float sizeToValue (float x) { return 0.2f + juce::jlimit (0.0f, 1.0f, x) * 0.79f; }
}
// ---------------------------------------------------------------------------
// Factory wavetable names (index == oscWave param value)
// ---------------------------------------------------------------------------
inline const char* const kWavetableNames[] =
{
"Basic Shapes",
"Saw PWM",
"Square Sync",
"Triangle Fold",
"Vowel",
"Organ",
"Warm Saw",
"Digital",
"Glass",
"Bass"
};
inline constexpr int kNumWavetables = 10;
} // namespace serum