mirror of
https://codeberg.org/armin/sm-26.git
synced 2026-10-11 17:01:53 +02:00
SM-26 synthesizer: initial implementation
This commit is contained in:
commit
8734ac25f1
18 changed files with 2619 additions and 0 deletions
106
Source/SynthEngine.h
Normal file
106
Source/SynthEngine.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#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;
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace sm26
|
||||
Loading…
Add table
Add a link
Reference in a new issue