簡體   English   中英

EZAudio:如何將緩沖區大小與FFT窗口大小分開(需要更高頻率的頻段分辨率)。

[英]EZAudio: How do you separate the buffersize from the FFT window size(desire higher frequency bin resolution).

https://github.com/syedhali/EZAudio

我已經成功使用了該音頻庫,但現在我想提高讀入的麥克風數據的分辨率,以使FFT分辨率或頻點大小降至10Hz。 為此,我需要8820而不是512的緩沖區大小。麥克風的緩沖區大小和FFT窗口大小是否可分離? 我看不到將其分開的方法。

如何設置音頻流描述,以便可以在更大的窗口中計算FFT?

任何幫助將非常感激。

FFT大小和音頻緩沖區大小應完全獨立。 您可以僅保存多個音頻輸入緩沖區(也許在循環FIFO或隊列中),而無需處理它們,直到您有足夠的樣本以達到所需的長度FFT。

通過這種方式保存音頻緩沖區,還可以對重疊的幀進行FFT,以獲得更高的時間分辨率。

瀏覽了鏈接項目的源之后,似乎音頻回調傳遞的緩沖區大小是麥克風設備的首選緩沖區大小。 我建議您在調用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是一個整數以跟蹤寫入數組的位置。

另外,我建議您在調用異步委托之前復制buffer參數。 我說這的原因是因為查看EZMicrophone的來源似乎是在回收緩沖區,所以您將遇到競爭狀況。

感謝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;
    } 
});  

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM