Search code examples
audiodelaysignal-processing

Implementing audio delay effects unit


I am creating an audio delay unit. Essentially the incoming samples go into a circular buffer and get picked out from some read pointer that is a number of samples behind the write pointer. These pointers are incremented by one for each new sample.

Additionally, in order to allow for fractional delays I actually have two read pointers one sample apart and use bilinear interpolation to blend between them depending on the floating point delay parameter. (I could use sinc interpolation or something else but have not bothered with that yet.)

It all works fine when the delay is set to a particular value. But when the user varies the delay while sounds are playing, a crackling noise is also apparent due to the changing delay taps. Presumably it is picking off the signal at varying samples and introducing random step discontinuities in the audio waveform.

I was wondering if there are any DSP audio buffs out there who know how to work around this problem, because I know that I have played with delay boxes where this effect does not happen, but at present I can't think of a solution.


Solution

  • When you're changing the delay, there will always be some sort of distortion. It's just a matter of picking what you want.

    As you've found, if you just drop into a random spot, the sharp jump from one sample value to the next will often cause an audible pop. One option is to simply mute the audio for a small period of time and start it again. If this is still too abrupt, you could scale the values down to zero over a few milliseconds, and scale them back up on the new buffer position over a few milliseconds. (Effectively turning the volume down quickly, and then back up once you're at the new position.)

    Propellerhead's Reason actually simulates speeding up and slowing down the recording as if it were a tape delay, and you were moving the head. This is pretty complicated... you are effectively re-sampling your buffer audio dynamically until you get to the new buffer location.