【发布时间】:2016-03-19 17:55:45
【问题描述】:
我正在使用这个名为“The Amazing Audio Engine”的 GitHub 项目来从麦克风捕获音频。所以我用这个方法:
id<AEAudioReceiver> receiver = [AEBlockAudioReceiver audioReceiverWithBlock: ^(void *source, const AudioTimeStamp *time, UInt32 frames, AudioBufferList *audio) {
// Do something with 'audio'
}];
此方法每 23 毫秒触发一次,提供一个 audio 数组,其中包含该 23 毫秒间隔内声波的所有幅度。
这就是问题所在。我正在处理的这个音频声音是一个 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 不是我想要的,因为 a[5] 和 a[11] 会在 0.23 毫秒内给我 ~1000Hz 和 ~2000Hz 的幅度,但实际上我需要的都是1000 Hz 和 2000 Hz 声音的变化超过了 0.23ms 的时间。实际上我需要获取数组,而不是单个值。
概括地说,我应该怎么做才能获得两个频率(1000 和 2000 Hz)随时间变化的幅度?
【问题讨论】:
-
如果是FM,载波频率是多少?如果它只是分离两个频率,1kHZ 和 2Khz,你可以使用一个滤波器,它可能比 FFT 更有效。
标签: ios objective-c audio signal-processing