私はiPhone用にDemetriのPitchDetectorプロジェクトを実装し、2つの問題に直面しました。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);
次に、Demetriは、次のように「支配的な」頻度を決定します。
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関数の前。次に、残りのコードをoutputBufferの代わりに「transferBuffer」を使用するように変更します...しかし、これまでのところ、最終的なピッチの推測に劇的な変化は見られません。