107 lines
3.5 KiB
C++
107 lines
3.5 KiB
C++
#include "SynthVoice.h"
|
|
|
|
//==============================================================================
|
|
NeuralSynthVoice::NeuralSynthVoice(NeuralSharedParams& sp) : shared(sp) {}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::prepare(const juce::dsp::ProcessSpec& spec)
|
|
{
|
|
setWaveform(0);
|
|
tempBlock = juce::dsp::AudioBlock<float>(heapBlock, spec.numChannels, spec.maximumBlockSize);
|
|
processorChain.prepare(spec);
|
|
adsr.setSampleRate(spec.sampleRate);
|
|
}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::noteStarted()
|
|
{
|
|
auto velocity = getCurrentlyPlayingNote().noteOnVelocity.asUnsignedFloat();
|
|
auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz();
|
|
|
|
processorChain.get<synthIndex>().setFrequency(freqHz, true);
|
|
|
|
juce::ADSR::Parameters p;
|
|
p.attack = shared.attack->load();
|
|
p.decay = shared.decay->load();
|
|
p.sustain = shared.sustain->load();
|
|
p.release = shared.release->load();
|
|
|
|
adsr.setParameters(p);
|
|
adsr.noteOn();
|
|
}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::notePitchbendChanged()
|
|
{
|
|
auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz();
|
|
processorChain.get<synthIndex>().setFrequency(freqHz, true);
|
|
}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::noteStopped(bool allowTailOff)
|
|
{
|
|
adsr.noteOff(); //Triggers release phase
|
|
}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::notePressureChanged() {}
|
|
void NeuralSynthVoice::noteTimbreChanged() {}
|
|
void NeuralSynthVoice::noteKeyStateChanged() {}
|
|
|
|
//==============================================================================
|
|
void NeuralSynthVoice::renderNextBlock(juce::AudioBuffer<float>& outputBuffer, int startSample, int numSamples)
|
|
{
|
|
if (!adsr.isActive())
|
|
clearCurrentNote();
|
|
|
|
if (waveform != -1) {
|
|
setWaveform(waveform);
|
|
waveform = -1;
|
|
}
|
|
|
|
auto block = tempBlock.getSubBlock(0, (size_t)numSamples);
|
|
block.clear();
|
|
juce::dsp::ProcessContextReplacing<float> context(block);
|
|
processorChain.process(context);
|
|
|
|
// 3. Apply ADSR envelope to tempBlock
|
|
std::vector<float*> channelPtrs;
|
|
for (size_t ch = 0; ch < tempBlock.getNumChannels(); ++ch)
|
|
channelPtrs.push_back(tempBlock.getChannelPointer(ch));
|
|
|
|
juce::AudioBuffer<float> buffer(channelPtrs.data(),
|
|
static_cast<int>(tempBlock.getNumChannels()),
|
|
static_cast<int>(tempBlock.getNumSamples()));
|
|
|
|
adsr.applyEnvelopeToBuffer(buffer, 0, numSamples);
|
|
|
|
juce::dsp::AudioBlock<float>(outputBuffer)
|
|
.getSubBlock((size_t)startSample, (size_t)numSamples)
|
|
.add(tempBlock);
|
|
}
|
|
|
|
void NeuralSynthVoice::setWaveform(int waveformType)
|
|
{
|
|
auto& osc = processorChain.template get<synthIndex>();
|
|
|
|
switch (waveformType)
|
|
{
|
|
case 0:
|
|
osc.initialise([](float x) { return std::sin(x); });
|
|
break;
|
|
|
|
case 1:
|
|
osc.initialise([](float x) { return x / juce::MathConstants<float>::pi; }); // Saw
|
|
break;
|
|
|
|
case 2:
|
|
osc.initialise([](float x) { return x < 0.0f ? -1.0f : 1.0f; }); // Square
|
|
break;
|
|
|
|
case 3:
|
|
osc.initialise([](float x) {
|
|
return 2.0f * std::abs(2.0f * (x / juce::MathConstants<float>::twoPi) - 1.0f) - 1.0f;
|
|
}); // Triangle
|
|
break;
|
|
}
|
|
} |