mirror of
https://codeberg.org/armin/sm-26.git
synced 2026-10-11 17:01:53 +02:00
112 lines
No EOL
3 KiB
C++
112 lines
No EOL
3 KiB
C++
#pragma once
|
|
|
|
#include <JuceHeader.h>
|
|
#include <array>
|
|
#include "SynthParams.h"
|
|
#include "Presets.h"
|
|
|
|
namespace sm26 {
|
|
|
|
class SynthEngine
|
|
{
|
|
public:
|
|
static constexpr int kNumVoices = 12;
|
|
|
|
SynthEngine();
|
|
|
|
void prepare (double sampleRate, int maxBlockSize);
|
|
void reset();
|
|
|
|
void loadPreset (const Preset& p);
|
|
int presetIndex() const { return currentPresetIndex; }
|
|
void setPresetIndex (int i);
|
|
|
|
void setParam (int id, float n01);
|
|
float getParam (int id) const;
|
|
|
|
struct KnobView {
|
|
const char* name;
|
|
int param;
|
|
float value01;
|
|
float lo;
|
|
float hi;
|
|
};
|
|
KnobView knobView (int knob) const;
|
|
|
|
float knobValue (int knob) const;
|
|
|
|
void process (AudioBuffer<float>& buffer, MidiBuffer& midi, int n,
|
|
double bpm, bool transportPlaying);
|
|
|
|
int notesPlaying() const { return activeNotes; }
|
|
float lastBpm() const { return lastBpmValue; }
|
|
bool transport() const { return wasPlaying; }
|
|
int delayTimeSamples() const { return lastDelaySamples; }
|
|
|
|
const char* waveNameFor (int index) const;
|
|
|
|
private:
|
|
struct Voice {
|
|
bool active = false;
|
|
int note = 60;
|
|
double velocity = 0.8;
|
|
double ph1 = 0.0, ph2 = 0.0;
|
|
double inc1 = 0.0, inc2 = 0.0, glidedInc1 = 0.0;
|
|
double env = 0.0;
|
|
int envState = 0;
|
|
int age = 0;
|
|
int fadeLen = 32;
|
|
double ic1eq = 0.0, ic2eq = 0.0;
|
|
};
|
|
|
|
void noteOn (int note, float vel);
|
|
void noteOff (int note);
|
|
void allNotesOff();
|
|
Voice* findFreeOrSteal();
|
|
void resetVoice (Voice& v, int note, float vel);
|
|
float oscWave (int wave, double phase);
|
|
float computeSingleSample (Voice& v, float& outL, float& outR,
|
|
double fad, double frel, double fsus, double fcut,
|
|
double fq, double drive, double glideCoef, double bpm);
|
|
double cutoffFor (const Voice& v, double baseCutoff, double envAmt, double env);
|
|
|
|
double sampleRate = 48000.0;
|
|
int maxBlock = 512;
|
|
|
|
float params[kNumParams];
|
|
int knobParams[kNumKnobs];
|
|
const char* knobNames[kNumKnobs];
|
|
float knobLows[kNumKnobs];
|
|
float knobHighs[kNumKnobs];
|
|
|
|
Voice voices[kNumVoices];
|
|
int activeNotes = 0;
|
|
|
|
struct DelayLine
|
|
{
|
|
std::vector<std::vector<float>> buf;
|
|
std::vector<int> writePos;
|
|
int maxLen = 1;
|
|
void prepare (double sr)
|
|
{
|
|
maxLen = (int) (sr * 18.0) + 4;
|
|
buf.assign (2, std::vector<float> (maxLen, 0.0f));
|
|
writePos.assign (2, 0);
|
|
}
|
|
void clear() { for (auto& c : buf) std::fill (c.begin(), c.end(), 0.0f); }
|
|
};
|
|
|
|
DelayLine delay;
|
|
double lastDelaySamples = 0.0;
|
|
double lastBpmValue = 120.0;
|
|
bool wasPlaying = false;
|
|
|
|
int currentPresetIndex = 0;
|
|
mutable juce::SpinLock paramLock;
|
|
|
|
std::array<float, kNumParams> smooth;
|
|
float smCoef = 1.0f;
|
|
float ftA = 1.0f, ftB = 0.0f, ftC = 0.0f;
|
|
};
|
|
|
|
} // namespace sm26
|