Auriotouch,从频率FFT获取音符

4

我正在开发一种吉他调音器。

我有一个可以给我FFT以及每个频率的FFT值的函数。

那么我该如何从中得到音符呢?我需要选择最高峰吗?

 for(y=0; y<maxY; y++){


    CGFloat yFract = (CGFloat)y / (CGFloat)(maxY - 1);          

    CGFloat fftIdx = yFract * ((CGFloat)fftLength);
    double fftIdx_i,fftIdx_f;
    fftIdx_f = modf(fftIdx, &fftIdx_i);

    SInt8 fft_l, fft_r;
    CGFloat fft_l_fl, fft_r_fl;
    CGFloat interpVal;

    fft_l = (fftData[(int)fftIdx_i] & 0xFF000000) >> 24;
    fft_r = (fftData[(int)fftIdx_i + 1] & 0xFF000000) >> 24;


    fft_l_fl = (CGFloat)(fft_l + 80) / 64.;
    fft_r_fl = (CGFloat)(fft_r + 80) / 64.;
    interpVal = fft_l_fl * (1. - fftIdx_f) + fft_r_fl * fftIdx_f;
    interpVal = CLAMP(0., interpVal, 1.);


    drawBuffers[0][y] = (interpVal * 120);
    //NSLog(@"The magnitude for %f Hz is %f.", (yFract * hwSampleRate * .5), (interpVal * 120));

}

Thanks a lot if you can help.

Julien.


在 SO 上已经有很多关于使用 FFT 等算法对乐器进行音高检测的问题和答案了,你可能想回去读一些这些问题,因为它们涵盖了这种任务的许多“常见问题”。似乎很多人正在尝试为 iPhone 和其他移动设备编写吉他调音器... - Paul R
1个回答

3
这是一个相当棘手的问题,原因如下:
  • 峰值可能不对应基波(甚至可能缺失)。
  • 基波很可能不会精确落在FFT bin的中心,因此它的能量将分布在多个bin上。您需要进行插值以估算实际频率。
  • 除非进行某种窗口处理,否则会出现“频谱泄漏”效应,这会使您的频谱扩散到各个地方,使细节难以辨别。
我知道这并没有真正回答你的问题,但这应该强调这实际上是一件相当棘手的事情。

谢谢您的快速回答。 我已经在应用加权窗口。 您如何找到基本波? - Neva
你需要进行插值,否则会出现“频谱泄漏”的困难问题。建议查看“Slepian窗口法”以获得可靠的频谱估计。 - Alexandre C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接