🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1008閲覧

FFT結果のピークが半分の周波数に出る

YMD_kts

総合スコア23

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/11/21 02:28

編集2019/11/21 02:29

こちらのサイトを参考にマイクから入力した音にFFTをかけて出力するというプログラムを作成しているのですが、テストで440Hzのサイン波を入力したところ、ピークが本来の周波数の半分である220Hzの部分で出てしまいます。
FFT機能は自作できないので、FFTWや、こちらの質問の回答などを参考に使用しているのですが、どちらの場合でも220Hzでピークが出てしまいます。

それともファイル出力時の周波数部分の計算方法が間違っているのでしょうか
わかる方がおりましたら回答お待ちしております

C++

1case MM_WIM_DATA:{ 2 3fftIn = (fftw_complex*)fftw_malloc(FFT_N * sizeof(fftw_complex)); 4fftOut = (fftw_complex*)fftw_malloc(FFT_N * sizeof(fftw_complex)); 5 6if (!fftIn || !fftOut) { 7 OutputDebugString("failed to allocate memory(-.-)\n"); 8 return false; 9} 10if (p == NULL) 11 p = fftw_plan_dft_1d(FFT_N, fftIn, fftOut, FFTW_FORWARD, FFTW_ESTIMATE); 12 13//入力データ移動 14for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded; dwCount++) 15{ 16 //ハミング窓 17 fftIn[dwCount][0] = (double)((PWAVEHDR)lp)->lpData[dwCount] 18 * (0.54 + 0.46 * cos((double)(2 * dwCount - FFT_N) * M_PI / (double)FFT_N)); 19 fftIn[dwCount][1] = 0; 20} 21//実行 22fftw_execute(p); 23 24//ファイル出力 25ofstream fout("test1.csv"); 26fout << "Freq," << setw(5) << "Re," << setw(5) << "Im," << setw(5) << "Power" << endl; 27for (dwCount = 0; dwCount <= ((LPWAVEHDR)lp)->dwBytesRecorded / 2; dwCount++) { 28 power[dwCount] = pow(fftOut[dwCount][0], 2) + pow(fftOut[dwCount][1], 2); 29 fout << (dwCount * 48000 / FFT_N) << "," << setw(5) << fftOut[dwCount][0] << "," << setw(5) 30 << fftOut[dwCount][1] << "," << setw(5) << power[dwCount] << endl; 31} 32 33//破棄 34if (p) fftw_destroy_plan(p); 35if (fftIn) fftw_free(fftIn); 36if (fftOut) fftw_free(fftOut); 37 38return 0; 39}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

私の回答

c

1for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded/2; dwCount++) 2 fftbuffer[dwCount] = ((int16_t*)((PWAVEHDR)lp)->lpData)[dwCount];

あなたのコード

c

1for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded; dwCount++) { 2 fftIn[dwCount][0] = (double)((PWAVEHDR)lp)->lpData[dwCount]

何が違うのかは前回説明したと思います。


適当に試してみましたが、440Hz付近になります。

c

1 case MM_WIM_DATA: { 2 bTmp = (int16_t*)realloc(bSave, dwLength + ((PWAVEHDR)lp)->dwBytesRecorded); 3 if (blReset || !bTmp) { 4 waveInClose(hWaveIn); 5 blReset = FALSE; 6 7 return 0; 8 } 9 bSave = bTmp; 10 memcpy(bSave + dwLength/2, ((PWAVEHDR)lp)->lpData, ((PWAVEHDR)lp)->dwBytesRecorded); 11 dwLength += ((PWAVEHDR)lp)->dwBytesRecorded; 12 13 14 double* fftbuffer = (double*)malloc(sizeof(double) * ((LPWAVEHDR)lp)->dwBytesRecorded /2); 15 const int NLEN = ((PWAVEHDR)lp)->dwBytesRecorded / 2; 16 if( NLEN > 4096 ){ 17 for (dwCount = 0; dwCount < 4096; dwCount++) 18 fftbuffer[dwCount] = ((int16_t*)((PWAVEHDR)lp)->lpData)[dwCount]; 19 fft1(fftbuffer, zeroData, 4096, 0, 0); 20 int imax = 0; double max = fftbuffer[0]*fftbuffer[0] + zeroData[0] * zeroData[0]; 21 for (int i = 0; i < 4096; i++){ 22 if(fftbuffer[i]*fftbuffer[i] + zeroData[i]*zeroData[i] > max){ 23 imax = i; 24 max = fftbuffer[i]*fftbuffer[i] + zeroData[i]*zeroData[i]; 25 } 26 } 27 cout << 48000.0 / 4096 * imax << max << endl; 28 } 29 waveInAddBuffer(hWaveIn, (PWAVEHDR)lp, sizeof(WAVEHDR)); 30 free(fftbuffer); 31 32 return 0; 33 }

投稿2019/11/21 05:40

編集2019/11/21 13:26
asm

総合スコア15149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YMD_kts

2019/11/21 10:37

何度も回答ありがとうございます。 それが、回答いただいたコードでも半分の220Hzでピークが出ていたので、FFTWを使ってみたりと自分なりにコードを書き換えてその状態で質問に投稿していました。 double* fftbuffer = (double*)malloc(sizeof(double) * ((LPWAVEHDR)lp)->dwBytesRecorded/2); for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded/2; dwCount++) { fftbuffer[dwCount] = ((int16_t*)((LPWAVEHDR)lp)->lpData)[dwCount]; } fft1(fftbuffer, zeroData, ((LPWAVEHDR)lp)->dwBytesRecorded /2 , 0, 0); こちらのコードの場合でも220Hzにピークがきてしまっています。 FFTWにSHORTを入れた for (dwCount = 0; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded/2; dwCount++) fftbuffer[dwCount] = ((int16_t*)((PWAVEHDR)lp)->lpData)[dwCount]; こちらも同じく220Hzピークになりました
YMD_kts

2019/11/21 16:27

ありがとうございます 無事440Hzピークを確認できました しかしこの方法は結局録音したサンプルの内4096サンプルしかFFT出来てないと考えて良いのでしょうか
asm

2019/11/21 23:31

えぇそうですね。データ到着時の先頭4096サンプルのみをFFTに掛けています。 適当に試しただけですので
YMD_kts

2019/11/22 00:08

了解しました。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問