#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 }, { "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 }, }; const Desc& desc (Id id) { return table[static_cast(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 r (d.min, d.max); if (juce::String (d.id) == "fltcut") r = juce::NormalisableRange (d.min, d.max, 1.0f, 0.22f); else if (d.discrete) r = juce::NormalisableRange (d.min, d.max, 1.0f); layout.add (std::make_unique ( d.id, d.name, r, p0.v[i])); } layout.add (std::make_unique ("patchsel", "Patch", 0, bank.size() - 1, 0)); layout.add (std::make_unique ("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 "; } } 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::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); 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