昨日のdataavailableコールバック関数の中では、キャプチャしたデータをそのままbufferedwaveprobiderに渡していたけど、同じ関数の中にFFTの処理を追加した。
1 2 3 4 5 6 7 8 9 10 11 12 |
private void wavein_dataavailable(object sender, WaveInEventArgs e) { bufferedwaveprovider.AddSamples(e.Buffer, 0, e.BytesRecorded); short[] sdata = new short[e.BytesRecorded / 4]; float[] snddata = new float[4096]; for (int i = 0; i < e.BytesRecorded; i += 4) sdata[i / 4] = (short)((e.Buffer[i + 1] << 8) | e.Buffer[i + 0]); Array.Copy(sdata, snddata, 4096); fftdata = FFT_NAudio(snddata); dataready = true; pictureBox1.Refresh(); } |
FFTのデータ数は、2のべき乗にする必要があるので、データ数を4096にしている。 また、音声データは、2チャンネル分あるけど、FFTをするのは1チャンネルだけ。
FFTの実装..といってもNAudioにある関数を使っているので、ちょー簡単。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private float[] FFT_NAudio(float[] sdata) { var fftsample = new Complex[sdata.Length]; var res = new float[sdata.Length / 2]; for (int i = 0; i < sdata.Length; i++) { fftsample[i].X = (float)(sdata[i] * FastFourierTransform.HammingWindow(i, sdata.Length)); fftsample[i].Y = 0; } FastFourierTransform.FFT(true, 12, fftsample); for (int i = 0; i < sdata.Length / 2; i++) { res[i] = 10 * (float)Math.Log(Math.Sqrt(fftsample[i].X * fftsample[i].X + fftsample[i].Y * fftsample[i].Y)); } return res; } |
データにハミング窓をかけてからFFTに渡す。 FFTへの入力データは複素数なので、虚部を0にした複素数に変換する。
FFTの最初の引数をfalseにすると逆フーリエ変換になる。 2つ目の引数は、データ数を2のべき乗で表した時のべき数。
結果の絶対値を取って、logに変換して表示。
ちょっと怪しい気もするけど、この表示が最終目的じゃないので、とりあえずこのまま次に進める。