#pragma once #include #include #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& 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; } double delayTimeMs() const; 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> buf; std::vector writePos; int maxLen = 1; void prepare (double sr) { maxLen = (int) (sr * 18.0) + 4; buf.assign (2, std::vector (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 smooth; float smCoef = 1.0f; float ftA = 1.0f, ftB = 0.0f, ftC = 0.0f; }; } // namespace sm26