Dear all,
I am trying to implement an audio unit synth. I am having a weird behaviour with the built-in ADSR of JUCE. Essentially, when I am setting the sustain parameter to 0 the release stage is not happening, and also when I am setting the sustain below 0.1 for example, the release time is longer than the settings. I am not sure what I am doing wrong here…
Thanks a lot!
This my code of the synth voice:
/*
==============================================================================
SynthVoice.h
Created: 7 Apr 2019 8:02:12pm
Author: Giuliano Anzani
==============================================================================
*/
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include "SynthSound.h"
#include "maximilian.h"
class SynthVoice : public SynthesiserVoice
{
public:
bool canPlaySound (SynthesiserSound* sound) override
{
return dynamic_cast<SynthSound*>(sound) != nullptr;
}
//========================================
void setADSRSampleRate(double sampleRate)
{
adsr.setSampleRate(sampleRate);
}
void getEnvelopeParam (float* attack, float* decay, float* sustain, float* release)
{
// envelope
adsrParams.attack = *attack;
adsrParams.decay = *decay;
adsrParams.sustain = *sustain;
adsrParams.release = *release;
}
void getMasterParam (float *mGain)
{
masterGain.setTargetValue(double (*mGain));
}
void setMasterSmoothing (double samplerate)
{
masterGain.reset(samplerate, 0.1);
}
//========================================
void startNote (int midiNoteNumber, float velocity, SynthesiserSound* sound, int currentPitchWheelPosition) override
{
// start the envelope
adsr.noteOn();
level = velocity;
frequency = MidiMessage::getMidiNoteInHertz(midiNoteNumber);
}
//========================================
void stopNote (float velocity, bool allowTailOff) override
{
if(allowTailOff)
{
adsr.noteOff();
}
else
{
clearCurrentNote();
}
}
//========================================
// Audio callback
void renderNextBlock (AudioBuffer<float> &outputBuffer, int startSample, int numSamples) override
{
adsr.setParameters(adsrParams);
if(adsr.isActive() != 0) {
for (int sample = 0; sample < numSamples; ++sample)
{
// adsr.setParameters(adsrParams);
// sin test
double theWave = osc1.sinewave(frequency) * 0.5;
for (int channel = 0; channel < outputBuffer.getNumChannels(); ++channel)
{
outputBuffer.addSample(channel, startSample, theWave * masterGain.getNextValue() * adsr.getNextSample());
}
++startSample;
}
}
else
{
clearCurrentNote();
}
}
//========================================
private:
double level;
double frequency;
SmoothedValue<double, ValueSmoothingTypes::Linear> masterGain;
maxiOsc osc1; // from maximilian lib
ADSR adsr; // JUCE envelope
ADSR::Parameters adsrParams;
};
EDIT (I forgot a piece )
here is the part of the code in the processor in which I am updating the samplerate for the ADSR:
void SynthFrameworkAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
ScopedNoDenormals noDenormals;
for (int i = 0; i < mySynth.getNumVoices(); i++)
{
if ((myVoice = dynamic_cast<SynthVoice*>(mySynth.getVoice(i))))
{
// set samplerate ADSR
myVoice->setADSRSampleRate(lastSampleRate);
// set parameters
myVoice->getEnvelopeParam(
// envelope
tree.getRawParameterValue(ATTACK_ID),
tree.getRawParameterValue(DECAY_ID),
tree.getRawParameterValue(SUSTAIN_ID),
tree.getRawParameterValue(RELEASE_ID)
);
myVoice->getMasterParam(tree.getRawParameterValue(MASTER_ID));
}
}
buffer.clear();
// audio callback from SynthVoice.h
mySynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
}