EZAudio:如何从FFT窗口大小(希望更高的频率分辨率)中分离缓冲区大小。

https://github.com/syedhali/EZAudio

我已经成功地使用了这个audio库,但是现在我想提高读入的麦克风数据的分辨率,以便FFT分辨率或频率分辨率降低到10Hz。 要做到这一点,我需要一个缓冲区大小为8820而不是512.麦克风的缓冲区大小和FFT窗口大小是否可分开? 我看不到一个方法来分开它。

如何设置audiostream描述,以便能够用更大的窗口计算FFT?

任何帮助将非常感激。

FFT大小和audio缓冲区大小应该完全独立。 您可以保存多个audioinput缓冲区(可能在一个循环的FIFO或队列中),而不需要处理它们,直到有足够的样本用于所需长度的FFT。

以这种方式保存audio缓冲区还可以使FFT重叠帧获得更多的时间分辨率。

浏览了链接项目的源代码之后,似乎audiocallback会传递一个缓冲区大小,该大小是麦克风设备的首选缓冲区大小。 我build议你在调用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是一个整数,用于跟踪写入数组的位置。

另外,我build议你在调用asynchronous委托之前制作一个buffer参数的副本。 我之所以这样说是因为看EZMicrophone的来源,它看起来像回收缓冲区,所以你会有一个竞争条件。

感谢Jaket的build议。 缓冲是要走的路,这里是我的工作实现相同的function现在与可调整的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; } }); 

}