Best way to implement a reverb pre-delay?


#1

I’ve checked these forums and googled around quite a bit. What would be the best way to implement a pre-delay for my reverb plugin from the ground up?

Say I had a pre-delay slider and wanted to delay the reverb processing to the value of that slider in milliseconds?


#2

Maybe you refer to the early reflections? These are direct delayed copies of the original signal, eventually filtered to simulate different reflecting surfaces, that usually change the frequency spectrum.
The reverb on the other hand is a mix of many interfering reflections, and is usually created by convolution of an impulse response.

But this is just read knowledge, I never created a reverb plugin, so I could be wrong.


#3

Reverb pre delay is usually the time to wait before “the output starts”. all other pieces of the Reverb (early reflections + optional input diffusion + tail) are calculated from the predelayed input.

After pre delay there can be a lot of so called “topologies”, but pre delaying the input before feeding it to the next blocks is usually a straightforward simple delay that’s always there.

NOTE: having the predelay syncable to the host tempo is a very nice feature, but if you do not need it, the Predelay block does not even have to be a fractional delay.

For a simple delay implementation look at any open source dsp platform (e.g. STK, sound pipe, sporth).
e.g. for STK

An explanation of what I mean by: pre delay is usually the time to wait before “the output starts”
Sorry for the quick and incomplete pseudocode (consider it a single sample calculation in the process block samples loop)

/**
	simple delay with time set at PluginProcessor::ParameterChanged
*/
yPredel = predelay(x);

/**
	earlyRef can be :
		- multitap delay
		- diffused multitap delay (mix & shake some allpass delays) 
		- simplified “echoing” tail algorithm (short convolution/Shroeder/FDN/Dattorro tank, ….)
*/
yEarly = earlyRef(yPredel);


/**

at this point you have a ton of possibilities for feeding a signal into the tail algorithm.

yTailInput = the input to the tail can be:
	-  the (predelayed) input: yPredel
	-  the early reflections: yEarly
	-  a diffused (multiple allpass delays ) version of the input that only goes to the tail : yDiffused = diffuse(yPredel);
	- a mix of the three above

the tail algo is a “smooth” version of some of the algorithms mentioned above

*/
yTailInput = someDiffusingAlgo(yPredel,yEarly);
yTail = tail(yTailInput);
out = dry*x + wet*( yEarly + yTail);

#4

Adding a (possibly fractional) delay line to JUCE’s DSP module is definitely on the roadmap.

For now, look at the JuceDemoPlugin code for a very simple delay line. For a reverb pre-delay, you probably don’t want to have feedback in your delay line. So you should change line 187 to:

delayData[delayPos] = (/* don't include this: delayData[delayPos] +*/ in) * delayLevel;