更新2016-03-15
请看一下这个项目:https://github.com/ooper-shlab/aurioTouch2.0-Swift https://github.com/ooper-shlab/aurioTouch2.0-Swift。它已被移植到 Swift,并且包含您正在寻找的所有答案(如果您来到这里)。
我做了很多研究,了解了很多有关 FFT 和加速框架的知识。但经过几天的实验,我有点沮丧。
我想在图表中显示音频文件播放过程中的频谱。对于每个时间间隔,它应该在 X 轴上通过 FFT 计算出的每个频率(在我的例子中为 512 个值)在 Y 轴上(以红色条显示)显示以 db 为单位的幅度。
The output should look like this:
我用 1024 个样本填充缓冲区,开始时仅提取左通道。然后我做所有这些 FFT 的事情。
到目前为止,这是我的代码:
设置一些变量
- (void)setupVars
{
maxSamples = 1024;
log2n = log2f(maxSamples);
n = 1 << log2n;
stride = 1;
nOver2 = maxSamples/2;
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
memset(A.imagp, 0, nOver2 * sizeof(float));
obtainedReal = (float *) malloc(n * sizeof(float));
originalReal = (float *) malloc(n * sizeof(float));
setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);
}
进行 FFT。 FrequencyArray 只是一个保存 512 个浮点值的数据结构。
- (FrequencyArry)performFastFourierTransformForSampleData:(SInt16*)sampleData andSampleRate:(UInt16)sampleRate
{
NSLog(@"log2n %i n %i, nOver2 %i", log2n, n, nOver2);
// n = 1024
// log2n 10
// nOver2 = 512
for (int i = 0; i < n; i++) {
originalReal[i] = (float) sampleData[i];
}
vDSP_ctoz((COMPLEX *) originalReal, 2, &A, 1, nOver2);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
float scale = (float) 1.0 / (2 * n);
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);
vDSP_ztoc(&A, 1, (COMPLEX *) obtainedReal, 2, nOver2);
FrequencyArry frequencyArray;
for (int i = 0; i < nOver2; i++) {
frequencyArray.frequency[i] = log10f(obtainedReal[i]); // Magnitude in db???
}
return frequencyArray;
}
输出看起来总是有点奇怪,尽管它似乎根据音乐移动。
我很高兴能够走到这里,感谢这里的一些非常好的帖子,如下所示:使用苹果FFT和加速框架 https://stackoverflow.com/questions/3398753/using-the-apple-fft-and-accelerate-framework
但现在我不知道该怎么办。我缺少什么?