- ベストアンサー
FFTを使って信号を周波数変換する方法を教えてください。
音信号を周波数変換するプログラムを作成しています。 FFTを使って実現しようとしているのですが、うまくいきません。 現時点で作った方法では、 (1)FFTする。結果は配列x_re[NFFT]、x_im[NFFT]に格納。(x_re:実数部 x_im:虚数部 NFFT:ポイント数、配列の内容としては周波数の低い順に結果データが並んでいる) (2) x_re,x_imの内容をずらす。(例えば以下のように配列内容を1つずらせばIFFTをした時周波数が高くなるはず) for(i=0;i<NFFT-1;i++){ x_re[i+1]=x_re[i]; x_im[i+1]=x_im[i]; } (3)配列x_re[NFFT]、x_im[NFFT]に対しIFFTする。 FFT・IFFTが正しく動作するのは確認しています。 (動作実績も結構あります。(2)を省略し(1)(3)だけとすれば出力結果は入力結果と同じ(出力音声を聴いた感じで)になるので、正しく動作していると思います。) よって(2)が間違っていると思います。 (2)をどのようにすれば周波数変換できるのか教えてください。また今の所FFTを使おうとしているのですが、別に入力信号を周波数変換できればOK(周波数を上げたり下げたりしたい)なので、その方法があれば教えてください(><)
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
配列をずらすと周波数は高くなるでしょうが、音は不自然になるはずです。足し算ではなく掛算で考えるべきだと思います。 たとえば、1kHzと2kHzがあって、これはちょうど倍音関係(1オクターブ上)になっていますが、足し算(+0.2kHz)だと1.2kHzと2.2kHzで不協和音になりますよね。掛算(*1.2)ならば1.2kHzと2.4kHzで倍音関係は維持したままです。 僕は専門家ではないのであまり詳しくないですが、周波数シフトではいろいろ気をつけることがあるみたいです。 FFTでは周波数の間隔が一定ですので、掛算で求めた周波数はちょうどグリッド上にくることはありません。 これは、掛算する前の周波数も本当の周波数ではなくて、最寄のグリッド上にでていることを意味します。 周波数シフトのようなデリケートな処理の場合、周波数の誤差は致命的ですので、補正処理が必要です。 補正方法は、位相差計測法とかいろいろあるようです。。
その他の回答 (2)
- keyguy
- ベストアンサー率28% (135/469)
FFTは単なる計算技術なのでDFTとIDFTに置き換えていうべきですがそもそもDFTを使うのは得策ではありません 計算区間の境で大きくなる誤差を生じるからです シフトしたい周波数幅をf0とすると単純に 元の信号にexp(j・2π・f0・t)をかければいいでしょう 気をつけなければならないのは複素数になり2つのデータを管理しなければならないのです 実部のcos(2π・f0・t)との積だけや虚部のsin(2π・f0・t)との積だけにしておくと折り返しを生じてしまうのです (サンプリング周波数fsが大きくf0が大きければこの限りで無い,ただしこの場合無駄が多い) このほうが正確(DFTと違って基本的には計算誤差以外の誤差なし)で計算量も小さい(1サンプルに複素数1乗算だけ)のです
- kmb01
- ベストアンサー率45% (63/138)
for(i=0;i<NFFT-1;i++){ x_re[i+1]=x_re[i]; x_im[i+1]=x_im[i]; } だとすべてのデータがx_re[0],x_im[0]になるのでは? 解決案 for (i=NFFT-1; i>0; i--) { x_re[i]=x_re[i-1]; x_im[i]=x_im[i-1]; }
補足
ご指摘の通りです(><) 質問登録直後に気づきましたが訂正できませんでした。 この場を借りまして訂正致します。 実際のプログラムでは、正しく配列内容を1つずらしております。