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!

To pitch shift, as others have said, you’ll need to make sure you output the same number of samples as is the buffer size (input size).

Generally, you want to find the base frequency, then duplicate or reduce the waves at that frequency. It can be a little complicated to get right, I think. You can to smooth the edges of the redundancy, like using a Hanning window or similar.

http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
^ This might be a good base to work from when pitch-shifting.

1 Like

Nearly 23 years old, on an outdated site (not yet converted to https) - very nice to offer input, but science and technology make big steps in 23 years…

The most concise implementation of granular (aka overlap-add) pitch shifting that I know of is ef.transpose from the Faust standard library. No fancy pitch-synchronization or nothing, but it still sounds decent. Might be a useful reference if you don’t mind functional code :wink:

//--------------`(ef.)transpose`----------------
// A simple pitch shifter based on 2 delay lines.
// `transpose` is a standard Faust function.
//
// #### Usage
//
// ```
// _ : transpose(w, x, s) : _
// ```
//
// Where:
//
// * `w`: the window length (samples)
// * `x`: crossfade duration duration (samples)
// * `s`: shift (semitones)
//-----------------------------------------
transpose(w, x, s, sig) = de.fdelay(maxDelay,d,sig)*ma.fmin(d/x,1) +
	de.fdelay(maxDelay,d+w,sig)*(1-ma.fmin(d/x,1))
with {
	maxDelay = 65536;
	i = 1 - pow(2, s/12);
	d = i : (+ : +(w) : fmod(_,w)) ~ _;
};
2 Likes

I found it to be an interesting article and website in general. The article is well written, there’s a good discussion in the comments and source code is included too. As far as I can see it’s quite instructive.

Could you explain which concepts discussed in the article have become outdated and which are the “big steps” which science and technology have made since? Could you provide an up-to-date example?

@aamf It’s spillover from Extreme danger of perforating eardrum from audioDeviceIOCallback

He embarrassed himself over my post, and now seems bent upon belittling me in the hope it will restore his sense of pride. It’s childish & he appears to lack the self-awareness to break pattern.

But let’s see… life is growth!

“I say never be complete, I say stop being perfect, I say let… let’s evolve, let the chips fall where they may.” (Tyler Durden)

Good to see the nonsense called out. 0% BS community FTW. :muscle: