mirror of
https://codeberg.org/armin/rmx-19.git
synced 2026-10-11 16:51:55 +02:00
Initial commit: RMX-19 rack sound module (VST3/AU) with dot-matrix LCD UI
This commit is contained in:
commit
c72c0216fd
16 changed files with 2170 additions and 0 deletions
154
Source/Params.cpp
Normal file
154
Source/Params.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#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, 4, 2, true, 1, 1 },
|
||||
{ "osc2wave", "OSC2 WAVE", "O2WV", 0, 4, 3, true, 1, 1 },
|
||||
{ "detune", "DETUNE", "DTN", -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.001f, 0.05f },
|
||||
{ "ampD", "AMP DECAY", "ADE", 0.001f, 6, 0.26f, false, 0.001f, 0.05f },
|
||||
{ "ampS", "AMP SUSTAIN", "ASUS", 0, 1, 0.70f, false, 0.01f, 0.08f },
|
||||
{ "ampR", "AMP RELEASE", "AREL", 0.001f, 8, 0.35f, false, 0.001f, 0.05f },
|
||||
{ "fenvA", "FENV ATTACK", "FAT", 0.001f, 6, 0.02f, false, 0.001f, 0.05f },
|
||||
{ "fenvD", "FENV DECAY", "FDE", 0.001f, 6, 0.16f, false, 0.001f, 0.05f },
|
||||
{ "fenvS", "FENV SUSTAIN", "FSUS", 0, 1, 0.26f, false, 0.01f, 0.08f },
|
||||
{ "fenvR", "FENV RELEASE", "FRE", 0.001f, 8, 0.25f, false, 0.001f, 0.05f },
|
||||
{ "lforate", "LFO RATE", "LFR", 0.02f, 22, 4.2f, false, 0.02f, 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, 3, 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 },
|
||||
};
|
||||
|
||||
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, 15, 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"; 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"; default: return "OFF"; }
|
||||
}
|
||||
|
||||
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: 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";
|
||||
}
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue