What is KVR Audio? | Submit News | Advertise | Developer Account

Options (Affects News & Product results only):

OS:
Format:
Include:
Quick Search KVR

"Quick Search" KVR Audio's Product Database, News Items, Developer Listings, Forum Topics and videos here. For advanced Product Database searching please use the full product search. For the forum you can use the phpBB forum search.

To utilize the power of Google you can use the integrated Google Site Search.

Products 0

Developers 0

News 0

Forum 0

Videos 0

Search  

Parameter smoothing for delay line?

DSP, Plug-in and Host development discussion.

Moderator: Moderators (Main)

KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Thu May 29, 2014 8:35 am Parameter smoothing for delay line?

I'm sure this is old news and has been asked X times before but I can't find what I'm looking for in "search" - or even Google. (Maybe I'm calling it the wrong term?)

Is there a standard/customary approach to smooth changes in delay line-based processes to avoid glitching noises when the delay time parameter is changing?

This would be something used in chorus, flangers, etc., as well as during user control changes of simple echos, etc.

I've tried smoothing parameter changes with simple IIR. It helps, but does not eliminate the problem (and creates new problems). What is the approach typically used for this?
KVRian
 
686 posts since 1 Dec, 2004

Postby MadBrain; Thu May 29, 2014 8:46 am Re: Parameter smoothing for delay line?

Yes
https://ccrma.stanford.edu/~dattorro/EffectDesignPart2.pdf
Long story short: For modulated delay lines (chorus, reverb, tape echo, physical modeling) use a 1-pole allpass IIR filter.

If you need to interpolate a large, instantaneous change in delay time (like changing a long delay time) instead of a bunch of smooth changes, it might be better to have a 2-tap delay line and do a crossfade.
KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Thu May 29, 2014 12:59 pm Re: Parameter smoothing for delay line?

Thank you.
KVRAF
 
4102 posts since 11 Feb, 2006, from Helsinki, Finland
 

Postby mystran; Fri May 30, 2014 2:48 am Re: Parameter smoothing for delay line?

Basically two methods: if you want a pitch shift, just smooth the delay length and interpolate for fractional samples. If you don't want a pitch shift, calculate the new length and do a fade (temporarily mixing two taps).
Image <- plugins | forum
KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Fri May 30, 2014 7:38 am Re: Parameter smoothing for delay line?

mystran wrote:Basically two methods: if you want a pitch shift, just smooth the delay length and interpolate for fractional samples. If you don't want a pitch shift, calculate the new length and do a fade (temporarily mixing two taps).

My current need is just to smooth a simple delay line during user control (parameter) changes. Whatever I use I do not want it affect the audio with interpolation or some other "always on" filtering means.

What I'm not getting is how to filter the parameter changes (in a VST plugin). The parameter changes take place outside the frame processing loop - but yet you need the "time" element of the processing loop to enact some sort of filter. So, how/where is this done?
KVRian
 
879 posts since 17 Apr, 2005
 

Postby JCJR; Fri May 30, 2014 8:57 am Re: Parameter smoothing for delay line?

Well, a simple crossfade example--

For instance maybe you have decided to do a 10 ms linear crossfade on the parameter change. For instance if the host happened to be running at 44.1K samplerate, 128 sample buffers, then the crossfade needs to happen over a span of 441 samples, so it will take several buffers to complete the crossfade.

If you decide to just do the crossfades starting at buffer boundaries, maybe something in the ballpark of this crude pseudocode--

Midi messages in vst can tell the plugin what sample offset in the buffer to begin responding to each midi message. The plugin doesn't have to start all notes and control changes exactly at buffer boundaries. I can't recall if other possible flavors of param changes can be time-stamped thataway in VST. I mainly pay attention to MIDI in my hosting.

Code: Select all
====
When you notice a param change--

double InterpFactor; //instance global
double InterpStep; //instance global

double FadeSeconds;
double FadeSpanInSamps;

SaveNewestSettingsInNewParmsObject();
InterpFactor = 1; //this is usually <= 0.0 except when crossfading
FadeSeconds = 0.01; //10 ms
FadeSpanInSamps = SampleRate * FadeSeconds;
InterpStep = 1.0 / FadeSpanInSamps;

====

In your rendering--

if (InterpFactor <= 0.0) //no recent parm changes, no crossfade in effect
  CalculateOutputBufferUsingOldParms();
