Regarding correct usage of juce:ADSR for filters / general


I’ve noticed that I may have a bug in the way I am applying envelopes in general and it is more visible in the case of filter envelopes.

const float nextFilterADSRSample = m_filterEnvelopeLeft.getNextSample() : m_filterEnvelopeRight.getNextSample();
// assume adsr is relative to m_cuttOff
float filterFreq = m_cutOff * nextFilterADSRSample;
filterFreq = max(filterFreq, Ids::Filter::Cutoff::min);
filterFreq = min(filterFreq, Ids::Filter::Cutoff::max);

// This is the TPT filter from dsp::StateVariableTPTFilter<float>
wave = m_filterTPT.processSample(channel, wave);

outputBuffer.addSample(channel, startSample, static_cast<float>(wave * m_velocity * nextADSRSample));

So what happens is, the moment the note is released, the value of cutoff goes to zero.

I thought I would work around this by only applying nextFilterADSRSample when nextFilterADSRSample.isActive() is true, but this makes it even worse and it stops the filter completely after the note release, meaning that it plays the note with filter fully open.

For example, For the case of a lowpass filter, when Release is zero, pressing a note you hear the normal decay that interpolates to sustain as expected. So you can hear the cut off as you normally would in any synth. But the moment you let go of the note, it is as if there is no cut off, it goes back to fully open sound without any filters.

Filter Release set to 0

Same thing happens when Release is set to 1.0, only after 1 second. Decay to sustain, release the note and in a second you can hear the unfiltered sound.

Filter Release set to greater than zero

I’ve been trying to figure out what’s causing this. I appreciate if anyone can point out the issue.

on another note, does it make sense to have the ADSR’s Attack, Decay and Release set to larger than 1 second for ambient and other sounds?