/* ============================================================================== Voice.cpp Created: 2 Mar 2021 1:04:00pm Author: Louis ============================================================================== */ #include "Voice.h" Voice::Voice() { auto& masterGain = processorChain.get(); masterGain.setGainLinear(0.7f); auto& filter = processorChain.get(); filter.setCutoffFrequencyHz(filterCutoff); filter.setResonance(filterResonance); lfo.initialise([](float x) { return std::sin(x); }, 128); lfo.setFrequency(lfoFrequency); } //============================================================================== void Voice::prepare(const juce::dsp::ProcessSpec& spec) { Voice::tempBlock = juce::dsp::AudioBlock(heapBlock, spec.numChannels, spec.maximumBlockSize); processorChain.prepare(spec); lfo.prepare({ spec.sampleRate / lfoUpdateRate, spec.maximumBlockSize, spec.numChannels }); setAmplifierSampleRate(spec.sampleRate); getAmplifierParameters(&SPamplifierAttack, &SPamplifierDecay, &SPamplifierSustain, &SPamplifierRelease); setAmplifierParameters(envelopeParams); } //============================================================================== void Voice::noteStarted() { // TODO : Acceder a la valeur de sliderOscMix1; // float mOsc1Level = mainContentComponent.global.oscMix.sliderOscMix1; envelope.noteOn(); auto velocity = getCurrentlyPlayingNote().noteOnVelocity.asUnsignedFloat(); auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz(); processorChain.get().setFrequency(freqHz * osc1Rate, true); processorChain.get().setLevel(velocity * osc1Level); processorChain.get().setFrequency(freqHz * osc2Rate * 1.01f, true); processorChain.get().setLevel(velocity * osc2Level); } //============================================================================== void Voice::notePitchbendChanged() { auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz(); processorChain.get().setFrequency(freqHz * osc1Rate); processorChain.get().setFrequency(freqHz * osc2Rate * 1.01f); } //============================================================================== void Voice::noteStopped(bool) { envelope.noteOff(); clearCurrentNote(); } //============================================================================== void Voice::notePressureChanged() {} void Voice::noteTimbreChanged() {} void Voice::noteKeyStateChanged() {} //============================================================================== void Voice::setAmplifierSampleRate(double sampleRate) { envelope.setSampleRate(sampleRate); } //============================================================================== void Voice::getAmplifierParameters(float* a, float* d, float* s, float* r) { envelopeParams.attack = *a; envelopeParams.decay = *d; envelopeParams.sustain = *s; envelopeParams.release = *r; } void Voice::setAmplifierParameters(juce::ADSR::Parameters params) { envelope.setParameters(params); } //============================================================================== void Voice::renderNextBlock(juce::AudioBuffer& outputBuffer, int startSample, int numSamples) { auto output = tempBlock.getSubBlock(0, (size_t)numSamples); output.clear(); for (size_t pos = 0; pos < (size_t)numSamples;) { auto max = juce::jmin((size_t)numSamples - pos, lfoUpdateCounter); auto block = output.getSubBlock(pos, max); juce::dsp::ProcessContextReplacing context(block); processorChain.process(context); pos += max; lfoUpdateCounter -= max; if (lfoUpdateCounter == 0) { lfoUpdateCounter = lfoUpdateRate; auto lfoOut = lfo.processSample(0.0f); auto curoffFreqHz = juce::jmap(lfoOut, -1.0f, 1.0f, 100.0f, 2000.0f); auto curEnvelope = envelope.getNextSample(); processorChain.get().setCutoffFrequencyHz(curoffFreqHz); processorChain.get().setLevel(curEnvelope); } } envelope.applyEnvelopeToBuffer(outputBuffer, startSample, numSamples); juce::dsp::AudioBlock(outputBuffer).getSubBlock((size_t)startSample, (size_t)numSamples).add(tempBlock); }