Upload files to "Source"

This commit is contained in:
ed
2025-10-22 17:15:31 +00:00
parent 187e9f36a4
commit 20b53a8780
2 changed files with 17 additions and 39 deletions

View File

@@ -1,6 +1,5 @@
#include "SynthVoice.h" #include "SynthVoice.h"
#include <cmath> #include <cmath>
std::shared_ptr<WT::Bank> NeuralSynthVoice::wtBank;
//============================================================================== //==============================================================================
@@ -16,15 +15,6 @@ void NeuralSynthVoice::prepare (const juce::dsp::ProcessSpec& newSpec)
// --- Oscillator // --- Oscillator
osc.prepare (spec.sampleRate); osc.prepare (spec.sampleRate);
setWaveform (0); // default to sine setWaveform (0); // default to sine
// --- Wavetable bank (build once), then prepare osc ---
if (!wtBank)
{
wtBank = std::make_shared<WT::Bank>(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) // --- Scratch buffer (IMPORTANT: allocate real memory)
tempBuffer.setSize ((int) spec.numChannels, (int) spec.maximumBlockSize, tempBuffer.setSize ((int) spec.numChannels, (int) spec.maximumBlockSize,
@@ -80,25 +70,21 @@ void NeuralSynthVoice::renderNextBlock (juce::AudioBuffer<float>& outputBuffer,
if (numSamples <= 0) if (numSamples <= 0)
return; return;
//if (! adsr.isActive()) if (! adsr.isActive())
// clearCurrentNote(); clearCurrentNote();
// Apply pending waveform change (from GUI / processor thread) // Apply pending waveform change (from GUI / processor thread)
const int wf = pendingWaveform.exchange (-1, std::memory_order_acq_rel); const int wf = pendingWaveform.exchange (-1, std::memory_order_acq_rel);
if (wf != -1) if (wf != -1)
setWaveform (wf); setWaveform (wf);
// --- Generate oscillator into temp buffer (WT or BLEP) --- // --- Generate oscillator into temp buffer
tempBuffer.clear(); tempBuffer.clear();
const int numCh = juce::jmin ((int) spec.numChannels, tempBuffer.getNumChannels()); 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) 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) for (int ch = 0; ch < numCh; ++ch)
tempBuffer.getWritePointer (ch)[i] = s; tempBuffer.getWritePointer (ch)[i] = s;
} }
@@ -336,14 +322,10 @@ void NeuralSynthVoice::noteStarted()
{ {
const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz();
// Oscillator frequency + phase // Oscillator frequency and phase retrigger
osc.setFrequency (freqHz); osc.setFrequency (freqHz);
osc.resetPhase (0.0f); osc.resetPhase (0.0f);
// Wavetable oscillator too
wtOsc.setFrequency(freqHz);
wtOsc.resetPhase(0.0f);
// Chorus snapshot // Chorus snapshot
if (shared.chorusCentre) chain.get<chorusIndex>().setCentreDelay (shared.chorusCentre->load()); if (shared.chorusCentre) chain.get<chorusIndex>().setCentreDelay (shared.chorusCentre->load());
if (shared.chorusDepth) chain.get<chorusIndex>().setDepth (shared.chorusDepth->load()); if (shared.chorusDepth) chain.get<chorusIndex>().setDepth (shared.chorusDepth->load());
@@ -390,7 +372,6 @@ void NeuralSynthVoice::notePitchbendChanged()
{ {
const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz();
osc.setFrequency (freqHz); osc.setFrequency (freqHz);
wtOsc.setFrequency (freqHz);
} }
//============================================================================== //==============================================================================

View File

@@ -1,13 +1,12 @@
#pragma once #pragma once
#include <JuceHeader.h> #include <JuceHeader.h>
#include <functional> #include <functional> // <-- for std::function used by WaveShaper
#include "NeuralSharedParams.h" #include "NeuralSharedParams.h"
#include "BlepOsc.h" #include "BlepOsc.h"
#include "WavetableOsc.h" // <-- new
//============================================================================== //==============================================================================
// A single voice with BLEP osc + optional Wavetable osc (morph + anti-aliasing), // A single polyBLEP oscillator voice with per-voice ADSR, filter ADSR,
// per-voice ADSR, filter ADSR, flanger/delay/chorus/reverb/distortion/EQ/master. // flanger (delayline), simple delay, chorus, reverb, distortion, EQ, master.
class NeuralSynthVoice : public juce::MPESynthesiserVoice class NeuralSynthVoice : public juce::MPESynthesiserVoice
{ {
public: public:
@@ -32,12 +31,12 @@ public:
private: private:
void setWaveform (int waveformType); void setWaveform (int waveformType);
//=== Processing chain (without oscillator) ================================= //=== Processing chain (without oscillator) ===============================
using DelayLine = juce::dsp::DelayLine<float, using DelayLine = juce::dsp::DelayLine<float,
juce::dsp::DelayLineInterpolationTypes::Linear>; juce::dsp::DelayLineInterpolationTypes::Linear>;
using IIR = juce::dsp::IIR::Filter<float>; using IIR = juce::dsp::IIR::Filter<float>;
using Gain = juce::dsp::Gain<float>; using Gain = juce::dsp::Gain<float>;
using WaveShaper = juce::dsp::WaveShaper<float, std::function<float(float)>>; using WaveShaper = juce::dsp::WaveShaper<float, std::function<float(float)>>; // <-- fix
using Chorus = juce::dsp::Chorus<float>; using Chorus = juce::dsp::Chorus<float>;
using Reverb = juce::dsp::Reverb; using Reverb = juce::dsp::Reverb;
using Limiter = juce::dsp::Limiter<float>; using Limiter = juce::dsp::Limiter<float>;
@@ -75,24 +74,22 @@ private:
private: private:
NeuralSharedParams& shared; NeuralSharedParams& shared;
juce::dsp::ProcessSpec spec {}; juce::dsp::ProcessSpec spec {};
// ==== Oscillators ======================================================== // ==== Oscillator (polyBLEP) ============================================
BlepOsc osc; // polyBLEP (existing) BlepOsc osc;
std::atomic<int> pendingWaveform { -1 }; std::atomic<int> pendingWaveform {-1}; // set by changeWaveform()
WT::Osc wtOsc; // wavetable oscillator (new) // ==== Envelopes & Filter ===============================================
static std::shared_ptr<WT::Bank> wtBank; // shared bank across voices
// ==== Envelopes & Filter =================================================
juce::ADSR adsr; juce::ADSR adsr;
juce::ADSR filterAdsr; juce::ADSR filterAdsr;
juce::dsp::StateVariableTPTFilter<float> svf; juce::dsp::StateVariableTPTFilter<float> svf;
// ==== FX chain =========================================================== // ==== Chain (FX, EQ, master, limiter) ==================================
Chain chain; Chain chain;
// ==== Scratch buffer ===================================================== // ==== Scratch buffer (properly allocated) ===============================
juce::AudioBuffer<float> tempBuffer; juce::AudioBuffer<float> tempBuffer;
juce::dsp::AudioBlock<float> tempBlock; juce::dsp::AudioBlock<float> tempBlock;