← 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