mirror of
https://codeberg.org/armin/rmx-19.git
synced 2026-10-12 17:31:56 +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
144
Source/SynthEngine.h
Normal file
144
Source/SynthEngine.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
#include <juce_audio_processors/juce_audio_processors.h>
|
||||
#include "Params.h"
|
||||
|
||||
struct VParams
|
||||
{
|
||||
float osc1w = 2, osc2w = 3, detune = 8, oscMix = 52.f;
|
||||
float fltType = 1, fltCut = 3400.f, fltRes = 0.18f, fltEnv = 52.f, fltKey = 40.f;
|
||||
float ampA = 0.008f, ampD = 0.26f, ampS = 0.70f, ampR = 0.35f;
|
||||
float fA = 0.02f, fD = 0.16f, fS = 0.26f, fR = 0.25f;
|
||||
float lfoRate = 4.2f, lfoShape = 0, lfoDepth = 0.22f, lfoTarget = 0;
|
||||
float fxType = 1, fxAmt = 0.30f, fxTime = 0.28f;
|
||||
float vol = 0.85f, pan = 0.0f, poly = 10.f, glide = 0.f, tune = 0.f;
|
||||
|
||||
void update (const juce::AudioProcessorValueTreeState& apvts)
|
||||
{
|
||||
auto get = [&] (const char* id) { return apvts.getRawParameterValue (id) -> load(); };
|
||||
osc1w = get ("osc1wave"); osc2w = get ("osc2wave"); detune = get ("detune");
|
||||
oscMix = get ("oscmix");
|
||||
fltType = get ("flttype"); fltCut = get ("fltcut"); fltRes = get ("fltres");
|
||||
fltEnv = get ("fltenv"); fltKey = get ("fltkey");
|
||||
ampA = get ("ampA"); ampD = get ("ampD"); ampS = get ("ampS");
|
||||
ampR = get ("ampR");
|
||||
fA = get ("fenvA"); fD = get ("fenvD"); fS = get ("fenvS");
|
||||
fR = get ("fenvR");
|
||||
lfoRate = get ("lforate"); lfoShape = get ("lfoshape"); lfoDepth = get ("lfodepth");
|
||||
lfoTarget= get ("lfotarget");
|
||||
fxType = get ("fxtype"); fxAmt = get ("fxamt"); fxTime = get ("fxtime");
|
||||
vol = get ("vol"); pan = get ("pan"); poly = get ("poly");
|
||||
glide = get ("glide"); tune = get ("tune");
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Env
|
||||
{
|
||||
public:
|
||||
enum State { Off, Atk, Dec, Sus, Rel };
|
||||
|
||||
void setRates (float a, float d, float s, float r, double sr)
|
||||
{
|
||||
srInv = 1.0 / sr;
|
||||
attTau = 1.0f / (0.001f + 0.25f * a);
|
||||
decTau = 1.0f / (0.001f + 0.35f * d);
|
||||
relTau = 1.0f / (0.001f + 0.30f * r);
|
||||
susL = s;
|
||||
}
|
||||
|
||||
void noteOn () { st = Atk; }
|
||||
|
||||
void noteOff ()
|
||||
{
|
||||
if (st != Off && st != Rel) st = Rel;
|
||||
}
|
||||
|
||||
void reset (float v = 0.0f) { cur = v; st = Off; }
|
||||
|
||||
float next()
|
||||
{
|
||||
switch (st)
|
||||
{
|
||||
case Atk:
|
||||
cur += (1.0f - cur) * std::min (1.0f, (float) (attTau * srInv) * 8.0f);
|
||||
if (cur >= 1.0f) { cur = 1.0f; st = Dec; }
|
||||
break;
|
||||
case Dec:
|
||||
cur = susL + (cur - susL) * std::exp (-decTau * (float) srInv);
|
||||
if (std::abs (cur - susL) < 0.001f) { cur = susL; st = Sus; }
|
||||
break;
|
||||
case Sus: break;
|
||||
case Rel:
|
||||
cur *= std::exp (-relTau * (float) srInv);
|
||||
if (cur < 0.0002f) { cur = 0.0f; st = Off; }
|
||||
break;
|
||||
case Off: break;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
bool running() const { return st != Off; }
|
||||
float getCur() const { return cur; }
|
||||
State getState() const { return st; }
|
||||
|
||||
private:
|
||||
float cur = 0.0f, susL = 0.7f;
|
||||
float attTau = 1.0f, decTau = 1.0f, relTau = 1.0f;
|
||||
double srInv = 1.0 / 48000.0;
|
||||
State st = Off;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class SynthEngine
|
||||
{
|
||||
public:
|
||||
SynthEngine();
|
||||
~SynthEngine();
|
||||
|
||||
void setSampleRate (double sr);
|
||||
void noteOn (int midiNote, float velocity);
|
||||
void noteOff (int midiNote);
|
||||
void allNotesOff (bool immediate);
|
||||
void sustainPedal (bool down);
|
||||
void pitchBend (float cents);
|
||||
void modWheel (float v);
|
||||
|
||||
void render (const VParams& p, float* left, float* right, int numSamples);
|
||||
|
||||
int activeVoices() const noexcept { return active; }
|
||||
void getMeters (float& l, float& r) const noexcept { l = metL; r = metR; }
|
||||
|
||||
private:
|
||||
struct Voice
|
||||
{
|
||||
bool active = false;
|
||||
int note = 0;
|
||||
float vel = 1.0f;
|
||||
float panL = 0.71f, panR = 0.71f;
|
||||
float curFreq = 0.0f, targetFreq = 0.0f;
|
||||
double ph1 = 0.0, ph2 = 0.0, lfoPh = 0.0;
|
||||
float lfoSH = 0.0f;
|
||||
int lfoIdx = 0;
|
||||
Env amp, flt;
|
||||
float lp = 0.0f, bp = 0.0f, f1c = 0.0f;
|
||||
float outSmooth = 0.0f;
|
||||
};
|
||||
|
||||
static constexpr int maxVoice = 16;
|
||||
Voice voices[maxVoice];
|
||||
double sr = 48000.0;
|
||||
int active = 0;
|
||||
int polyLimit = 16;
|
||||
float mod = 0.0f, bendCents = 0.0f, bendSmooth = 0.0f;
|
||||
bool pedal = false;
|
||||
float lastNoteFreq = 440.0f, lastGlide = 0.0f, lastPan = 0.0f;
|
||||
int stealIdx = 0;
|
||||
float metL = 0.0f, metR = 0.0f;
|
||||
juce::Random rng;
|
||||
juce::Array<int> sustainedNotes;
|
||||
|
||||
float osc (int wave, double ph);
|
||||
Voice* acquireVoice();
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue