iOS FFT Accerelate.framework 在回放时绘制频谱

标签 ios fft frequency spectrum

2016 年 3 月 15 日更新

请看这个项目:https://github.com/ooper-shlab/aurioTouch2.0-Swift .它已移植到 Swift 并包含您正在寻找的所有答案,如果您来到这里。


我做了很多研究并学到了很多关于 FFT 和 Accelerate Framework 的知识。但经过几天的实验,我有点沮丧。

我想在图表中播放期间显示音频文件的频谱。对于每个时间间隔,它应该在 X 轴上通过 FFT 计算的每个频率(在我的例子中为 512 个值)在 Y 轴上显示以 db 为单位的幅度(由红色条显示)。

输出应该是这样的: enter image description here

我用 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;  
}

输出看起来总是有点奇怪,尽管它似乎会随着音乐移动。

我很高兴我能走到这一步,多亏了这里的一些非常好的帖子,比如: Using the apple FFT and accelerate Framework

但是现在我不知道该怎么办。我错过了什么?

最佳答案

首先,您没有申请 window function在 FFT 之前 - 由于 spectral leakage,这将导致频谱模糊.

其次,您只是使用 FFT 输出箱的实部来计算 dB 幅度 - 您需要使用复数幅度:

magnitude_dB = 10 * log10(re * re + im * im);

关于iOS FFT Accerelate.framework 在回放时绘制频谱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10636134/

相关文章:

ios - 在 ios 中绘制图像渐变

ios - 在 Swift 中导入扩展文件

iphone - IOS 如何在 MPMediaPickerController 中获取 IPHONE 中当前选定音轨的完整 URL

algorithm - Rutkowska 的位反转算法

android - 如何在android中生成准确的频率

iphone - 我需要在仪器上测试我的应用程序吗?

python - 为什么 scipy.fftpack.rfft 返回真实值?

iphone - 将Auriotouch线性刻度更改为对数

r - 如何折叠频率表的行以将其计数添加到新列中?

iPhone音频