Add delay tempo sync, rack faceplate, README, docs

- Add host-tempo-synced delay: FX screen gains a 4th SYNC row for
  rhythmic divisions (1/16 .. 1/1) that lock delay time to DAW tempo
- Embed rack faceplate background (b2.png) via juce binary data
- Add offline dev probe (rmx_probe) for GUI-less MIDI testing
- Allow overriding JUCE_ROOT when configuring the build
- Write comprehensive README describing the instrument, UI, MIDI, DSP,
  and build/install steps
This commit is contained in:
Armin 2026-09-08 15:10:12 +02:00
commit 2e870380d4
17 changed files with 1413 additions and 324 deletions

View file

@ -14,15 +14,15 @@ static const Desc table[num] = {
{ "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 },
{ "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.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 },
{ "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.001f, 0.05f },
{ "lforate", "LFO RATE", "LFR", 0.02f, 22, 4.2f, false, 0.02f, 0.5f },
{ "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 },
@ -34,6 +34,7 @@ static const Desc table[num] = {
{ "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 },
};
const Desc& desc (Id id) { return table[static_cast<int>(id)]; }
@ -59,7 +60,8 @@ juce::AudioProcessorValueTreeState::ParameterLayout createLayout()
d.id, d.name, r, p0.v[i]));
}
layout.add (std::make_unique<juce::AudioParameterInt> ("patchsel", "Patch", 0, 15, 0));
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;
}
@ -93,6 +95,49 @@ const char* fxTypeName (int t)
case 3: return "SPACE"; default: return "OFF"; }
}
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";
@ -138,6 +183,7 @@ juce::String formatParam (Id id, float v)
const int t = (int) v;
return juce::String (t > 0 ? "+" : "") + juce::String (t) + "ST";
}
case Id::hq: return v >= 0.5f ? "HQ" : "ECO";
default: return "-----";
}
}