Hi all,
I’ve been looking at the ADSR class and I’m hoping somebody could help me out a bit here. I managed to reproduce my issue on the JUCE tutorials, so I am going to use that as a reference.
As a first experiment, I tried making use of ADSR in the Build a MIDI synthesiser tutorial and things work as expected there.
What I’ve done is basically to call noteOn()
and noteOff()
from noteStarted
and noteStopped
respectively and then just to add the following inside of my renderNextBlock
:
// ...
auto currentAmpEnv = m_empEnv.getNextSample();
auto currentSample = (float) (std::sin (currentAngle) * (level * currentAmpEnv));
// ...
Now, as a next example, I try using ADSR on the Introduction to DSP tutorial, which is also a simple synth but uses the juce::dsp
classes and also encourages to compute modulation not at each sample, but rather at each group/block of samples (whose size can be finetuned). Here I experience some audio glitches.
Following the style of the example, my code looks like this:
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
{
// ...
for (size_t pos = 0; pos < numSamples;)
{
// ...
processorChain.process(context);
pos += max;
lfoUpdateCounter -= max;
if (lfoUpdateCounter == 0)
{
lfoUpdateCounter = lfoUpdateRate;
float ampEnvOut = m_ampEnv.getNextSample();
processorChain.get<osc1Index>().setLevel(ampEnvOut);
}
}
// ...
}
This gives me audible glitches in the very first milliseconds of the attack stage.
After several experiments I figured that the problem becomes much worst as I increase the value of lfoUpdateRate
: say, if I keep it to 10
the problem is barely noticeable; with 100
it gets worst etc. If I set it to 1
it goes almost away i.e. there’s no more “distortion”, but still there’s a very small click at the very beginning of the attack (that is not there in the first “naive” example).
Now, my understanding is that in the first tutorial we go through each sample in the buffer and apply the envelope directly while in the second tutorial we do not apply modulation at each sample but rather at each block of samples, as defined by lfoUpdateRate
; Setting lfoUpdateRate
to 1
should make it equivalent to the first example.
There are some things I do not understand here:
-
why do I get those glitches at all in the second example? I am aware of the concepts of “audio rate” vs “control rate” and I think that indeed I do not want to compute the envelope for each sample, so setting
lfoUpdateRate
to1
is not the solution. But what is happening here? Do I need perhaps some kind of “smoothing”? -
when I set
lfoUpdateRate
to1
, it is my understanding that the two examples should be equivalent (i.e. modulation is computed and applied for each sample). But why in the second example there’s still a little click while there’s none in the first?
Thanks in advance and please do let me know if I need to post more info!