【发布时间】:2014-01-26 15:25:24
【问题描述】:
我目前正在使用此处的 FFT 代码: https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/iOS/EZAudioFFTExample
以下是 2 个相关方法的代码:
-(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// Setup the length
_log2n = log2f(bufferSize);
// Calculate the weights array. This is a one-off operation.
_FFTSetup = vDSP_create_fftsetup(_log2n, FFT_RADIX2);
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Populate *window with the values for a hamming window function
float *window = (float *)malloc(sizeof(float)*bufferSize);
vDSP_hamm_window(window, bufferSize, 0);
// Window the samples
vDSP_vmul(data, 1, window, 1, data, 1, bufferSize);
free(window);
// Define complex buffer
_A.realp = (float *) malloc(nOver2*sizeof(float));
_A.imagp = (float *) malloc(nOver2*sizeof(float));
}
-(void)updateFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Pack samples:
// C(re) -> A[n], C(im) -> A[n+1]
vDSP_ctoz((COMPLEX*)data, 2, &_A, 1, nOver2);
// Perform a forward FFT using fftSetup and A
// Results are returned in A
vDSP_fft_zrip(_FFTSetup, &_A, 1, _log2n, FFT_FORWARD);
// Convert COMPLEX_SPLIT A result to magnitudes
float amp[nOver2];
float maxMag = 0;
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
maxMag = mag > maxMag ? mag : maxMag;
}
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
// Bind the value to be less than 1.0 to fit in the graph
amp[i] = [EZAudio MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
我已经修改了上面的 updateFFTWithBufferSize 方法,这样我就可以像这样获得以赫兹为单位的频率:
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
if(maxMag < mag) {
_i_max = i;
}
maxMag = mag > maxMag ? mag : maxMag;
}
float frequency = _i_max / bufferSize * 44100;
NSLog(@"FREQUENCY: %f", frequency);
我已经用 Audacity 在不同的频率下生成了一些纯正弦音来进行测试。我看到的问题是代码为两个值相对接近的不同正弦音返回相同的频率。
例如: 以 19255Hz 生成的正弦音将从 FFT 显示为 19293.750000Hz。以 19330Hz 产生的正弦音也是如此。计算中一定有问题。
对于如何修改上述代码以获得更精确的纯正弦音 FFT 频率读数的任何帮助,我们将不胜感激。 谢谢!
【问题讨论】:
-
由于我的声音的采样率为 44.1KHz,看起来频率分辨率将在 20000 / 256 bins 左右,即 78.125。所以这就是为什么我不能得到一个特定的频率,只有那个 78 范围内的一个。还有其他方法可以更具体地了解正弦音吗?
-
如果您列出相关数字会有所帮助,例如:buffer_size、分辨率等。
-
我猜我的缓冲区大小目前是 512。我将在哪里/如何增加它?
-
您的频率分辨率将受到采样频率和缓冲区大小的限制。
-
你好 Codeman,你能把修改后的增加缓冲区大小的代码发给我吗(我面临着类似的问题,我已经研究了一个月了)
标签: ios objective-c audio signal-processing fft