diff --git a/Source/SynthVoice.cpp b/Source/SynthVoice.cpp index a7a55ed..c9467f5 100644 --- a/Source/SynthVoice.cpp +++ b/Source/SynthVoice.cpp @@ -1,6 +1,5 @@ #include "SynthVoice.h" #include -std::shared_ptr NeuralSynthVoice::wtBank; //============================================================================== @@ -16,15 +15,6 @@ void NeuralSynthVoice::prepare (const juce::dsp::ProcessSpec& newSpec) // --- Oscillator osc.prepare (spec.sampleRate); setWaveform (0); // default to sine - // --- Wavetable bank (build once), then prepare osc --- - if (!wtBank) - { - wtBank = std::make_shared(2048, 16, 6); // N=2048, frames=16, levels=6 - wtBank->generateDefaultMorph(); // Sine -> Saw -> Square -> Triangle - wtBank->buildMipmaps(); - } - wtOsc.prepare(spec.sampleRate); - wtOsc.setBank(wtBank); // --- Scratch buffer (IMPORTANT: allocate real memory) tempBuffer.setSize ((int) spec.numChannels, (int) spec.maximumBlockSize, @@ -80,25 +70,21 @@ void NeuralSynthVoice::renderNextBlock (juce::AudioBuffer& outputBuffer, if (numSamples <= 0) return; - //if (! adsr.isActive()) - // clearCurrentNote(); + if (! adsr.isActive()) + clearCurrentNote(); // Apply pending waveform change (from GUI / processor thread) const int wf = pendingWaveform.exchange (-1, std::memory_order_acq_rel); if (wf != -1) setWaveform (wf); - // --- Generate oscillator into temp buffer (WT or BLEP) --- + // --- Generate oscillator into temp buffer tempBuffer.clear(); const int numCh = juce::jmin ((int) spec.numChannels, tempBuffer.getNumChannels()); - const bool useWT = (shared.wtOn && shared.wtOn->load() > 0.5f); - if (useWT && shared.wtMorph) - wtOsc.setMorph(shared.wtMorph->load()); // 0..15 continuous - for (int i = 0; i < numSamples; ++i) { - const float s = useWT ? wtOsc.process() : osc.process(); + const float s = osc.process(); for (int ch = 0; ch < numCh; ++ch) tempBuffer.getWritePointer (ch)[i] = s; } @@ -336,14 +322,10 @@ void NeuralSynthVoice::noteStarted() { const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); - // Oscillator frequency + phase + // Oscillator frequency and phase retrigger osc.setFrequency (freqHz); osc.resetPhase (0.0f); - // Wavetable oscillator too - wtOsc.setFrequency(freqHz); - wtOsc.resetPhase(0.0f); - // Chorus snapshot if (shared.chorusCentre) chain.get().setCentreDelay (shared.chorusCentre->load()); if (shared.chorusDepth) chain.get().setDepth (shared.chorusDepth->load()); @@ -390,7 +372,6 @@ void NeuralSynthVoice::notePitchbendChanged() { const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); osc.setFrequency (freqHz); - wtOsc.setFrequency (freqHz); } //============================================================================== diff --git a/Source/SynthVoice.h b/Source/SynthVoice.h index 1db869d..e1e8856 100644 --- a/Source/SynthVoice.h +++ b/Source/SynthVoice.h @@ -1,13 +1,12 @@ #pragma once #include -#include +#include // <-- for std::function used by WaveShaper #include "NeuralSharedParams.h" #include "BlepOsc.h" -#include "WavetableOsc.h" // <-- new //============================================================================== -// A single voice with BLEP osc + optional Wavetable osc (morph + anti-aliasing), -// per-voice ADSR, filter ADSR, flanger/delay/chorus/reverb/distortion/EQ/master. +// A single polyBLEP oscillator voice with per-voice ADSR, filter ADSR, +// flanger (delayline), simple delay, chorus, reverb, distortion, EQ, master. class NeuralSynthVoice : public juce::MPESynthesiserVoice { public: @@ -32,12 +31,12 @@ public: private: void setWaveform (int waveformType); - //=== Processing chain (without oscillator) ================================= + //=== Processing chain (without oscillator) =============================== using DelayLine = juce::dsp::DelayLine; using IIR = juce::dsp::IIR::Filter; using Gain = juce::dsp::Gain; - using WaveShaper = juce::dsp::WaveShaper>; + using WaveShaper = juce::dsp::WaveShaper>; // <-- fix using Chorus = juce::dsp::Chorus; using Reverb = juce::dsp::Reverb; using Limiter = juce::dsp::Limiter; @@ -75,24 +74,22 @@ private: private: NeuralSharedParams& shared; + juce::dsp::ProcessSpec spec {}; - // ==== Oscillators ======================================================== - BlepOsc osc; // polyBLEP (existing) - std::atomic pendingWaveform { -1 }; + // ==== Oscillator (polyBLEP) ============================================ + BlepOsc osc; + std::atomic pendingWaveform {-1}; // set by changeWaveform() - WT::Osc wtOsc; // wavetable oscillator (new) - static std::shared_ptr wtBank; // shared bank across voices - - // ==== Envelopes & Filter ================================================= + // ==== Envelopes & Filter =============================================== juce::ADSR adsr; juce::ADSR filterAdsr; juce::dsp::StateVariableTPTFilter svf; - // ==== FX chain =========================================================== + // ==== Chain (FX, EQ, master, limiter) ================================== Chain chain; - // ==== Scratch buffer ===================================================== + // ==== Scratch buffer (properly allocated) =============================== juce::AudioBuffer tempBuffer; juce::dsp::AudioBlock tempBlock;