我使用Novocaine框架进行音高检测。一切运行良好 - 只有图形FFT表示,有一些麻烦。
当我使用音频文件进行输入时,FFT工作正常 - 低于100 Hz的频率可以完美显示。
相反,当我使用麦克风作为输入时,100 Hz以下的频率根本没有显示 - 我无法弄清楚原因!见下面的截图:
正确显示更高的频率(例如1000 Hz)!
这里是FFT程序的源代码:
- (NSMutableArray*)performFFT: (float*) data withFrames: (int) numSamples {
// 1. init
float bufferSize = numSamples;
uint32_t maxFrames = numSamples;
displayData = (float*)malloc(maxFrames*sizeof(float));
bzero(displayData, maxFrames*sizeof(float));
int log2n = log2f(maxFrames);
int n = 1 << log2n;
assert(n == maxFrames);
float nOver2 = maxFrames/2;
A.realp = (float*)malloc(nOver2 * sizeof(float));
A.imagp = (float*)malloc(nOver2 * sizeof(float));
fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
// 2. calcuate
bufferSize = numSamples;
float ln = log2f(numSamples);
vDSP_ctoz((COMPLEX*)data, 2, &A, 1, numSamples/2);
//fft
vDSP_fft_zrip(fftSetup, &A, 1, ln, FFT_FORWARD);
// Absolute square (equivalent to mag^2)
vDSP_zvmags(&A, 1, A.realp, 1, numSamples/2);
// make imaginary part to zero in order to filter them out in the following loop
bzero(A.imagp, (numSamples/2) * sizeof(float));
//convert complex split to real
vDSP_ztoc(&A, 1, (COMPLEX*)displayData, 2, numSamples/2);
// Normalize
float scale = 1.f/displayData[0];
vDSP_vsmul(displayData, 1, &scale, displayData, 1, numSamples);
//scale fft
Float32 mFFTNormFactor = 1.0/(2*numSamples);
vDSP_vsmul(A.realp, 1, &mFFTNormFactor, A.realp, 1, numSamples/2);
vDSP_vsmul(A.imagp, 1, &mFFTNormFactor, A.imagp, 1, numSamples/2);
...
}
&#13;
对于更多图形问题,我使用 displayData 。
由于我对较低的频率感兴趣(有一个单独的音调检测算法工作正常),我将采样率降低到11.025(而不是44100)。
在诺沃卡因内,我拨打以下电话:
1)输入
[audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
// frequency analysis
vDSP_rmsqv(data, 1, &magnitude, numFrames*numChannels);
self->ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
...
}
&#13;
2)输出:
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
self->ringBuffer->FetchInterleavedData(data, numFrames, numChannels);
....
[fft performFFT:data withFrames:numFrames];
...
}
&#13;
有人有想法吗?
答案 0 :(得分:1)
这是因为内置麦克风是一个电容式麦克风,并配有一个高通滤波器,用于消除信号上的直流偏置。
可以禁用HPF。直流偏置不是什么大问题,因为它只会在FFT的#2中出现。
[[AVAudioSession sharedInstance] setMode: AVAudioSessionModeMeasurement error:NULL];
另请注意,FFT的窗口化也会影响FFT的低频区间的精度。对于任何给定频率,窗口中至少需要2 * PI样本。
答案 1 :(得分:0)
音高与频谱频率不同。低音调声音通常由谐波和泛音能量组成,并且在基频处没有太多能量。因此,FFT也找不到多少。在找到这些类型的富含谐波的声音的音高时,自相关稍微好一些。
除此之外,iPhone麦克风对低频能量的敏感度不如中高音频(在线audio response graphs)。
另请注意,FFT缓冲器需要按比例更长,以获得低频内容的等效百分比(以美分为单位的回音间距)。低频分辨率通常需要远远超过iOS音频单元提供的任何单个缓冲区的FFT。