#pragma once #include #include "GrainVoice.h" class GrainEngine { public: static constexpr int maxVoices = 8; GrainEngine(); void prepare (double sampleRate, int samplesPerBlock); void processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages); void loadSample (const juce::File& file); void loadSample (const void* data, size_t dataSize, const juce::String& formatName); const juce::AudioBuffer& getSampleBuffer() const { return sampleBuffer; } double getSampleRate() const { return currentSampleRate; } bool hasSample() const { return sampleBuffer.getNumSamples() > 0; } juce::String getSamplePath() const { return loadedSamplePath; } // Root note — which MIDI note the sample represents (default C4 = 60) std::atomic rootNote { 60 }; // Grain parameters (GUI → audio) std::atomic position { 0.5f }; std::atomic grainSizeMs { 100.0f }; std::atomic density { 10.0f }; std::atomic pitchSemitones { 0.0f }; std::atomic pan { 0.0f }; std::atomic posScatter { 0.0f }; std::atomic sizeScatter { 0.0f }; std::atomic pitchScatter { 0.0f }; std::atomic panScatter { 0.0f }; std::atomic direction { 0 }; std::atomic freeze { false }; // ADSR std::atomic attackTime { 0.01f }; std::atomic decayTime { 0.1f }; std::atomic sustainLevel { 1.0f }; std::atomic releaseTime { 0.3f }; // Filter std::atomic filterType { 0 }; // 0=LP, 1=HP, 2=BP std::atomic filterCutoff { 20000.0f }; std::atomic filterReso { 0.707f }; // Reverb std::atomic reverbSize { 0.0f }; std::atomic reverbDecay { 0.0f }; // Master std::atomic masterVolume { 1.0f }; // VU meter levels (audio → GUI) std::atomic vuLevelL { 0.0f }; std::atomic vuLevelR { 0.0f }; // Grain visualization struct ActiveGrainInfo { int startSample; int lengthSamples; float progress; }; std::vector getActiveGrainInfo() const; private: std::array voices; juce::AudioBuffer sampleBuffer; juce::String loadedSamplePath; double currentSampleRate = 44100.0; double sourceSampleRate = 44100.0; int currentBlockSize = 512; juce::AudioFormatManager formatManager; // Global effects juce::dsp::StateVariableTPTFilter filter; juce::Reverb reverb; juce::Reverb::Parameters reverbParams; void handleMidiEvent (const juce::MidiMessage& msg); void handleNoteOff (int note); void syncVoiceParameters(); // Sustain pedal bool sustainPedalDown = false; std::array sustainedVoices {}; // voices held by pedal };