2016-12-07 13 views
2

Math.Net、特にFFT部分を試してみようとしています。私は純粋な正弦波から周波数領域の情報を抽出しようとしています。あなたが見ることができるように、私は20kHzの時にサンプリングし、10Kのサンプルを生成し、500Hzでの周波数の正弦波を生成しています純粋な正弦波のウィンドウデータセットに対してFFTを正しく実行する方法

private void Form1_Load(object sender, EventArgs e) 
     { 
      //Set up the wave and derive some useful info 
      Double WaveFreq = 500; 
      Double WavePeriod = 1/WaveFreq; 
      Double SampleFreq = 20000; 
      Double SampleTime = (1/SampleFreq); 

      //Generate the wave using the above parameters 
      var points = Generate.Sinusoidal(100000, SampleFreq, WaveFreq, 1); 

      //Array to hold our complex numbers 
      var data = new Complex[points.Length]; 

      //Set up the series to display our raw wave 
      Series WaveSeries = new Series("Waveform"); 
      WaveSeries.ChartType = SeriesChartType.Line; 

      //Creat the series for displaying the FFT 
      Series FFTSeries = new Series("FFT Test"); 
      FFTSeries.ChartType = SeriesChartType.Column; 

      //Populate both the wave series and the data array 
      for (int i = 0; i < points.Length; i++) 
      { 
       Double x = SampleTime * i; 
       WaveSeries.Points.AddXY(x, points[i]); 
       data[i] = new Complex(x, points[i]); 
      } 

      //Create the window to evaluate (using a window 5 times wider than the wavelength of the lowest ferequency being measured) 
      int WindowWidth = (int)Math.Round((1/WaveFreq)/(1/SampleFreq) * 5 + 0.5f); 
      var HannWindow = Window.HannPeriodic(WindowWidth); 
      var window = new Complex[WindowWidth]; 

      for(int i = 0; i < WindowWidth; i++) 
      { 
       var y = data[i].Imaginary * HannWindow[i]; 
       window[i] = new Complex(data[i].Real, y); 
      } 

      //Perform the FFT 
      Fourier.Forward(window); 

      //Add the calculated FFT to our FFTSeries 
      foreach(Complex sample in window) 
      { 
       FFTSeries.Points.AddXY(sample.Phase, sample.Magnitude); 
      } 

      chart2.Series.Add(WaveSeries); 
      chart2.ChartAreas[0].AxisX.Minimum = 0; 
      chart2.ChartAreas[0].AxisX.Maximum = .01; 
      chart2.ChartAreas[0].AxisY.Minimum = -2; 
      chart2.ChartAreas[0].AxisY.Maximum = 2; 

      chart1.Series.Add(FFTSeries); 
      chart1.ChartAreas[0].AxisX.Minimum = 0; 
      chart1.ChartAreas[0].AxisX.Maximum = 1000; 
      chart1.ChartAreas[0].AxisY.Minimum = 0; 
      chart1.ChartAreas[0].AxisY.Maximum = 5; 

     } 

:ここではコードです。

出力は以下の通りです(左のFFT、右の波) enter image description here

FFTは(0Hzから1.8程度のピークからasides)絶対に何も表示しません!私はそれがおそらくウィンドウ処理のエラーだと思うが、私の人生にとっては、それが何かを見ることができない。

ご協力いただきありがとうございます。

+0

これを複製しようとすると、私はWindow.HannPeriodic関数を見つけることができません。これはMathNetのドキュメントにありますが、Window.Hannだけに切り替えるとコンパイルできます。何か不足していますか? –

+1

@KelsonB​​all 3.14.0-beta3バージョンです。 –

答えて

3

複素数には多少の誤解があるようです。あなたのコードでは、それらはポイント(x、y-タプル)のように使われるようですが、ポイントとはまったく関係ありません。実際のデータ点の複素数は、複素数の実数部が実際のデータ点に一致し、虚数部がすべてゼロの配列です。基本的に:

var window = new Complex[WindowWidth]; 
for (int i = 0; i < WindowWidth; i++) 
{ 
    window[i] = new Complex(points[i] * HannWindow[i], 0.0); 
} 

あなたの周波数プロットの正しいx軸を取得する簡単な方法が必要な場合は、の線に沿って、FrequencyScale機能を使用することができます。

var scale = Fourier.FrequencyScale(WindowWidth, SampleFreq); 
for (int i = 0; i < WindowWidth; i++) 
{ 
    FFTSeries.Points.AddXY(scale[i], window[i].Magnitude); 
} 

あなたはスパイクが表示されるはずですインデックス5で、計算されたscaleの配列は周波数500に対応し、これはあなたの波の周波数と一致します。

FFTルーチンは負の周波数を含む全スペクトルを返しますので、同じサイズのスパイクも周波数-500で表示する必要があります。

+0

ああありがとうございます。私は今、私のエラーを理解しています。私は 'https://msdn.microsoft.com/en-us/library/system.numerics.complex(v = vs.110).aspx'を読んでいました。特に「複素数の実数部x軸(水平軸)上に位置し、虚数部分はy軸上に配置されています」そこで、ポイントの値を入力したと仮定してから、「実数」の仮想プロパティが複合同等。 –

+0

迅速なフォローアップとして、FFTを「正規化」する必要があるかもしれない方法について読んでいました。これは、現実に沿った振幅をもたらすために必要なステップでしょうか?現在、振幅は周波数が2つのビンの間のどこにあるかに依存しているようです。私はこれがウィンドウ処理の効果であることを知っていますが、それを修正する方法はわかりません。これに利用できるリソースがありますか?私は私の前提で正しいですか? –

+0

おそらくFFTのスケーリングを参照していますか?これを 'FourierOptions'引数で制御することができますが、デフォルトではparsevalの定理(時間空間エネルギー=周波数空間エネルギー)を満たすように、すでにデフォルトで対称的にスケールされています。これは、例えばMATLABは非対称にスケールされ、自分自身を拡大する必要があります。 –

0

FFTは間違いありませんが、マッピングした縮尺が間違っています。

ちょうどX軸を変更し、次のように表示されます、それ

​​

それはまた、あなたが私は数学のネット専門家でない権利が、私にはわからないされていない生成する正弦波の形のように思えます。センターはゼロには見えません。

+0

ありがとう!私はFFTチャートのy軸がその周波数での波の振幅を1対1で表すと考えました。私は今それがそうでないことを見る。 FFTグラフの振幅をどのように解釈すべきか説明できますか?ありがとうございます –

関連する問題