Я в настоящее время использую код FFT здесь: https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/iOS/EZAudioFFTExampleБолее точная частота от FFT с чисто синусоидальными тонами
Вот код из 2 соответствующих методов:
-(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// Setup the length
_log2n = log2f(bufferSize);
// Calculate the weights array. This is a one-off operation.
_FFTSetup = vDSP_create_fftsetup(_log2n, FFT_RADIX2);
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Populate *window with the values for a hamming window function
float *window = (float *)malloc(sizeof(float)*bufferSize);
vDSP_hamm_window(window, bufferSize, 0);
// Window the samples
vDSP_vmul(data, 1, window, 1, data, 1, bufferSize);
free(window);
// Define complex buffer
_A.realp = (float *) malloc(nOver2*sizeof(float));
_A.imagp = (float *) malloc(nOver2*sizeof(float));
}
-(void)updateFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Pack samples:
// C(re) -> A[n], C(im) -> A[n+1]
vDSP_ctoz((COMPLEX*)data, 2, &_A, 1, nOver2);
// Perform a forward FFT using fftSetup and A
// Results are returned in A
vDSP_fft_zrip(_FFTSetup, &_A, 1, _log2n, FFT_FORWARD);
// Convert COMPLEX_SPLIT A result to magnitudes
float amp[nOver2];
float maxMag = 0;
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
maxMag = mag > maxMag ? mag : maxMag;
}
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
// Bind the value to be less than 1.0 to fit in the graph
amp[i] = [EZAudio MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
Я модифицировал updateFFTWithBufferSize Описанный выше метод, так что я мог бы получить частоту в Гц, как это:
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
if(maxMag < mag) {
_i_max = i;
}
maxMag = mag > maxMag ? mag : maxMag;
}
float frequency = _i_max/bufferSize * 44100;
NSLog(@"FREQUENCY: %f", frequency);
Я генерироваться несколько чистых синусоидальных тонов с Audacity в ди для проверки частоты. Проблема, которую я вижу, заключается в том, что код возвращает ту же частоту для двух разных синусоидов, которые относительно близки по стоимости.
Например: Синусоидальный сигнал, генерируемый на 19255 Гц, будет отображаться с FFT как 19293.750000Hz. Таким образом, синусовый тон генерируется на частоте 19330 Гц. В расчетах должно быть что-то не так.
Признается, что любая помощь в том, как я могу изменить приведенный выше код, чтобы получить более точное считывание частоты FFT для чистых синусоидов. Спасибо!
Поскольку частота дискретизации моих звуков составляет 44,1 кГц, похоже, что разрешение по частоте будет около 20000/256 бит, что составляет 78,125. Вот почему я не могу получить определенную частоту, только одну в пределах диапазона 78. Любой другой способ получить более конкретный оттенок синуса? – codeman
Это поможет, если вы перечислите соответствующие номера, например: buffer_size, разрешение и т. Д. – tom10
Я предполагаю, что размер моего буфера составляет 512. Где/как я могу его увеличить? – codeman