55 lines
2.7 KiB
C++
55 lines
2.7 KiB
C++
#pragma once
|
|
#include "../SynthVoice.h"
|
|
|
|
void NeuralSynthVoice::renderDistortion(
|
|
int numSamples,
|
|
int numCh,
|
|
juce::dsp::AudioBlock<float> &block) {
|
|
// ================================================================
|
|
// Distortion + tone (post LPF/Peak)
|
|
// ================================================================
|
|
const float driveDb = shared.distortionDrive ? shared.distortionDrive->load() : 0.0f;
|
|
const float bias = juce::jlimit (-1.0f, 1.0f, shared.distortionBias ? shared.distortionBias->load() : 0.0f);
|
|
const float toneHz = juce::jlimit (100.0f, 8000.0f, shared.distortionTone ? shared.distortionTone->load() : 3000.0f);
|
|
const int shape = (int) std::lround (juce::jlimit (0.0f, 2.0f,
|
|
shared.distortionShape ? shared.distortionShape->load() : 0.0f));
|
|
const float mix = shared.distortionMix ? shared.distortionMix->load() : 0.0f;
|
|
|
|
auto& pre = chain.get<distortionPreGain>();
|
|
auto& sh = chain.get<distortionIndex>();
|
|
auto& tone = chain.get<distortionPostLPF>();
|
|
|
|
pre.setGainDecibels (driveDb);
|
|
|
|
// Explicit std::function target (works on MSVC)
|
|
if (shape == 0) sh.functionToUse = std::function<float(float)>{ [bias](float x) noexcept { return std::tanh (x + bias); } };
|
|
else if (shape == 1) sh.functionToUse = std::function<float(float)>{ [bias](float x) noexcept { return juce::jlimit (-1.0f, 1.0f, x + bias); } };
|
|
else sh.functionToUse = std::function<float(float)>{ [bias](float x) noexcept { return std::atan (x + bias) * (2.0f / juce::MathConstants<float>::pi); } };
|
|
|
|
tone.coefficients = juce::dsp::IIR::Coefficients<float>::makePeakFilter (
|
|
spec.sampleRate, toneHz, 0.707f,
|
|
juce::Decibels::decibelsToGain (shared.highGainDbls ? shared.highGainDbls->load() : 0.0f));
|
|
|
|
if (shared.distortionOn && shared.distortionOn->load() > 0.5f)
|
|
{
|
|
// Wet/dry blend around the shaper
|
|
juce::AudioBuffer<float> dryCopy (tempBuffer.getNumChannels(), numSamples);
|
|
for (int ch = 0; ch < numCh; ++ch)
|
|
dryCopy.copyFrom (ch, 0, tempBuffer, ch, 0, numSamples);
|
|
|
|
// pre -> shaper -> tone
|
|
pre.process (juce::dsp::ProcessContextReplacing<float> (block));
|
|
sh.process (juce::dsp::ProcessContextReplacing<float> (block));
|
|
tone.process (juce::dsp::ProcessContextReplacing<float> (block));
|
|
|
|
const float wet = mix, dry = 1.0f - mix;
|
|
for (int ch = 0; ch < numCh; ++ch)
|
|
{
|
|
auto* d = dryCopy.getReadPointer (ch);
|
|
auto* w = tempBuffer.getWritePointer (ch);
|
|
for (int i = 0; i < numSamples; ++i)
|
|
w[i] = dry * d[i] + wet * w[i];
|
|
}
|
|
}
|
|
}
|