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