OS XのリニアPCMオーディオファイル(複数のオーディオチャネルが含まれる可能性があります)でFFTを実行しようとしています。これを実行するための最良の方法は何ですか?
いくつかの情報源は、AppleのAccelerateFrameworkが私に必要なものであることを示しています。もしそうなら、それらのFFT関数で使用するために浮動小数点データをどのように抽出して適切に準備する必要がありますか?
やりたいことは大体こんな感じ。独自の入力関数と出力関数を入力します。
// Stick new data into inData, a (float*) array
fetchFreshData(inData);
// (You might want to window the signal here... )
doSomeWindowing(inData);
// Convert the data into a DSPSplitComplex
// Pardon the C++ here. Also, you should pre-allocate this, and NOT
// make a fresh one each time you do an FFT.
mComplexData = new DSPSplitComplex;
float *realpart = (float *)calloc(mNumFrequencies, sizeof(float));
float *imagpart = (float *)calloc(mNumFrequencies, sizeof(float));
mComplexData->realp = realpart;
mComplexData->imagp = imagpart;
vDSP_ctoz((DSPComplex *)inData, 2, mComplexData, 1, mNumFrequencies);
// Calculate the FFT
// ( I'm assuming here you've already called vDSP_create_fftsetup() )
vDSP_fft_zrip(mFFTSetup, mComplexData, 1, log2f(mNumFrequencies), FFT_FORWARD);
// Don't need that frequency
mComplexData->imagp[0] = 0.0;
// Scale the data
float scale = (float) 1.0 / (2 * (float)mSignalLength);
vDSP_vsmul(mComplexData->realp, 1, &scale, mComplexData->realp, 1, mNumFrequencies);
vDSP_vsmul(mComplexData->imagp, 1, &scale, mComplexData->imagp, 1, mNumFrequencies);
// Convert the complex data into something usable
// spectrumData is also a (float*) of size mNumFrequencies
vDSP_zvabs(mComplexData, 1, spectrumData, 1, mNumFrequencies);
// All done!
doSomethingWithYourSpectrumData(spectrumData);
それが役立つことを願っています。
オーディオ データに対して FFT を実行する場合、サンプルは実数部分に入り、虚数部分はゼロになるはずです。
Apple の vDSP を含むほとんどの FFT ライブラリには、入力が実数 (虚数成分なし) で出力が複素数である「実数 FFT」と呼ばれる方法が含まれています。
Core Audio を調べる必要があるように思えます... 私はそれにあまり詳しくありませんが、チャネルのインターリーブ解除が既に行われているようで、PCM データで直接動作します。あまり詳しくないので、これは大まかに考えてください。ただし、FFT を Audio Unit に入れ、単一チャネルの PCM データを入力として取り、FFT の結果をアクセス可能な場所に保存し、入力を渡してみます。アウトプットまで。
実際に FFT を実行する限り、主な課題は、FFT ルーチンが操作したい double * ベクトルに PCM 入力を強制することにあるように思えます。vDSP.h (加速フレームワークの一部) を見ると、vDSP_vflt16D (16 ビット整数のベクトルを倍精度実数のベクトルに変換する) のような関数が表示され、問題が解決するようです。