#ifndef SYNTH_ENGINE_H #define SYNTH_ENGINE_H #include #include /** * @class SynthEngine * @brief A portable, platform-agnostic synthesizer engine. * * This class contains the core digital signal processing (DSP) logic. * It has no dependencies on any specific hardware, OS, or audio API. * It works by filling a provided buffer with 16-bit signed audio samples. * * The oscillator uses a 32-bit unsigned integer as a phase accumulator, * which is highly efficient and avoids floating-point math in the audio loop, * making it ideal for the RP2040. */ class SynthEngine { public: enum Waveform { SAWTOOTH, SQUARE, SINE }; /** * @brief Constructs the synthesizer engine. * @param sampleRate The audio sample rate in Hz (e.g., 44100). */ ~SynthEngine(); SynthEngine(uint32_t sampleRate); /** * @brief Fills a buffer with audio samples. This is the main audio callback. * @param buffer Pointer to the output buffer to be filled. * @param numFrames The number of audio frames (samples) to generate. */ void process(int16_t* buffer, uint32_t numFrames); /** * @brief Sets the frequency of the oscillator. * @param freq The frequency in Hz. */ void setFrequency(float freq); /** * @brief Sets the output volume. * @param vol Volume from 0.0 (silent) to 1.0 (full). */ void setVolume(float vol); /** * @brief Sets the oscillator's waveform. * @param form The waveform to use. */ void setWaveform(Waveform form); /** * @brief Opens or closes the sound gate. * @param isOpen True to produce sound, false for silence. */ void setGate(bool isOpen); /** * @brief Gets the current frequency of the oscillator. * @return The frequency in Hz. */ float getFrequency() const; /** * @brief Configures the ADSR envelope. * @param attack Attack time in seconds. * @param decay Decay time in seconds. * @param sustain Sustain level (0.0 to 1.0). * @param release Release time in seconds. */ void setADSR(float attack, float decay, float sustain, float release); /** * @brief Configures the filters. * @param lpCutoff Low-pass cutoff frequency in Hz. * @param hpCutoff High-pass cutoff frequency in Hz. */ void setFilter(float lpCutoff, float hpCutoff); // --- Grid Synth --- struct GridCell { enum Type { EMPTY, FIXED_OSCILLATOR, INPUT_OSCILLATOR, WAVETABLE, NOISE, FORK, WIRE, OPERATOR, DELAY, REVERB, SINK }; enum Op { OP_ADD, OP_MUL, OP_SUB, OP_DIV, OP_MIN, OP_MAX }; Type type = EMPTY; float param = 0.5f; // 0.0 to 1.0 int rotation = 0; // 0:N, 1:E, 2:S, 3:W (Output direction) float value = 0.0f; // Current output sample float phase = 0.0f; // For Oscillator, Noise state float* buffer = nullptr; // For Delay uint32_t buffer_size = 0; // For Delay uint32_t write_idx = 0; // For Delay }; GridCell grid[5][8]; std::mutex gridMutex; // Helper to process one sample step of the grid float processGridStep(); private: uint32_t _sampleRate; uint32_t _phase; // Phase accumulator for the oscillator. uint32_t _increment; // Phase increment per sample, determines frequency. float _volume; Waveform _waveform; bool _isGateOpen; // ADSR State enum EnvState { ENV_IDLE, ENV_ATTACK, ENV_DECAY, ENV_SUSTAIN, ENV_RELEASE }; EnvState _envState; float _envLevel; float _attackInc, _decayDec, _sustainLevel, _releaseDec; // Filter State float _lpAlpha; float _hpAlpha; float _lpVal; float _hpVal; }; #endif // SYNTH_ENGINE_H