rmx-19/Source/Params.cpp

251 lines
12 KiB
C++
Raw Normal View History

#include "Params.h"
#include "PresetBank.h"
namespace prm {
static const Desc table[num] = {
// id name short min max def disc fine coarse
{ "osc1wave", "OSC1 WAVE", "O1WV", 0, 14, 2, true, 1, 1 },
{ "osc2wave", "OSC2 WAVE", "O2WV", 0, 14, 3, true, 1, 1 },
{ "detune", "DETUNE 2", "DT2", -50, 50, 8, false, 1, 6 },
{ "oscmix", "OSC BAL", "MIX", 0, 100, 52, false, 1, 8 },
{ "flttype", "FILTER TYPE", "FTYP", 0, 3, 1, true, 1, 1 },
{ "fltcut", "CUTOFF", "CUT", 20, 20000, 3400, false, 20, 400 },
{ "fltres", "RESONANCE", "RES", 0, 0.98f, 0.18f, false, 0.01f, 0.08f },
{ "fltenv", "FILT ENV", "FEN", 0, 100, 52, false, 1, 8 },
{ "fltkey", "KEY TRACK", "KEY", 0, 100, 40, false, 1, 8 },
{ "ampA", "AMP ATTACK", "AAT", 0.001f, 6, 0.008f, false, 0.01f, 0.1f },
{ "ampD", "AMP DECAY", "ADE", 0.001f, 6, 0.26f, false, 0.01f, 0.1f },
{ "ampS", "AMP SUSTAIN", "ASUS", 0, 1, 0.70f, false, 0.01f, 0.08f },
{ "ampR", "AMP RELEASE", "AREL", 0.001f, 8, 0.35f, false, 0.01f, 0.1f },
{ "fenvA", "FENV ATTACK", "FAT", 0.001f, 6, 0.02f, false, 0.01f, 0.1f },
{ "fenvD", "FENV DECAY", "FDE", 0.001f, 6, 0.16f, false, 0.01f, 0.1f },
{ "fenvS", "FENV SUSTAIN", "FSUS", 0, 1, 0.26f, false, 0.01f, 0.08f },
{ "fenvR", "FENV RELEASE", "FRE", 0.001f, 8, 0.25f, false, 0.01f, 0.1f },
{ "lforate", "LFO RATE", "LFR", 0.02f, 22, 4.2f, false, 0.1f, 0.5f },
{ "lfoshape", "LFO SHAPE", "LFS", 0, 3, 0, true, 1, 1 },
{ "lfodepth", "LFO DEPTH", "LFD", 0, 1, 0.22f, false, 0.01f, 0.08f },
{ "lfotarget", "LFO TARGET", "LFT", 0, 2, 0, true, 1, 1 },
{ "fxtype", "FX TYPE", "FXT", 0, 7, 1, true, 1, 1 },
{ "fxamt", "FX DEPTH", "FXD", 0, 1, 0.30f, false, 0.01f, 0.08f },
{ "fxtime", "FX TIME", "FXT", 0.05f, 1.2f, 0.28f, false, 0.01f, 0.12f },
{ "vol", "MASTER VOL", "VOL", 0, 1, 0.85f, false, 0.01f, 0.08f },
{ "pan", "STEREO PAN", "PAN", -1, 1, 0, false, 0.02f, 0.2f },
{ "poly", "POLYPHONY", "POLY", 1, 16, 10, true, 1, 1 },
{ "glide", "PORTAMENTO", "GLD", 0, 2, 0, false, 0.02f, 0.2f },
{ "tune", "MASTER TUNE", "TUN", -12, 12, 0, true, 1, 1 },
{ "hq", "HQ MODE", "HQ", 0, 1, 0, true, 1, 1 },
2026-09-08 21:57:34 +02:00
{ "arpon", "ARP ON", "ARP", 0, 1, 0, true, 1, 1 },
{ "arprate", "ARP RATE", "ART", 0, 7, 2, true, 1, 1 },
{ "arppattern", "ARP PATTERN", "APT", 0, 3, 0, true, 1, 1 },
{ "arpoct", "ARP OCTAVES", "AOC", 1, 4, 1, true, 1, 1 },
{ "arpgate", "ARP GATE", "AGT", 10, 100, 70, false, 1, 10 },
{ "detune1", "DETUNE 1", "DT1", -50, 50, 0, false, 1, 6 },
{ "xmod", "CROSS MOD", "XML", 0, 3, 0, true, 1, 1 },
{ "xmix", "XMIX AMT", "XMX", 0, 1, 0, false, 0.01f, 0.08f },
{ "evolve", "EVOLVE", "EVO", 0, 1, 0, false, 0.01f, 0.08f },
{ "warp", "WARP", "WRP", 0, 1, 0, false, 0.01f, 0.08f },
{ "ctune1", "COARSE TUNE 1","CT1", -24, 24, 0, true, 1, 1 },
{ "ctune2", "COARSE TUNE 2","CT2", -24, 24, 0, true, 1, 1 },
};
const Desc& desc (Id id) { return table[static_cast<int>(id)]; }
bool validId (int i) { return i >= 0 && i < num; }
juce::AudioProcessorValueTreeState::ParameterLayout createLayout()
{
juce::AudioProcessorValueTreeState::ParameterLayout layout;
PresetBank bank;
const Patch& p0 = bank.get (0); // seed APVTS defaults with the first patch
for (int i = 0; i < num; ++i)
{
const Desc& d = table[i];
juce::NormalisableRange<float> r (d.min, d.max);
if (juce::String (d.id) == "fltcut")
r = juce::NormalisableRange<float> (d.min, d.max, 1.0f, 0.22f);
else if (d.discrete)
r = juce::NormalisableRange<float> (d.min, d.max, 1.0f);
layout.add (std::make_unique<juce::AudioParameterFloat> (
d.id, d.name, r, p0.v[i]));
}
layout.add (std::make_unique<juce::AudioParameterInt> ("patchsel", "Patch", 0, bank.size() - 1, 0));
layout.add (std::make_unique<juce::AudioParameterInt> ("delaysync", "Delay Sync", 0, 10, 0));
return layout;
}
const char* waveName (int w)
{
switch (w) { case 0: return "SINE"; case 1: return "TRIANG"; case 2: return "SAWTOOTH";
case 3: return "PULSE"; case 4: return "NOISE"; case 5: return "FM ";
case 6: return "PWM "; case 7: return "SUPRSW "; case 8: return "DBLSAW ";
case 9: return "WARP "; case 10: return "HSYNC "; case 11: return "TINE ";
case 12: return "SEQ "; case 13: return "CHORD "; case 14: return "SUPRPL ";
default: return "-----"; }
}
const char* fltTypeName (int t)
{
switch (t) { case 0: return "OFF "; case 1: return "LOWPASS "; case 2: return "BANDPASS ";
case 3: return "HIGH-PASS"; default: return "OFF "; }
}
const char* lfoShapeName (int s)
{
switch (s) { case 0: return "SINE"; case 1: return "TRIANG"; case 2: return "SQUARE";
case 3: return "S+H "; default: return "SINE"; }
}
const char* lfoTargetName (int t)
{
switch (t) { case 0: return "FILTER"; case 1: return "PITCH"; case 2: return "AMP ";
default: return "FILTER"; }
}
const char* fxTypeName (int t)
{
switch (t) { case 0: return "OFF"; case 1: return "CHORUS"; case 2: return "DELAY ";
case 3: return "SPACE"; case 4: return "REV HALL"; case 5: return "ENS+REV";
case 6: return "DLY+REV"; case 7: return "CATHEDRAL"; default: return "OFF"; }
}
const char* xmodTypeName (int t)
{
switch (t) { case 0: return "OFF "; case 1: return "RING "; case 2: return "FM ";
case 3: return "AM "; default: return "OFF "; }
}
2026-09-08 21:57:34 +02:00
const char* arpRateName (int r)
{
switch (r) { case 0: return "1/16"; case 1: return "1/8T"; case 2: return "1/8 ";
case 3: return "1/4T"; case 4: return "1/4 "; case 5: return "1/2 ";
case 6: return "3/4 "; case 7: return "1/1 "; default: return "1/8 "; }
}
const char* arpPatternName (int p)
{
switch (p) { case 0: return "UP"; case 1: return "DOWN"; case 2: return "UP/DN";
case 3: return "RANDOM"; default: return "UP"; }
}
const char* delaySyncName (int s)
{
switch (s)
{
case 0: return "OFF ";
case 1: return "1/16";
case 2: return "1/8 ";
case 3: return "1/8T";
case 4: return "1/8D";
case 5: return "1/4 ";
case 6: return "1/4T";
case 7: return "1/4D";
case 8: return "1/2 ";
case 9: return "3/4 ";
case 10: return "1/1 ";
default: return "--";
}
}
double delaySyncBeats (int s)
{
switch (s)
{
case 0: return 0.0; // disabled
case 1: return 0.25; // 1/16 note
case 2: return 0.5; // 1/8
case 3: return 1.0 / 3.0; // 1/8 triplet
case 4: return 0.75; // 1/8 dotted
case 5: return 1.0; // 1/4
case 6: return 2.0 / 3.0; // 1/4 triplet
case 7: return 1.5; // 1/4 dotted
case 8: return 2.0; // 1/2
case 9: return 3.0; // 3/4
case 10: return 4.0; // whole
default: return 0.0;
}
}
float delaySyncMaxTime()
{
return 5.0f; // allow a whole note at slow tempos (e.g. 48 BPM)
}
static juce::String fmtTime (float t)
{
if (t >= 1.0f) return juce::String (t, 2) + "s";
if (t >= 0.1f) return juce::String (t, 2) + "s";
return juce::String ((int) (t * 1000.0f)) + "ms";
}
static juce::String fmtPercent (float v) { return juce::String ((int) (v * 100.0f + 0.5f)) + "%"; }
juce::String formatParam (Id id, float v)
{
switch (id)
{
case Id::osc1Wave:
case Id::osc2Wave: return waveName ((int) v);
case Id::detune:
case Id::detune1: return juce::String ((int) v > 0 ? "+" : "") + juce::String ((int) v) + "c";
case Id::oscMix: return juce::String ((int) (100.0f - v)) + "/" + juce::String ((int) v);
case Id::fltType: return fltTypeName ((int) v);
case Id::fltCutoff:
if (v >= 1000.0f) return juce::String (v / 1000.0f, 2) + "kHz";
return juce::String ((int) v) + "Hz";
case Id::fltRes: return fmtPercent (v);
case Id::fltEnv: return fmtPercent (v / 100.0f);
case Id::fltKey: return fmtPercent (v / 100.0f);
case Id::ampA: case Id::ampD: case Id::ampR:
case Id::fenvA: case Id::fenvD: case Id::fenvR: return fmtTime (v);
case Id::ampS: case Id::fenvS: return fmtPercent (v);
case Id::lfoRate: return juce::String (v, 2) + "Hz";
case Id::lfoShape: return lfoShapeName ((int) v);
case Id::lfoDepth: return fmtPercent (v);
case Id::lfoTarget:return lfoTargetName ((int) v);
case Id::fxType: return fxTypeName ((int) v);
case Id::fxAmt: return fmtPercent (v);
case Id::fxTime: return fmtTime (v);
case Id::vol: return fmtPercent (v);
case Id::pan:
if (v < -0.02f) return "L" + juce::String ((int) (v * -100.0f));
if (v > 0.02f) return "R" + juce::String ((int) (v * 100.0f));
return "CTR";
case Id::poly: return juce::String ((int) v) + " VOICE";
case Id::glide: return v < 0.001f ? juce::String ("0") : fmtTime (v);
case Id::tune: {
const int t = (int) v;
return juce::String (t > 0 ? "+" : "") + juce::String (t) + "ST";
}
case Id::ctune1:
case Id::ctune2: {
const int t = (int) v;
return juce::String (t > 0 ? "+" : "") + juce::String (t) + "ST";
}
case Id::hq: return v >= 0.5f ? "HQ" : "ECO";
case Id::xmod: return xmodTypeName ((int) v);
case Id::xmix:
case Id::evolve:
case Id::warp: return fmtPercent (v);
2026-09-08 21:57:34 +02:00
case Id::arpOn: return v >= 0.5f ? "ON " : "OFF";
case Id::arpRate: return arpRateName ((int) v);
case Id::arpPattern: return arpPatternName ((int) v);
case Id::arpOct: return juce::String ((int) v) + " OCT";
case Id::arpGate: return juce::String ((int) v) + "%";
default: return "-----";
}
}
float changeParam (Id id, float cur, int dir, bool coarse)
{
const Desc& d = desc (id);
float step = coarse ? d.coarse : d.fine;
cur = juce::jlimit (d.min, d.max, cur + dir * step);
if (d.discrete) cur = (float) juce::roundToInt (cur);
return cur;
}
} // namespace prm