Extracting precise frequencies from FFT Bins using phase change between frames

前端 未结 6 2358
南方客
南方客 2020-12-12 16:05

I have been looking through this fantastic article: http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/

While being fantastic, it is extremely hard and he

6条回答
  •  南方客
    南方客 (楼主)
    2020-12-12 16:16

    I have implemented this algorithm for Performous myself. When you take another FFT at a time offset, you expect the phase to change according to the offset, i.e. two FFTs taken 256 samples apart should have a phase difference of 256 samples for all frequencies present in the signal (this assumes that the signals themselves are steady, which is a good assumption for short periods like 256 samples).

    Now, the actual phase values you get from FFT are not in samples but in phase angle, so they will be different depending on the frequency. In the following code the phaseStep value is the conversion factor needed per bin, i.e. for frequency corresponding to bin x, the phase shift will be x * phaseStep. For bin center frequencies x would be an integer (the bin number) but for actual detected frequencies it may be any real number.

    const double freqPerBin = SAMPLE_RATE / FFT_N;
    const double phaseStep = 2.0 * M_PI * FFT_STEP / FFT_N;
    

    The correction works by assuming that the signal in a bin has the bin center frequency and then calculating the expected phase shift for that. This expected shift is substracted from the actual shift, leaving the error. A remainder (modulo 2 pi) is taken (-pi to pi range) and the final frequency is calculated with bin center + correction.

    // process phase difference
    double delta = phase - m_fftLastPhase[k];
    m_fftLastPhase[k] = phase;
    delta -= k * phaseStep;  // subtract expected phase difference
    delta = remainder(delta, 2.0 * M_PI);  // map delta phase into +/- M_PI interval
    delta /= phaseStep;  // calculate diff from bin center frequency
    double freq = (k + delta) * freqPerBin;  // calculate the true frequency
    

    Notice that many adjacent bins often end up corrected to the same frequency because the delta correction can be up to 0.5 * FFT_N / FFT_STEP bins either way so the smaller FFT_STEP you use, the further away will corrections be possible (but this increases the processing power needed as well as imprecision due to inaccuracies).

    I hope this helps :)

提交回复
热议问题