getSpectrum
現在、FMODオーディオライブラリの機能を再現しようとしています。この関数は、現在再生中のバッファの PCM データを読み取り、このデータにウィンドウを適用し、FFT を適用してスペクトルを取得します。
各 float が 0 ~ 1 dB の float の配列を返します ( 10.0f * ( float)log10(val) * 2.0f
)。
自分が何をすべきかよくわからないので、説明します。
最初に、4096 バイトのバッファーで PCM データを取得します。ドキュメントによると、PCM データは左右のデータのペアであるサンプルで構成されています。
私の場合、上の画像のように 16 ビットのサンプルを使用しています。したがって、左チャンネルのみで作業したい場合は、左の PCM データを次のようにして短い配列に保存します。
short *data = malloc(4096);
FMOD_Sound_ReadData(sound, (void *)data, 4096, &read);
したがって、サンプル = 4 バイトの場合、1024 個のサンプルがあります。つまり、左チャネルを表す 1024 ショートと右チャネルを表す 1024 ショートです。
FFT を実行するには、float 配列を用意し、データにウィンドウ (ハニング) を適用する必要があります。
float hanningWindow(short in, size_t i, size_t s)
{
return in*0.5f*(1.0f-cos(2.0f*M_PI*(float)(i)/(float)(s-1.0f)));
}
wewin
は入力、i
は配列内の位置、および配列s
のサイズ (1024) です。
左チャンネルのみを取得するには:
float *input = malloc(1024*sizeof(float));
for (i = 0; i < 1024; i++)
input[i] = hanningWindow(data[i*2], i, 1024);
次に、kiss_fft のおかげで FFT を実行します (実数から複素数へ)。kiss_fft_cpx *ouput
サイズ 1024/2+1 = 513 の (複合体の配列)を取得します。
各周波数の振幅を次のように計算します。
kiss_fft_cpx c = output[i];
float amp = sqrt(c.r*c.r + c.i*c.i);
dB で計算します。
amp = 10.0f * (float)log10(amp) * 2.0f;
amp
は 0 と 1 の間ではありません。どこでデータを正規化する必要があるかわかりません (PCM データ上または最後)。また、PCM データにウィンドウを適用する方法もわかりません。
これは、getSpectrum 関数の結果と比較して、0 ~ 20kHz の曲から取得した結果です。(長方形の窓の場合)
My Result getSpectrum Result
どうすれば同じ結果を得ることができますか?