UPDATE 2016-03-15
请看这个项目:https://github.com/ooper-shlab/aurioTouch2.0-Swift.它已经移植到Swift,并包含你要找的所有答案,如果你在这里凸轮.
我做了大量的研究,并学到了很多关于FFT和加速框架.但经过几天的实验,我感到很沮丧.
我想在图中播放时显示音频文件的频谱.对于每个时间间隔,应在X轴上通过FFT计算的每个频率(在我的情况下为512个值)中显示Y轴上的数值(以红色条显示).
输出应如下所示:
我填写一个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,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,stride,FFT_FORWARD);
- float scale = (float) 1.0 / (2 * n);
- vDSP_vsmul(A.realp,&scale,A.realp,nOver2);
- vDSP_vsmul(A.imagp,A.imagp,nOver2);
- vDSP_ztoc(&A,(COMPLEX *) obtainedReal,nOver2);
- FrequencyArry frequencyArray;
- for (int i = 0; i < nOver2; i++) {
- frequencyArray.frequency[i] = log10f(obtainedReal[i]); // Magnitude in db???
- }
- return frequencyArray;
- }
输出看起来总是有点奇怪,虽然它有些似乎根据音乐移动.
我很高兴我来到这么远,感谢一些非常好的帖子,像这样:
Using the apple FFT and accelerate Framework
但现在我不知道该怎么办我失踪了什么
解决方法
首先,在FFT之前您不应用
window function,这将导致
spectral leakage发生频谱的拖延.
其次,您正在使用FFT输出槽的实际分量来计算dB幅度 – 您需要使用复数幅度:
- magnitude_dB = 10 * log10(re * re + im * im);