EZAudio:如何将缓冲区大小与 FFT 窗口大小分开(希望更高的频率 bin 分辨率)。

Posted

技术标签:

【中文标题】EZAudio:如何将缓冲区大小与 FFT 窗口大小分开(希望更高的频率 bin 分辨率)。【英文标题】:EZAudio: How do you separate the buffersize from the FFT window size(desire higher frequency bin resolution). 【发布时间】:2014-05-06 23:40:02 【问题描述】:

https://github.com/syedhali/EZAudio

我已经成功使用了这个音频库,但现在我想提高读入的麦克风数据的分辨率,以便 FFT 分辨率或频率箱大小降至 10Hz。为此,我需要 8820 而不是 512 的缓冲区大小。麦克风的缓冲区大小和 FFT 窗口大小是否可分离?我看不出有什么方法可以分开它。

如何设置音频流描述,以便计算更大窗口的 F​​FT?

任何帮助将不胜感激。

【问题讨论】:

您在一个分析周期中处理的样本数量与频率分辨率有内在联系。要获得更高的分辨率,您需要处理更多的样本。在 FFT 代码的上游,您可以根据需要缓冲任何内容,只要您向 FFT 代码提供所需数量的样本即可。 【参考方案1】:

FFT 大小和音频缓冲区大小应该完全独立。您可以只保存多个音频输入缓冲区(可能在循环 FIFO 或队列中),而无需处理它们,直到您有足够的样本来满足您所需的 FFT 长度。

以这种方式保存音频缓冲区还允许您对重叠帧进行 FFT 以获得更多时间分辨率。

【讨论】:

同意,我做了一个非 FIFO 解决方案,它可以工作,但 FIFO 缓冲区对于重叠窗口会更好。【参考方案2】:

浏览了链接项目的源代码后,音频回调似乎传递了一个缓冲区大小,该缓冲区大小是麦克风设备的首选缓冲区大小。我建议您在调用 FFT 之前缓冲所需数量的样本。以下代码修改自 EZAudioFFTExample 中的 FFTViewController.m:

#pragma mark - EZMicrophoneDelegate
-(void)    microphone:(EZMicrophone *)microphone
     hasAudioReceived:(float **)buffer
       withBufferSize:(UInt32)bufferSize
 withNumberOfChannels:(UInt32)numberOfChannels 
  dispatch_async(dispatch_get_main_queue(), ^

    // Update time domain plot
    [self.audioPlotTime updateBuffer:buffer[0]
                      withBufferSize:bufferSize];

    // Setup the FFT if it's not already setup
    if( !_isFFTSetup )
      [self createFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
      _isFFTSetup = YES;
    

    int samplesRemaining = bufferSize;
    while (samplesRemaining > 0)
    
        int samplestoCopy = max(bufferSize, FFTLEN - _fftBufIndex);
        memcpy(_fftBuf, buffer[0], samplesToCopy*sizeof(float));       
        _fftBufIndex += samplesToCopy;
        samplesRemaining -= samplesToCopy;

        if (_fftBufIndex == FFTLEN)
        
            _fftBufIndex = 0;
            [self updateFFTWithBufferSize:FFTLEN withAudioData:_fftBuf];
        
    
  );
 

在修改后的程序中,FFTLEN 是您定义的值,_fftBuf 是您分配的浮点数组,它需要保存FFTLEN 元素,_fftBufIndex 是跟踪写入位置的整数进入数组。

另外,我建议您在调用异步委托之前复制缓冲区参数。我之所以这么说是因为查看 EZMicrophone 的源代码,它看起来像是在回收缓冲区,所以你会有一个竞争条件。

【讨论】:

谢谢我修改了这段代码,现在我有一个工作的 FFT 窗口大小可选实现来获得你想要的 FFT res。包含在下面的答案中,因为我无法将其放入此评论部分。【参考方案3】:

感谢 Jaket 的建议。缓冲区是要走的路,这是我现在使用可调节 FFT 窗口对同一功能的工作实现:

    -(void)microphone:(EZMicrophone *)microphone
            hasAudioReceived:(float **)buffer
            withBufferSize:(UInt32)bufferSize
            withNumberOfChannels:(UInt32)numberOfChannels 

dispatch_async(dispatch_get_main_queue(),^

    [self.audioPlot updateBuffer:buffer[0] withBufferSize:bufferSize];

    // Decibel Calculation.
    float one       = 1.0;
    float meanVal   = 0.0;
    float tiny      = 0.1;
    vDSP_vsq(buffer[0], 1, buffer[0], 1, bufferSize);
    vDSP_meanv(buffer[0], 1, &meanVal, bufferSize);
    vDSP_vdbcon(&meanVal, 1, &one, &meanVal, 1, 1, 0);
    // Exponential moving average to dB level to only get continous sounds.
    float currentdb = 1.0 - (fabs(meanVal)/100);
    if (lastdbValue == INFINITY || lastdbValue == -INFINITY || isnan(lastdbValue)) 
        lastdbValue = 0.0;
    
    dbValue =   ((1.0 - tiny)*lastdbValue) + tiny*currentdb;
    lastdbValue = dbValue;
    // NSLog(@"dbval:  %f",dbValue);
    //
    // Setup the FFT if it's not already setup
    int samplestoCopy = fmin(bufferSize, FFTLEN - _fftBufIndex);
    for ( size_t i = 0; i < samplestoCopy; i++ ) 
        _fftBuf[_fftBufIndex+i] = buffer[0][i];
    
    _fftBufIndex        += samplestoCopy;
   _samplesRemaining    -= samplestoCopy;
    if (_fftBufIndex == FFTLEN) 
        if( !_isFFTSetup )
            [self createFFTWithBufferSize:FFTLEN withAudioData:_fftBuf];
            _isFFTSetup = YES;
        
        [self updateFFTWithBufferSize:FFTLEN withAudioData:_fftBuf];
        _fftBufIndex        = 0;
        _samplesRemaining   = FFTLEN;
     
);  

【讨论】:

你在哪里初始化 dbVal ,_fftBuf,samplesRemaining,lastdbValue 变量。请尽快回复

以上是关于EZAudio:如何将缓冲区大小与 FFT 窗口大小分开(希望更高的频率 bin 分辨率)。的主要内容,如果未能解决你的问题,请参考以下文章

DSP FFT基频wav文件

使用 EZAudio 从 FFT 获得更精确的频率?

FFT窗口大小的意义

EZAudio - 如何使用 EZAudioPlotGL 根据视图大小更改相同的波形大小

FFT 的窗口大小与数据长度

每 10 毫秒录制一次音频的音频缓冲区大小和 FFT 大小是多少?