LagrangeInterpolator sounds weird when I try to implement it in SamplerVoice

Hi, I tried to implement Lagrange interpolation in a SamplerVoice inherited class replacing this:

     while (--numSamples >= 0)
    {
        auto pos = (int) sourceSamplePosition;
        auto alpha = (float) (sourceSamplePosition - pos);
        auto invAlpha = 1.0f - alpha;

        // just using a very simple linear interpolation here..
        float l = (inL[pos] * invAlpha + inL[pos + 1] * alpha);

       
        sourceSamplePosition += pitchRatio;
    }

By somethine like this:

        leftInterpolator.processAdding(pitchRatio, inL + (int)(sourceSamplePosition), outL, numSamples, 1.0f);
       sourceSamplePosition += numSamples * pitchRatio;

But it produces strange artifacts when playing. I’m sure I’m doing something wrong, but I ignore the reason.

I’m playing an upgraded to 96Khz sine wave sample (using the same Lagrange class, which works fine here), and then resampling it to 44.1Khz in the code used before.

Please, could someone point me in the right direction?

You need to render the amount of samples into the resampler based on the resampling factor, then produce the true numSamplesNeeded.

So if you wanted to go from 88.2k to 44.1k

for (int sample = 0; sample < numSample * 2; sample++) {
  in[sample] = sampleAt88.2k[readhead]
  readhead += 1 // or your "pitchRatio"
}

interpolator.process(2, in, out, numSamples)

Apologies if i’m mistaken reading your source code and this is the approach, but it looks like pitchRatio is somehow being used as a factor in resampling. you should iterate through your source by 1 and resample at the ratio (sourceRate / sampleRate) – to render it at the same pitch. In any case your desired pitch change / speed you go through the source buffer, doesn’t have much to do with you resampling factor

1 Like

Thank you for the reply @Jake_Penn :slight_smile:

Well, the solution was… embarrassing… the weird things I was listening was the host clipping… The piece of code I placed originally seems work fine.

Juan could you provide the full code?
I am also hearing artifacts. I believe because of the casting of the sourceSamplePosition from float to int. I think the “quantising” introduces little clicks each render of a block…

Hi @dataexcessaudio, the juce interpolator store these remaining decimals inside a variable to use it in the next call. I had a lot of problems with the interpolators (non-related to juce) and I ended creating one myself, based on hermite. But the main point here is it works in the same way. This how I do the call, and as you see, I’m casting a double variable (inPos) to int too:

           const int inPos32 = static_cast<int>(inPos);
           for (int c=0; c!=numOutChannels; ++c)
           {
              SampleType* outBuffer = block.getChannelPointer(c);
              const SampleType* inBuffer = m_playedSample.m_sampleData[c];
              m_interpolators[c].process(m_inputAdvance, inBuffer + inPos32, outBuffer + s, n);
           }

Nice.

I actually already fixed it. The problem I was having was the fractional offset caused by the fractional ratio. I had to recalculate the input buffer to account for the fractional part. Shifting all the values so to speak. I’ve put my answer in this thread if you’re interested: