C# FFT1 D Example

← All NMath Code Examples

```using System;
using System.Globalization;
using System.Text;

using CenterSpace.NMath.Core;

namespace CenterSpace.NMath.Core.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.

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 FFT's 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.
Console.WriteLine( "fft fully unpacked (requires twice the memory)= " );
Console.Write( "[ " );
for ( int i = 0; i < 5; i++ )
{
}
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 FFT's 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 FFT's.
var fft4 = new DoubleForward1DFFT( 4 );

// rfft4 is for reversing the complex-conjugate symmetric results of DoubleForward1DFFT's.
// 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 FFT's 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 );

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." );