smoothing parameter changes, how is it done in DAWs?

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Hi,

I am currently working on my first real synthesizer/sequencer application (c++) and I am at the point where most features are implemented. however, the paramter-smoothing was something I left open until now.

I am using a simple class for smoothing parameters, which I found in the web. It's a one-pole LPF with the following parameters:

b1 = 0.99;
a0 = 1.0 - b1 = 0.01;

For every sample, I calculate the parameter like this:
float last = parameter * b + (last * a);
return last;

All of my parameters which are send to the signal processing are in a range of 0 to 1, if not, they are clipped.
My stereo-delay effect updates both delay-lines ever sample, they are set to 100 to 1000ms, so [0,1] is scalled up to [100,900].

The problem I am having is that most parameters get smoothed with the low pass and there are no unwanted noises when moving gui-elements around, however the delay-effect sounds even more distorted then without any parameter smoothing.

So the question is: what could I use for smoothing this parameter? I've compared it with abletons simple delay and this thing doesn't make any noise at all when turning the dial like crazy! :)

Thanks in advance!

Post

WRodewald wrote:My stereo-delay effect updates both delay-lines ever sample, they are set to 100 to 1000ms, so [0,1] is scalled up to [100,900].

The problem I am having is that most parameters get smoothed with the low pass and there are no unwanted noises when moving gui-elements around, however the delay-effect sounds even more distorted then without any parameter smoothing.
From what you're saying, you're modulating the length of your delay line, yes? But what is changing the delay line length actually doing, algorithm wise? Are you making the buffer longer? If so, how? Changing the start/end points within a larger buffer? Changing the effective read rate on a fixed buffer size? What's catering for intermediate values (ie interpolation)? Yada yada.
Your delay line algorithm needs to cater for modulation of its length. Without knowing what you've done in that respect its kinda impossible to work out what's going wrong.
my other modular synth is a bugbrand

Post

Hi,

I use the synthesis toolkit for my low level signal processing. The setDelayLength()-function only calculates bounds and so on but doesn't realloc the buffer. Here is the docu for the delay-line: https://ccrma.stanford.edu/software/stk ... elayA.html

I use the same class with a chorus effect and it doesn't make problemce since the range is quite a bit shorter. It's an allpass-interpolation.

When I took a look on the parameters, the biggest jumps in delay-length (in samples) in the middle of the change was around 300 samples.

Here is the full function, the first part is a debug-only part I guess, debug isn't active right now and the delay length should be in bounds.

Code: Select all

void DelayA :: setDelay( StkFloat delay )
{
  unsigned long length = inputs_.size();
  if ( delay + 1 > length ) { // The value is too big.
    oStream_ << "DelayA::setDelay: argument (" << delay << ") greater than maximum!";
    handleError( StkError::WARNING ); return;
  }

  if ( delay < 0.5 ) {
    oStream_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
    handleError( StkError::WARNING );
  }

  StkFloat outPointer = inPoint_ - delay + 1.0;     // outPoint chases inpoint
  delay_ = delay;

  while ( outPointer < 0 )
    outPointer += length;  // modulo maximum length

  outPoint_ = (long) outPointer;         // integer part
  if ( outPoint_ == length ) outPoint_ = 0;
  alpha_ = 1.0 + outPoint_ - outPointer; // fractional part

  if ( alpha_ < 0.5 ) {
    // The optimal range for alpha is about 0.5 - 1.5 in order to
    // achieve the flattest phase delay response.
    outPoint_ += 1;
    if ( outPoint_ >= length ) outPoint_ -= length;
    alpha_ += (StkFloat) 1.0;
  }

  coeff_ = (1.0 - alpha_) / (1.0 + alpha_);  // coefficient for allpass
}

Post

make sure your one-pole LP is working properly
the "last" variable is its memory, which has to be remembered, so you cannot define it locally in the function
declare that variable as a member, and make sure to initialize its value on startup

and the coefficients for that filter.. you should know that the way they are hardcoded means that the speed of the LP filter would change if you change the sampling rate

you could calculate the coeffs as in frequency, using this formula:
b1 = exp(-2 * pi * (f/samplerate));
a0 = 1.0-b1;
"f" is the frequency in Hz.. for parameter smoothing, try somethings like 5 to 50Hz -ish... really, adjust to taste there
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!

irc.libera.chat >>> #kvr

Post

double-post. :/
Last edited by WRodewald on Wed Aug 13, 2014 5:37 pm, edited 1 time in total.

Post

Hi,

I have used exactly this calculation for the coefficients before but changed it to minimise possible problem sources. ;) Also, my sample Rate is fixed in the application (for now) so hardcoding the coefficients should do the trick for now.

The lowpass workes fine, there is barely any noise left from parameter change. Only the delay effect with the long delay line still makes problem.

Post

WRodewald wrote:Hi,

I have used exactly this calculation for the coefficients before but changed it to minimise possible problem sources. ;) Also, my sample Rate is fixed in the application (for now) so hardcoding the coefficients should do the trick for now.

The lowpass workes fine, there is barely any noise left from parameter change. Only the delay effect with the long delay line still makes problem.
Allpass interpolation is great for small delay changes and smooth modulation but it is an IIR filter, large delay changes will cause clicking. Your choices are: 1) Use a FIR interpolator, linear, hermite etc. 2) Duck the delay volume while changing. 3) Try to eliminate the clicks the hard way:

http://quod.lib.umich.edu/cgi/p/pod/dod ... 2.1995.096

Personally I'd just use option no.1.

Post

this could produce denormaling in the case where the parameter is reduced to zero. it sounds like you have some other factor acting on your length (...) as suggested scope, multithreading?
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

Hi,

sorry for the late response. I was working on the project, so It's basicly done right now.

I think I will switch to a linear interpolating delay line then. I realy have to learn more about the in depth dsp parts like this. ;)
@xoxos, I don't realy undderstand your post (english isn't my native language). The audio processing is done In a high prio thread which only doesn the signal processing.
Parameter changes are done in another thread. However, this thread only switches the parameter before it gets filtered. The actuall parameter change is done in the dsp-thread again. (I hope you know what I mean, not good in explaining stuff. :D)


Best regards

Post Reply

Return to “DSP and Plugin Development”