C# FFT1 D Example

← All NMath Code Examples

 

using System;
using System.Globalization;
using System.Threading;
using System.Text;

using CenterSpace.NMath.Core;

namespace CenterSpace.NMath.Examples.CSharp
{
  /// <summary>
  /// .NET example in C# showing how to use the 1D Fast Fourier Transform (FFT) classes.
  /// </summary>
  class FFT1DExample
  {

    static void Main( string[] args )
    {
      Console.WriteLine();

      # region forward 1D real 1024 point FFT

      //
      // Simple example to compute a forward 1D real 1024 point FFT
      //

      // Create some random signal data.
      RandomNumberGenerator rand = new RandGenMTwist( 4230987 );
      var data = new DoubleVector( 1024, rand );

      // Create the 1D real FFT instance
      var fft1024 = new DoubleForward1DFFT( 1024 );

      // Compute the FFT
      // This will create a complex conjugate symmetric packed result.
      fft1024.FFTInPlace( data );

      // Ask the FFT instance for the correct reader, to unpacked the result.
      DoubleSymmetricSignalReader reader = fft1024.GetSignalReader( data );

      // The reader provides random access to any element in the pack fft result.
      DoubleComplex thirdelement = reader[2];

      Console.WriteLine( "1D real 1024 point FFT computed." );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      #region backward 1D complex 1000 point FFT
      //
      // Simple example to compute a backward 1D complex 1000 point FFT
      //

      // Create some new random signal data.
      var cdata = new DoubleComplexVector( 1000, rand );

      // Create the 1D backward complex FFT instance
      var fft1000 = new DoubleComplexBackward1DFFT( 1000 );

      // Compute the FFT
      // Complex FFTs generated unpacked results.
      fft1000.FFTInPlace( cdata );

      Console.WriteLine( "1D complex 1000 point FFT computed." );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      #region forward 1D real FFT out-of-place using arrays

      //
      // Compute a small 1D real FFT out-of-place using arrays.
      //

      // Create the input signal data and the fft
      Double[] data5 = { 1, 2, 3, 4, 5 };
      var fft5result = new Double[5];
      var fft5 = new DoubleForward1DFFT( 5 );

      // Compute the FFT
      fft5.FFT( data5, ref fft5result );

      // Look at packed complex-conjugate symmetric result
      Console.WriteLine( "1D real FFT result." );
      Console.WriteLine( "Input data = [1, 2, 3, 4, 5]\n" );
      Console.WriteLine( "fft symmetric half packed = " );
      Console.Write( "[ " );
      for ( int i = 0; i < 5; i++ )
      {
        Console.Write( "{0,4:0.00} ", fft5result[i] );
      }
      Console.WriteLine( " ]\n" );

      // Ask the FFT instance for the correct reader, to unpacked the result.
      DoubleSymmetricSignalReader reader5 = fft5.GetSignalReader( fft5result );
      Console.WriteLine( "fft fully unpacked (requires twice the memory)= " );
      Console.Write( "[ " );
      for ( int i = 0; i < 5; i++ )
      {
        Console.Write( "({0,4:0.00},{1,4:0.00}) ", reader5[i].Real, reader5[i].Imag );
      }
      Console.WriteLine( " ]" );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      #region forward 1D real FFT using the complex FFT instance

      //
      // Compute the same 1D FFT using the complex instance
      //

      // Create the input signal data and the fft
      var cdata5 = new DoubleComplexVector( "[ (1,0) (2,0) (3,0) (4,0) (5,0) ]" );
      var cfft5 = new DoubleComplexForward1DFFT( 5 );

      // Show input data
      Console.WriteLine( "1D complex FFT result." );
      Console.WriteLine( "Input data = " );
      Console.Write( "[ " );
      for ( int i = 0; i < cdata5.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", cdata5[i].Real );
      }
      Console.WriteLine( "]\n" );

      // Compute the FFT in-place.
      cfft5.FFTInPlace( cdata5 );

      // Look at the (unpacked) complex fft result
      // Note that complex FFTs never create packed results.
      Console.WriteLine( "complex fft = " );
      Console.Write( "[ " );
      for ( int i = 0; i < cdata5.Length; i++ )
      {
        Console.Write( "({0,4:0.00},{1,4:0.00}) ", cdata5[i].Real, cdata5[i].Imag );
      }
      Console.WriteLine( " ]" );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      #region forward and backward 1D real FFT & reversal

      //
      // Compute a forward real 1D fft and then reverse the fft
      //

      // Create the input signal data and the fft
      var data4 = new DoubleVector( "[ 1 2 2 1 ]" );
      var fft4result = new DoubleVector( 4 );
      var fft4reverse = new DoubleVector( 4 );

      // Build the two FFT instances
      // fft4 is for forward real 1D FFTs.
      var fft4 = new DoubleForward1DFFT( 4 );

      // rfft4 is for reversing the complex-conjugate symmetric results of DoubleForward1DFFTs.
      // DoubleSymmetricBackward1DFFT inputs are always assumed have this complex-conjugate symmetry.
      var rfft4 = new DoubleSymmetricBackward1DFFT( 4 );

      // Compute forward real the FFT.
      fft4.FFT( data4, ref fft4result );

      // Now reverse the FFT, and for fft4reverse should match the original input data.
      rfft4.SetScaleFactorByLength(); // This scaling is necessary to match data4.
      rfft4.FFT( fft4result, ref fft4reverse );

      // Look at the packed complex-conjugate symmetric fft result
      // Note that complex FFTs never create packed results.
      Console.WriteLine( "1D real forward & backward FFT results." );

      Console.WriteLine( "Input data = " );
      Console.Write( "[ " );
      for ( int i = 0; i < rfft4.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", data4[i] );
      }
      Console.WriteLine( "]\n" );

      Console.WriteLine( "Complex-conjugate symmetric packed result of real fft = " );
      Console.Write( "[ " );
      for ( int i = 0; i < fft4.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", fft4result[i] );
      }
      Console.WriteLine( "]\n" );

      Console.WriteLine( "Backward of real fft = " );
      Console.Write( "[ " );
      for ( int i = 0; i < rfft4.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", fft4reverse[i] );
      }
      Console.WriteLine( "]" );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      #region forward 1D real FFT for an offset and strided signal

      //
      // Example computing a 1D FFT of an offset and strided signal.
      // When working with strided signals, the FFT must be configured
      // separately, and then used to create an advanced general FFT instance.
      //

      // Build our FFT configuration: direction: Forward, precision: Double, forward domain: REAL, Dimension: 1, Length: 4
      var configcomplex = new FFTConfiguration( FFTDirection.FORWARD, FFTPrecision.DOUBLE, FFTDomain.REAL, 1, 4 );

      // Set up special parameters about this data set.
      configcomplex.DataOffset = 3; // Skip three data values before starting
      configcomplex.DataStride = 2; // Skip every other data value.
      configcomplex.InPlace = true; // This will be configured for an in-place computation.

      // Not create the data set, with an offset of 3, and stride of 2.
      Double[] signal = { 94423, -341, 42343, 1, -1, 2, -1, 2, -1, 1, -85, 22 };
      var gfftresult = new Double[4];

      // Now build the general FFT object using this configuration.
      var gfft = new DoubleGeneral1DFFT( configcomplex );

      // Now compute the FFT, it should match the previous example.
      gfft.FFT( signal, ref gfftresult );

      Console.WriteLine( "Input data = " );
      Console.Write( "[ " );
      for ( int i = 0; i < signal.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", signal[i] );
      }
      Console.WriteLine( "]\n" );

      // Show the results
      Console.WriteLine( "Complex-conjugate symmetric packed result of real fft = " );
      Console.Write( "[ " );
      for ( int i = 0; i < fft4.Length; i++ )
      {
        Console.Write( "{0,4:0.00} ", gfftresult[i] );
      }
      Console.WriteLine( "]\n" );
      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      Console.WriteLine();
      Console.WriteLine( "Finished. Press Enter Key." );
      Console.Read();
    }
  }
}

← All NMath Code Examples
Top