## Polynomial | Spline Interpolation for smoothing out sliders in JUCE++?

mystran
KVRAF

4927 posts since 11 Feb, 2006, from Helsinki, Finland
Nidnogg wrote:
Code: Select all
`for (int *sample = 0*; sample < bufferToFill.numSamples; ++sample)            {                float value = targetAmplitude * sin(2 * double_Pi * targetFrequency * time);                monoBuffer[sample] = value;                time += deltaTime;                            }`

Here's your problem: you are accumulating time, then multiplying it by frequency to get phase. When the frequency changes, the phase jumps around as the time gets scaled differently. When interpolating, this happens over some period of time, during which you just get garbage.

To fix the problem you need to accumulate phase instead, moving the frequency scaling into the running sum. This way the phase stays continuous without any jumps and the frequency then simply controls how fast the phase accumulates.

The result then looks something like this:
Code: Select all
`for ( .... ){   phase += targetFrequency;   float value = targetAmplitude * sin(2 * double_Pi * phase);   monoBuffer[sample] = value;}`

It's also worth keeping in mind that if you let the phase accumulate without any wrap-around, you'll run into numeric precision issues eventually (and if phase is single precision float, that happens sooner rather than later).

So normally you'd want to keep it within [0,1] range or something similar. One way to do that looks like this:
Code: Select all
`  phase += targetFrequency;  if(phase > 1) phase -= 1;`
<- plugins | forum
sault
KVRist

44 posts since 4 Sep, 2014
Okay, so you want to do interpolation between values. If you're talking specifically about parameter smoothing then one way to approach it would be to set up your control points like so -

<current value> .... parameter smoothing time ... <target value>

Any time the knob value is changed, that changes the target value. If you are working with 4 control points, like cubic interpolation, then use the target value twice, then you've got your current state value, then maybe use whatever the current value was some number of ms ago.

In other words, take the following cubic hermite interpolation function (again using RJS, written for clarity not optimization) -

// from http://www.xoxos.net/sem/dsp2public.pdf
// xoxos' formula has tension and bias set to 0

function hermite(x0,x1,x2,x3,mu)
instance(a,b,c,d,out)
(
a = ((3 * (x1- x2)) - x0 + x3) * 0.5;
b = x2 + x2 + x0 - (5*x1 + x3) * 0.5;
c = (x2 - x0) * 0.5;
d = mu;
out = ((a*d+b)*d+c)*d+x1;
);

Note that the interpolation is between the values in x1 and x2, and mu is the fractional interval between them.

on knob update

total_samples_until_update = (time_in_ms*0.001*samplerate);
prev_knob_value = current_knob_value;
sample_counter = 0;
frac = 0;

and each sample you could end up calling

current_knob_value = hermite(prev_knob_value,current_knob_value,target_knob_val,target_knob_val,frac);
sample_counter += 1;
frac = sample_counter/total_samples_until_update;
frac = min(frac,1);

So this is just sample code and there is definitely room for optimization, but this should be enough to get you on your way I think. If it was me doing this, I would consider graphing out different results using the different algorithms, whether using a real-time graphical display or via some kind of graphing utility.

If the end result is a presentation then the idea to graph out different functions with different interpolation algorithms is a good one. Including a spectral analysis of the result would be pretty boss, too, that way you could show why when quality is a factor you might use a 6-pt 3rd order interpolation algorithm rather than linear interpolation. You could even go one further and list the number of operations in each function to give another order of comparison, or the execution time of running each algorithm 1000 times, stuff like that.

I suggest checking out Oli's PDF on interpolation for some good examples of different algorithms. Keep in mind that his "optimal" algorithms don't preserve the control points, so are basically useless for this type of thing.

http://yehar.com/blog/wp-content/upload ... 8/deip.pdf
kamalmanzukie
KVRist

125 posts since 12 May, 2012
yeah, i had very similar problems trying to figure this out myself. i finally had what i thought was working, when someone posted these super simple equations for parabolic interpolation and i realized how badly id been overthinking it

this one is for peak amplitude at sample b: peakvalue = b + 0.5 * (0.5 * ((c - a) * (c - a))) / (2 * b - a - c)

this one is for fractional sample value of sample b: fraction = (0.5 * (c - a)) / ( 2. * b - a - c)

its from this site here, which is a terrific learning resource if you're starting out: http://www.katjaas.nl/helmholtz/helmholtz.html
Previous

Moderator: Moderators (Main)

Return to DSP and Plug-in Development

FEATURED
Advertisements