随时间推移获得两个频率的幅度

时间:2015-12-14 09:47:47

标签: ios objective-c audio signal-processing

我正在使用这个名为“The Amazing Audio Engine”的GitHub项目,从麦克风中捕获音频。所以我使用这种方法:

id<AEAudioReceiver> receiver = [AEBlockAudioReceiver audioReceiverWithBlock: ^(void *source, const AudioTimeStamp *time, UInt32 frames, AudioBufferList *audio) {
 // Do something with 'audio'
}];

此方法每隔23 ms触发一次audio数组,其中包含23 ms间隔内所有声波幅度。

这是一个问题。我正在处理的这种音频声音是一个FM信号,由两个频率组成,一个频率为1000 Hz,另一个频率为频率的两倍,代表零和一个数字流。

这是我的问题。那时我有一个超过0.23毫秒的音频幅度阵列。

所以我想我可以做一个FFT来将信号转换成频率水平。我用了这段代码:

 // Setup the length
 vDSP_Length log2n = log2f(numFrames);

 // Calculate the weights array. This is a one-off operation.
 FFTSetup fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);

 // For an FFT, numSamples must be a power of 2, i.e. is always even
 int nOver2 = numFrames/2;

 // Populate *window with the values for a hamming window function
 float *window = (float *)malloc(sizeof(float) * numFrames);
 vDSP_hamm_window(window, numFrames, 0);
 // Window the samples
 vDSP_vmul(data, 1, window, 1, data, 1, numFrames);

 // Define complex buffer
 COMPLEX_SPLIT A;
 A.realp = (float *) malloc(nOver2*sizeof(float));
 A.imagp = (float *) malloc(nOver2*sizeof(float));

 // Pack samples:
 // C(re) -> A[n], C(im) -> A[n+1]
 vDSP_ctoz((COMPLEX*)data, 2, &A, 1, numFrames/2);


 // RUN THE FFT
 //Perform a forward FFT using fftSetup and A
 //Results are returned in A
 vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);

因为每个间隔是172 Hz,我想隔离1000Hz,我认为FFT结果的第6个“桶”就是那个,所以我有这个代码:

 //Convert COMPLEX_SPLIT A result to magnitudes
 float amp[numFrames];
 amp[0] = A.realp[0]/(numFrames*2);

 for(int i=1; i<numFrames; i++) {
   amp[i]=A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i];
 }

 // I need the 6th and the 12th bucket, so I need a[5] and a[11]

然后我开始认为FFT不是我想要的,因为[5]和[11]会在0.23 ms内给出~1000Hz和~2000Hz的幅度,但实际上我需要的是全部1000赫兹和2000赫兹声音的变化超过0.23毫秒。实际上我需要获取数组,而不是单个值。

粗略地说,我应该怎样做才能获得两个频率1000和2000 Hz的振幅?

1 个答案:

答案 0 :(得分:1)

如果您知道自己想要什么样的时间分辨率,那么按照该长度滑动的两个Goertzel滤波器将允许您以比使用FFT更少的开销来测量两个频率的幅度。滤波器或FFT的长度不需要(通常不应该)与每个音频回调的帧数相同。您可以使用循环缓冲区或fifo来解耦长度。 (在iOS中,numFrames在不同的设备型号上可能会有所不同,并且可能会根据应用程序控件之外的其他因素而突然发生变化)。