Simple(st) pitch shift with interpolator?

I am trying my luck with Interpolators but can’t seem to nail it (I’m a noob, I know).

I want to do a very simple pitch shift process resampling the sound, and no matter what I try, I always get constant pops.

In short, I copy my buffer to a tmp, and then I process a Linear interpolator using a ratio. If I use a 1.0 ratio, all is well, but if I move (above or below) I can hear the pitch changing, but completely surrounded by pops.

below is a very short summary of what I’m doing:

        juce::Interpolators::Linear interpolator;
        tmpBuffer.copyFrom(0, 0, buffer, 0, 0, buffer.getNumSamples());
        interpolator.process(ratio, tmpBuffer.getReadPointer(0), buffer.getWritePointer(0), buffer.getNumSamples());

Any help?

If your ratio is > 1.0, then you’ll raise the pitch of the input, but have silence in the output buffer when it ran out of input = pops (when the block size is small enough, if you had a large enough block size you’d notice this more as glitching instead of popping).

If your ratio is < 1.0, then you’ll fill the output buffer before using all the input for that block, then next block will have a discontinuity in the wave = pops.

That was my thought - so I guess new “new buffer size” is also numSamples * ratio, is that correct?

is there any (simple) way to make the buffers “fit”? or is there any other way to resample to change the pitch of a sound?

a linear interpolation pitchshifter will definitely sound very grainy, unless you’re on a very high samplerate. if those pops are regular you are either making a mistake about the block processing or it’s just the pitchshifter’s architecture itself. is this running in realtime?

Yeah just as a “vst insert”. The code above pretty much is all, I was wondering if there was a quick way to resample and wrote those lines, but its incredibly poppy

then it is the clear. as you already noticed it would make sense to have a different number of samples in the output. but that is not possible in realtime. input buffer is output buffer. so shift your thought away from that and instead ask yourself how to make a resampler that stays inside numSamples, but still fills up a grain in its total size everytime. you can do that with a ring buffer. you’ll still get pops then, but for a different reason. it will be about making sure the grain always loops in a smooth way.

more infos on ring buffers in my delay video:

and i released an open source pitch shifter just yesterday which you could check out:

1 Like

Oh wow, thank you so much for this! It indeed looks much more complex from what I thought!

I’ll check the resources you shared! Thanks!

Best,

Not sure if this will help, but I came across this post yesterday which uses the LagrangeInterpolator
for resampling:

1 Like

sry if my pitchshifter looks a bit complicated. it’s just that i added some unique features like the feedback parameter. and you can also ignore this whole multiple-voices-stuff and all the parameter-smoothing things to make it easier

1 Like

Thank you! Will give it a check :slight_smile:

In case it wasn’t clear from the previous posts:

An Interpolator / Resampler is not sufficient for pitch shifting.
While it changes the pitch, it also changes the number of samples, i.e. the duration. In a streaming plugin that VST3 and AUs etc. are, you have to deliver the same amount of samples as you received.

@asimilon described in his first answer what happens: on each block you are either discarding additional samples creating a discontinuity in the signal, or you are zero-padding (if you are lucky, or leaving garbage from the input signal if you are unlucky), which is also creating the noise you are hearing.

A real pitch shifter like the one @Mrugalla posted needs to fill the gaps or smoothen the discontinuities using fragemnts (grains) of the signal which they duplicate and arrange as needed.
Depending on the strategy of restoring the continuous signal from the fragments the result will sound better or artificial.

2 Likes

Yep got it! Thanks a lot!