else //need to calculate two buffers with the two sets of parameters and crossfade
{
  CalcTempOutBufferWithOldParms(); //fill temp buf OldParmBuffer[]
  CalcTempOutBufferWithNewParms(); //fill temp buf NewParmBuffer[]
  for (i = 0; i < NumSampsInBuffer; ++i)
  {
    if (InterpFactor <= 0.0) //finished crossfade within this loop
      OutputBuffer[i] = NewParmBuffer[i];
    else
    {
      OutputBuffer[i] = OldParmBuffer[i] * InterpFactor + NewParmBuffer[i] * (1.0 - InterpFactor);
      InterpFactor -= InterpStep; //decrement InterpFactor toward zero
    }
  }
  if (InterpFactor <= 0.0) //it reached the end of crossfade in this buffer loop
    OldParms = NewParms; //update the OldParms after crossfade finished
}
KVRist
 
189 posts since 4 Apr, 2010
 

Postby earlevel; Fri May 30, 2014 12:22 pm Re: Parameter smoothing for delay line?

There are a number of ways to go—you just have to decide on the behavior you want. For example, in Echo Farm (PT plug-in) and the DL4 delay pedal (shared DSP code), I gave the analog delays analog behavior by smoothing the delay parameter with a one-pole lowpass. This makes the pitch drop or rise (depending on increasing or decreasing delay) and settle back into pitch, like it does with a tape echo or other continuous analog delay.

But for digital delays, I ramped the delays down and back up per change, so that it gets ducked repeatedly while the knob is in motion. The pitch doesn't change, and I was simply looking for "digital delay" behavior to go with digital delay emulation. (Note, this doesn't require multiple delays. Echo Farm and DL4 use two delay lines in order to let the old delay effect to repeat out when switching to another, but the current, single delay line per channel is used with the ducking effect.) Think of how many radios duck the audio while you're spinning the tuning knob—you do hear a kind of sucking in and out of the level while the knob's turning, but not the blasts of noise you'd get without the ducking. The effect on the digital delays is smoother, but maybe that description give you some idea.

You probably don't need this, but maybe someone does—this is exactly the sort of filter I used for various parameters, including the delay smoothing for analog:

http://www.earlevel.com/main/2012/12/15/a-one-pole-filter/
My audio DSP blog: earlevel.com
KVRAF
 
4102 posts since 11 Feb, 2006, from Helsinki, Finland
 

Postby mystran; Fri May 30, 2014 12:37 pm Re: Parameter smoothing for delay line?

JCJR wrote: I can't recall if other possible flavors of param changes can be time-stamped thataway in VST.


In VST2, no such time-stamps. Those few hosts that actually care (not very many), just split process blocks so the changes can be done in betwee.
Image <- plugins | forum
KVRian
 
879 posts since 17 Apr, 2005
 

Postby JCJR; Fri May 30, 2014 1:35 pm Re: Parameter smoothing for delay line?

mystran wrote:
JCJR wrote: I can't recall if other possible flavors of param changes can be time-stamped thataway in VST.


In VST2, no such time-stamps. Those few hosts that actually care (not very many), just split process blocks so the changes can be done in between.


Thanks, mystran!
KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Fri May 30, 2014 4:22 pm Re: Parameter smoothing for delay line?

Thanks all.

I actually went with a little different, and very simple, approach to what was suggested above. I created a new variable I called "newoffset" (pretty clever name, eh? LOL) which is set by the parameter change. I then ramped the current value up or down to it in the "process()" function like this:
Code: Select all
        if(offset < newoffset) offset++;//delay change smooth to new value
        if(offset > newoffset) offset--;

So with each sample that is processed the delay pointer (which is offset by the delay value of "offset") can only change by one increment up or down (rather than jumping several at once). It ramps smoothly, and linearly, to the new offset value. The bigger the change the longer it takes to get there. Higher sample rates will ramp faster but - so what - it's still a graduated transition vs. jumps.

It's not perfect but it is simple and took care of the clicks and pops during user delay time changes. The best part is it doesn't affect the audio at all once settled.

BTW - I initialized "offset" to 0 in the constructor to make sure it didn't have too far to go to any new value. I also protect the range with limits elsewhere in the code.
KVRist
 
189 posts since 4 Apr, 2010
 

Postby earlevel; Fri May 30, 2014 4:58 pm Re: Parameter smoothing for delay line?

Fender19 wrote:I actually went with a little different, and very simple, approach to what was suggested above...
Code: Select all
        if(offset < newoffset) offset++;//delay change smooth to new value
        if(offset > newoffset) offset--;



Great...but I suggest that you do yourself a favor and at least try the one-pole. It's actually simpler, and the behavior sounds more natural (you aren't limited by the slew rate for bigger moves, and it has a satisfying deceleration into the target). If you look at the link to code I posted, it's a single, branchless "z1 = in * a0 + z1 * b1", where z1 is the delay element and output for each iteration. a0 is just 1 - b1, so you could rearrange it that way if you want. I give the calculation for b1 (exp(-2.0 * M_PI * Fc);), but in a nut shell it's just a constant that gives you the rate of change you're happy with, so you could just plug in a number—a little less than 1.

BTW, a one-pole filter won't overshoot, so it behaves the way you want for this purpose.
My audio DSP blog: earlevel.com
KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Sat May 31, 2014 11:46 am Re: Parameter smoothing for delay line?

earlevel wrote:BTW, a one-pole filter won't overshoot, so it behaves the way you want for this purpose.

Overshoot may not be a problem but I have found that UNDERSHOOT can be. Since the delay line pointers are integers when cast to float and smoothed with IIR the final value cast back to integer may settle +/-1 sample off from what your control wants it to be.

At least that's what I found when I've tried IIR smoothing before. Maybe I've misunderstood the approach? I will give it another try. Thank you for the code and reference.
KVRist
 
189 posts since 4 Apr, 2010
 

Postby earlevel; Sat May 31, 2014 12:18 pm Re: Parameter smoothing for delay line?

Fender19 wrote:
earlevel wrote:BTW, a one-pole filter won't overshoot, so it behaves the way you want for this purpose.

Overshoot may not be a problem but I have found that UNDERSHOOT can be. Since the delay line pointers are integers when cast to float and smoothed with IIR the final value cast back to integer may settle +/-1 sample off from what your control wants it to be.


Ah, so your delay line doesn't support fractional delays times (if I understand correctly)...well, you can round or something...

Of course fractional delay times are a big improvement if you want to support various time-based effects (flanging, etc.). There are more sophisticated ways, but if you want to experiment cheaply, try simple linear interpolation, using a float time value in samples (interpolating between the sample indexed by the integer part and the next one, using the fractional part). Now, I hear gasps, but linear interp is good for lower freqs, not so good for the higher, but you can cheat a little by forcing your time settings to sample boundaries (so that it's normal at or very close to a sample boundary, but can still slide continuously through time while being modulated); do this with your nominal delay setting but let everything from there on (the one-pole and any wow-and-flutter or other modulation) "float".

First, it's not as bad as you'd think, since for much of music the high frequencies are at lower amplitudes (and it helps if you're emulating an analog delay with HF rolloff). And second, if it's not good enough, you can just drop in an improved interpolated delay line later.

Anyway, just a tip, not telling you how to do your thing. But since you're going to the effort of trying to handle time changes in a somewhat natural manner, I think you'll enjoy the improvement with a fractional delay line.
My audio DSP blog: earlevel.com
KVRist
 
73 posts since 30 Aug, 2012

Postby Fender19; Sat May 31, 2014 1:25 pm Re: Parameter smoothing for delay line?

earlevel wrote:Ah, so your delay line doesn't support fractional delays times (if I understand correctly)...well, you can round or something....

Yes, I am using a simple delay line where the read pointer is X offset behind the write pointer in a rotating buffer. It's normally a static offset. The only time it's "modulated" is when the user is making delay parameter changes during which the original code gave nasty clicks and pops.

earlevel wrote:Anyway, just a tip, not telling you how to do your thing.

I appreciate any/all tips. :tu:
KVRer
 
2 posts since 13 Mar, 2014

Postby omygaudio; Thu Jun 12, 2014 2:35 am Re: Parameter smoothing for delay line?

Have you tried cubic interpolation? It has this almost buttery flavor to it, I used it in my pitch shifting delay and it has been pretty "smooth".

Code: Select all
double CubicInterp (double frac, double w, double x, double y, double z)
{
   double c1 = (y - w) * 0.5f;
   double c3 = (x - y) * 1.5f + (z - w) * 0.5f;
   double c2 = c1 + w - x - c3;
   return ((c3 * frac + c2) * frac + c1) * frac + x;
}


And yeah I would also try slapping a OnePole on there and see how things go, even something like this might work

Code: Select all
struct Smooth {
    Smooth() : value(0), target(0), factor(0.003) {}
   
    double operator()() {
        double y = value;
        value += (target - value) * factor;
        return y;
    }
   
    void operator=(double target) {
        this->target = target;
    }
   
    double value, target, factor;
};


=)
Next

Moderator: Moderators (Main)

Return to DSP and Plug-in Development