Skip to content

Pitchshifting with FFT

March 20, 2012
tags: ,

Yesterday, I outlined a process for time-stretching a signal by interpolating between FFT frames in Reaktor. Today, I’ll explain how to pitch-shift using the FFT frequency detector I posted recently, and demonstrate how we can add it to the time-stretcher. The algorithm I’ll be using was outlined in this paper by Stephan Bernsee, a true titan of the DSP world.

The first step we must accomplish is calculating the true frequency  of each FFT bin. This is not too hard, and I’ve already outlined how to do it in my post on the FFT frequency detector. After this process is complete, we are left with three pieces of information – the FFT bin number, the amplitude of the sine wave, and the true frequency of the sine wave. Now that we know the pitch, we are ready to shift it.

The true frequencies and the bin number should be multiplied by the variable pitch shift value. The amplitudes do not change – we are changing the pitch after all. Both the amplitudes and the new frequencies can then be stored in an array using the new FFT bin we calculated. Once we have done this for an entire FFT frame, we can read the values we’ve stored out. We have to wait for a whole frame due to the lack of iteration in core and the nature of the ezFFT modules. This means that implementing this algorithm in Reaktor will impose an extra 512 samples of latency.  Here’s what all of this looks like:

The copy-erase modules do exactly that – The copy the Buf array into the Out array, and then erase all the data in the Buf array. What comes out of these arrays is the amplitudes and true frequencies, shifted in position. Now we can just undo the frequency detection math we did earlier and plug it all into iFFT and we’re done! Undoing the math:

Calculate the phase difference from the true frequency

Now we have the phase difference and the amplitude values, we simply add the phase difference to the phase from 512 samples ago (remember we’re latent by a whole FFT cycle at this point). Now we convert from polar form back to Cartesian coordinates, (the pol2Vec macro that comes as part of the ezFFT package) and run send it to an iFFT.

Here’s a sample of the sound. I play around with some octave jumps and then start time-stretching as well as pitch-shifting to demonstrate the two together.

Download a sample ensemble.

Simple Instructions:

Turn off On button

Load a file

Press Read button

Wait a second

Then press On, and play with the knobs

Let me know if you do anything cool with it!

5 Comments leave one →
  1. rickyeffe permalink
    July 9, 2012 6:17 am

    the pitch shift parts makes the sound play worse even when pitch is equal to 0, i’ve tried on a 2048 band fft and still that routing changes the quality, if i bypass and use only timestretch the quality is perfect. am i missing something ?

    • July 9, 2012 8:19 am

      hmm, i tested this mainly on laptop speakers. the obvious workaround is that if the pitch is to stay the same, simply bypass the pitchshift routing in core.

      • rickyeffe permalink
        July 10, 2012 4:14 am

        well, it would be nice to be able to use it, about timestretch i found that is very granular, i though that using fft results will be much better in terms of quality. I was thinking about finding loop transients and then do an incremental timestretch, for example, if i want to make it longer at 0.75, at transient point is 1 then it goes down to 0.5 until the next transient, and so on, in this way the transients should play fine… is it possible to reach that precision or is somewhat limited by frame size ?

      • July 10, 2012 8:05 am

        Sorry I’m not sure what you mean.
        These guys have a granular pitchshift/timestretch in reaktor that you can have a look at if this one doesn’t work for you:


  1. Timestretch in Real Time « salamanderangram

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: