IOS 和 FFT (vDSP_fft_zrip) : frequencies below appr. 100 Hz 被切断 - 为什么?

标签 ios audio core-audio

我正在使用 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);

...
}

对于进一步的图形问题,我使用displayData

由于我对较低频率感兴趣(有一个单独的音调检测算法可以正常工作),因此我将采样率降低到 11.025(而不是 44100)。

在 Novocaine 中,我进行了以下调用:

1) 输入

[audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
            
            // frequency analysis
            vDSP_rmsqv(data, 1, &magnitude, numFrames*numChannels);
            self->ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
...
}

2)输出:

[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
     { 
   self->ringBuffer->FetchInterleavedData(data, numFrames, numChannels);
   ....
   [fft performFFT:data withFrames:numFrames];
   ...
   }

有人有想法吗?

最佳答案

这是因为内置麦克风是电容麦克风,并且具有高通滤波器,可以消除信号上的直流偏置。

可以禁用 HPF。 DC 偏置并不是什么大问题,因为它只会出现在 FFT 的 bin #0 中。

[[AVAudioSession sharedInstance] setMode: AVAudioSessionModeMeasurement error:NULL];

另请注意,FFT 的加窗也会影响 FFT 低频箱的准确性。对于任何给定频率,窗口中至少需要 2*PI 的样本。

关于IOS 和 FFT (vDSP_fft_zrip) : frequencies below appr. 100 Hz 被切断 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30934971/

相关文章:

android - Google Plus Android GoogleAuthUtil.getToken() 等效于 iOS

iphone - 将 AUConverter 添加到 AUGraph 时出现错误 -10877

ios - 使用 AudioBufferList 添加释放时间以生成正弦波

ios - AudioUnit "Sometime"不工作。 "Only"发生在 6 秒(可能是 6 秒以上,但我没有测试过)

android - 在 React Native 中保存和共享项目 Assets 中的图像

objective-c - 将 UIImageView 向下发送回 1 层

ios - UITableView、搜索栏和部分索引

java - 如何获取视频/音频信息,例如持续时间和高度?

java - 向Mediaplayer添加音频时出现异常

使用 Phonegap/Cordova 收听声音和记录音量的 Android 应用程序