Я реализовал проект Demetri Pitch Detector для iPhone и столкнулся с двумя проблемами.1) любой фоновый шум посылает бананам показания частоты и 2) звуки более низкой частоты не передаются правильно.Я попытался настроить свою гитару, и, пока работали более высокие струны - тюнер не мог правильно различить низкий E.
Код обнаружения высоты тона находится в RIOInterface.mm и выглядит примерно так ...
// get the data
AudioUnitRender(...);
// convert int16 to float
Convert(...);
// divide the signal into even-odd configuration
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2);
// apply the fft
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
// convert split real form to split vector
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2);
Затем Деметрий определяет «доминирующую» частоту следующим образом:
float dominantFrequency = 0;
int bin = -1;
for (int i=0; i<n; i+=2) {
float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]);
if (curFreq > dominantFrequency) {
dominantFrequency = curFreq;
bin = (i+1)/2;
}
}
memset(outputBuffer, 0, n*sizeof(SInt16));
// Update the UI with our newly acquired frequency value.
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)];
Для начала, я считаю, что мне нужно применить ФИЛЬТР НИЗКОГО ПРОХОДА ... но яне эксперт FFT и не уверен точно, где и как это сделать для данных, возвращаемых функциями vDSP.Я также не уверен, как улучшить точность кода на низких частотах.Кажется, существуют другие алгоритмы для определения доминирующей частоты, но, опять же, ищем толчок в правильном направлении при использовании данных, возвращаемых платформой Apple Accelerate.
ОБНОВЛЕНИЕ:
Среда ускоренияна самом деле имеет некоторые оконные функции.Я настраиваю базовое окно, подобное этому
windowSize = maxFrames;
transferBuffer = (float*)malloc(sizeof(float)*windowSize);
window = (float*)malloc(sizeof(float)*windowSize);
memset(window, 0, sizeof(float)*windowSize);
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM);
, которое затем применяю, вставляя
vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize);
перед функцией vDSP_ctoz.Затем я изменяю оставшуюся часть кода, чтобы использовать 'TransferBuffer' вместо outputBuffer ... но до сих пор не заметил каких-либо существенных изменений в окончательном предположении основного тона.