Cubic Polynomial for inter-sample calculation


#1

Using cubic polynomial sounds pretty good to my ears when say my host is at 96khz and playing back 44.1khz audio

float interpolatedSample(float sm0, float sm1, float sm2, float sm3, float period)
{
    // quick win
    if(period==0)
    {
        return sm1;
    }

    float t = period;
    float u = 1 - t;
    float t2 = t * t;
    float u2 = u * u;
    float u3 = u2 * u;
    float t3 = t2 * t;
    
    // linear interoplation
    // float linear = ( sm1 * t ) + ( sm2 * u );
    
    // Cubic polynomial
    float rise = sm1 - sm0;
    float fall = sm3 - sm2;

    float curve =
    (u3) * sm1 +
    (3.0 * u2 * t) * (sm1 + rise) +
    (3.0 * u * t2) * (sm2 - fall) +
    (t3) * sm2;
    
    return curve;
}

where period = the period between samples sm1 and sm2
sm0 the history sample
sm3 is the next future sample

I use sm0 and sm3 to get the vectors for the audio curve.

I originally did this using a full on beizer curve but the trig functions was quite costly (but not unusable)…

Is there an easier win that I don’t know about. Quite happy with this solution if not.

To test

    for(float t=0;t<=1.01;t=t+0.1) {
        DBG(String(t) + " , " + String(interpolatedSample(0.49, 0.58,0.88,0.77, t)));
    }

#2

You know we have classes to do interpolation?
https://docs.juce.com/develop/classCatmullRomInterpolator.html
https://docs.juce.com/develop/classLagrangeInterpolator.html


#3

Yes but suffer from a classic case of not invented here syndrome :wink:

Actually I was aware of them but couldn’t see an obvious way to work with concurrent frames / windows (edge of group of samples with dirty overlap) without getting artefacts. There great for one time processes of audio but how do I work with them in chunks

X X X X X X X
| | | | | | | | | | | | |

Where x is sample and | is host sample rate there’s a an overlap which I don’t how to offset for


#4
double samplePos  = (positionInSeconds * sourceSampleRate / hostSampleRate);
double baseSamplePos = floor(samplePos);
double period = samplePos - baseSamplePos;

float sampleValue = interpolatedSample(samples[baseSamplePos-1], samples[baseSamplePos] ... period)

which gives me the sample at a position in-between any two samples in any buffer and I just manipulate positionInSeconds to suite. eg. playback speed and host sample rate independent.