3

FFT (高速フーリエ変換)を使用して 2 つのオーディオ ファイル間で単純な畳み込みを実行しようとしていますMathNet.Numerics'sが、IFFT の後で奇妙なバックグラウンド サウンドが発生します。

問題の原因が畳み込みなのか変換なのかをテストしたところ、FFT -> IFFT (Inverze FFT) 変換で既に問題が発生していることがわかりました。

単純な FFT と IFFT の私のコード:

float[] sound; //here are stored my samples

Complex[] complexInput = new Complex[sound.Length];
for (int i = 0; i < complexInput.Length; i++)
{
      Complex tmp = new Complex(sound[i],0);
      complexInput[i] = tmp;
 }

MathNet.Numerics.IntegralTransforms.Fourier.Forward(complexInput);

//do some stuff

MathNet.Numerics.IntegralTransforms.Fourier.Inverse(complexInput);

float[] outSamples = new float[complexInput.Length];

for (int i = 0; i < outSamples.Length; i++)
     outSamples[i] = (float)complexInput[i].Real;

この後、outSamples私は FFT と IFFT の間で何もしていませんが、いくつかの奇妙なバックグラウンド サウンド/ノイズで破損しています。

私は何が欠けていますか?

4

1 に答える 1

4

(およびMathNet.Numerics.IntegralTransform.Fourierを参照)の現在の実装では、2 のべき乗でない FFT 長に対してBluestein のアルゴリズムを使用します。Fourier.csFourier.Bluestein.cs

このアルゴリズムには、バージョン 3.6.0 までは次のコードを使用していた Bluestein シーケンス (n 2に比例する項を含む) の作成が含まれます。

static Complex[] BluesteinSequence(int n)
{
  double s = Constants.Pi/n;
  var sequence = new Complex[n];

  for (int k = 0; k < sequence.Length; k++)
  {
    double t = s*(k*k); // <--------------------- (k*k) 32-bit int expression
    sequence[k] = new Complex(Math.Cos(t), Math.Sin(t));
  }

  return sequence;
}

サイズnが 46341 より大きい場合(k*k)、この実装の中間式は算術演算 ( MSDN 整数型リファレンス テーブルintによる 32 ビット型) を使用して計算され、 の最大値の数値オーバーフローが発生します。そのため、 の現在の実装では、2 のべき乗または 2 のべき乗でない最大 46341 (含まれる) の入力配列サイズのみがサポートされます。kMathNet.Numerics.IntegralTransfom.Fourier

したがって、大規模な入力配列の場合、回避策として、入力を次の 2 の累乗にパディングすることができます。

: この観察結果は のバージョン 3.6.0 に基づいMathNet.Numericsていますが、以前のリリースには制限があったようです (Bluestein シーケンス コードは、バージョン 2.1.1 までさかのぼって大幅に変更されていません)。


2015/04/26 更新:

これとgithub bugtracking の同様の問題に関するコメントを投稿した後、問題は ですぐに修正されましたMathNet.Numerics。この修正は、バージョン 3.7.0 で利用できるようになりました。ただし、パフォーマンス上の理由から、特に線形畳み込みのためにゼロパッドを既に必要としているため、2 のべき乗までパディングする必要がある場合があることに注意してください。

于 2015-04-22T14:44:00.340 に答える