コード例 #1
0
ファイル: FourierTestForm.cs プロジェクト: vr3d/GodComplex
        void    CheckAgainstFFTW()
        {
            if (m_FFTW_2D == null)
            {
                m_FFTW_2D       = new fftwlib.FFT2D(SIGNAL_SIZE_2D, SIGNAL_SIZE_2D);
                m_test_CPU      = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, true, false, null);
                m_FFTW2D_Output = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null);
            }

            // Retrieve input as CPU-accessible
            m_test_CPU.CopyFrom(m_FFT2D_GPU.Input);
            PixelsBuffer bufferIn = m_test_CPU.MapRead(0, 0);

            m_test_CPU.UnMap(bufferIn);

            float2[,]       input_GPU = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D];
            using (System.IO.BinaryReader R = bufferIn.OpenStreamRead())
                for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++)
                {
                    for (int X = 0; X < SIGNAL_SIZE_2D; X++)
                    {
                        input_GPU[X, Y].Set(R.ReadSingle(), R.ReadSingle());
                    }
                }
            bufferIn.Dispose();

            // Apply FFT
            m_FFT2D_GPU.FFT_GPUInOut(-1.0f);

            // Retrieve output as CPU-accessible
            m_test_CPU.CopyFrom(m_FFT2D_GPU.Output);
            PixelsBuffer bufferOut = m_test_CPU.MapRead(0, 0);

            m_test_CPU.UnMap(bufferOut);

            float2[,]       output_GPU = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D];
            using (System.IO.BinaryReader R = bufferOut.OpenStreamRead())
                for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++)
                {
                    for (int X = 0; X < SIGNAL_SIZE_2D; X++)
                    {
                        output_GPU[X, Y].Set(R.ReadSingle(), R.ReadSingle());
                    }
                }
            bufferOut.Dispose();

            // Process input with FFTW
            m_FFTW_2D.FillInputSpatial((int _x, int _y, out float _r, out float _i) => {
                _r = input_GPU[_x, _y].x;
                _i = input_GPU[_x, _y].y;
            });
            m_FFTW_2D.Execute(fftwlib.FFT2D.Normalization.DIMENSIONS_PRODUCT);
            float2[,]       output_FFTW = new float2[SIGNAL_SIZE_2D, SIGNAL_SIZE_2D];
            m_FFTW_2D.GetOutput((int _x, int _y, float _r, float _i) => {
                output_FFTW[_x, _y].Set(_r, _i);
            });

            // Upload FFTW output to GPU
            bufferOut = m_test_CPU.MapWrite(0, 0);
            using (System.IO.BinaryWriter W = bufferOut.OpenStreamWrite())
                for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++)
                {
                    for (int X = 0; X < SIGNAL_SIZE_2D; X++)
                    {
                        W.Write(output_FFTW[X, Y].x);
                        W.Write(output_FFTW[X, Y].y);
                    }
                }
            m_test_CPU.UnMap(bufferOut);
            bufferOut.Dispose();
            m_FFTW2D_Output.CopyFrom(m_test_CPU);

            // Compare
            float sumSqDiffR = 0.0f;
            float sumSqDiffI = 0.0f;

            for (int Y = 0; Y < SIGNAL_SIZE_2D; Y++)
            {
                for (int X = 0; X < SIGNAL_SIZE_2D; X++)
                {
                    float2 GPU  = output_GPU[X, Y];
                    float2 FFTW = output_FFTW[X, Y];
                    float2 diff = GPU - FFTW;
                    sumSqDiffR += diff.x * diff.x;
                    sumSqDiffI += diff.y * diff.y;
                }
            }
            labelDiff2D.Text = "SqDiff = " + sumSqDiffR.ToString("G3") + " , " + sumSqDiffI.ToString("G3");
        }
コード例 #2
0
ファイル: Form1.cs プロジェクト: Patapom/GodComplex
        protected unsafe override void OnLoad( EventArgs e )
        {
            base.OnLoad( e );

            using ( fftwlib.FFT2D FFT = new fftwlib.FFT2D( 256, 256 ) )
            {
                // Build the source data
            //				FillInput( FFT.Input );

                {
                    const double	Lx = 400.0;
                    const double	Lz = Lx;

                    const double	WindAngle = 45.0 * Math.PI / 180.0;
                    const double	WindVelocity = 20.0;

                    double	Wx = Math.Cos( WindAngle );
                    double	Wz = Math.Sin( WindAngle );

                    double	U1, U2, fX, fZ;

                    Random	RNG = new Random( 1 );

                    FFT.FillInputFrequency( ( int Fx, int Fy, out float r, out float i ) => {
                        double	kx = (2.0 * Math.PI / Lx) * Fx;
                        double	kz = (2.0 * Math.PI / Lz) * Fy;

                        // Build white gaussian noise
                        // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise)
                        U1 = 1e-10 + RNG.NextDouble();
                        U2 = RNG.NextDouble();
                        fX = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 );
                        U1 = 1e-10 + RNG.NextDouble();
                        U2 = RNG.NextDouble();
                        fZ = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 );

            fX = fZ = 1.0;

                        // Build Phillips spectrum
                        double	SqrtPhillips = Math.Sqrt( Phillips( kx, kz, WindVelocity, Wx, Wz ) );
                        r = (float) (1.0 / Math.Sqrt( 2.0 ) * fX * SqrtPhillips);
                        i = (float) (1.0 / Math.Sqrt( 2.0 ) * fZ * SqrtPhillips);

            r = (float) (U1);// * Math.Exp( -0.001 * Math.Abs( Fx ) ));
            i = 0.0f;//(float) U2;

            // r = 0.0;
            // for ( int j=1; j < 100; j++ )
            // 	r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j;
            // i = 0.0;

            // r = Math.Exp( -0.1 * kx );
            // i = Math.Exp( -0.1 * kz );

                        } );
                }

                // Fill in bitmap
                outputPanelFrequency.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) =>
                    {
                        int	X = 256 * _X / _Width;
                        int	Y = 256 * _Y / _Height;
                        byte	R = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+0] )));
                        byte	I = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+1] )));

                        return 0xFF000000 | (uint) ((R << 16) | (I << 8));
                    } );

                // Inverse FFT
                FFT.InputIsSpatial = false;	// We fed frequencies and need an inverse transform
                FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT );

            // DEBUG: Test we get back what we fed!
            // FFT.SwapInputOutput();
            // FFT.InputIsSpatial = false;
            // FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT );

                // Retrieve results
                outputPanelSpatial.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) =>
                    {
                        int	X = 256 * _X / _Width;
                        int	Y = 256 * _Y / _Height;
                        byte	R = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+0] )));
                        byte	I = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+1] )));
            // byte	R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) ));
            // byte	I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) ));

                        return 0xFF000000 | (uint) ((R << 16) | (I << 8));
                    } );

                //////////////////////////////////////////////////////////////////////////
                // Save the results
                System.IO.FileInfo		F = new System.IO.FileInfo( @".\Water0_256x256.complex" );
                System.IO.FileStream	S = F.Create();
                System.IO.BinaryWriter	Writer = new System.IO.BinaryWriter( S );

                for ( int Y=0; Y < 256; Y++ )
                    for ( int X=0; X < 256; X++ )
                    {
                        Writer.Write( FFT.Output[2*(256*Y+X)+0] );
                        Writer.Write( FFT.Output[2*(256*Y+X)+1] );
                    }

                Writer.Close();
                S.Close();
            }
        }
コード例 #3
0
ファイル: FourierTestForm.cs プロジェクト: vr3d/GodComplex
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

// Quick color picker L*a*b* extension test... (should totally NOT be here! :D)
//Nuaj.Cirrus.Utility.ColorPickerForm	picker = new Nuaj.Cirrus.Utility.ColorPickerForm();
//picker.ShowDialog( this );

            //////////////////////////////////////////////////////////////////////////
            // Initialize 1D data
            try {
                m_device1D.Init(imagePanel.Handle, false, true);
                m_FFT1D_GPU = new FFT1D_GPU(m_device1D, SIGNAL_SIZE);

                m_CB_Main1D = new ConstantBuffer <CB_Main>(m_device1D, 0);
                m_Shader_GenerateSignal1D = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/GenerateSignal.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_Shader_FilterSignal1D   = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/FilterSignal.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_Shader_Display1D        = new Shader(m_device1D, new System.IO.FileInfo("./Shaders/Display.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_texSpectrumCopy         = new Texture2D(m_device1D, SIGNAL_SIZE, 1, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null);
            } catch (Exception) {
                MessageBox.Show("Failed to initialize DirectX device! Can't execute GPU FFT!", "DirectX Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                m_device1D = null;
            }

            m_image = new ImageFile((uint)imagePanel.Width, (uint)imagePanel.Height, ImageUtility.PIXEL_FORMAT.BGRA8, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB));

            try {
                m_FFTW_1D = new fftwlib.FFT2D(SIGNAL_SIZE, 1);                          // Allocate on the fly, if the interop fails then it will crash immediately but at least the
            } catch (Exception _e) {
                MessageBox.Show("Failed to initialize reference FFTW library! It's not necessary for the unit test unless you need to compare against \"ground truth\".\r\nReason:\r\n" + _e.Message, "FFTW Library Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                m_FFTW_1D = null;
            }

            imagePanel.SkipPaint = checkBoxGPU.Checked;

            UpdateGraph1D();

            //////////////////////////////////////////////////////////////////////////
            // Initialize 2D data
            try {
                m_device2D.Init(imagePanel2D.Handle, false, true);
                m_FFT2D_GPU = new FFT2D_GPU(m_device2D, SIGNAL_SIZE_2D);

                m_CB_Main2D = new ConstantBuffer <CB_Main>(m_device2D, 0);
                m_Shader_GenerateSignal2D = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/GenerateSignal2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_Shader_FilterSignal2D   = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/FilterSignal2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_Shader_Display2D        = new Shader(m_device2D, new System.IO.FileInfo("./Shaders/Display2D.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);
                m_texOriginalSignalCopy2D = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null);
                m_texSpectrumCopy2D       = new Texture2D(m_device2D, SIGNAL_SIZE_2D, SIGNAL_SIZE_2D, 1, 1, ImageUtility.PIXEL_FORMAT.RG32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null);
            } catch (Exception _e) {
                MessageBox.Show("Failed to initialize DirectX device! Can't execute GPU FFT!\r\nReason:\r\n" + _e.Message, "DirectX Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                m_device2D = null;
            }

            m_image2D = new ImageFile((uint)imagePanel2D.Width, (uint)imagePanel2D.Height, PIXEL_FORMAT.BGRA8, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB));

            imagePanel2D.SkipPaint = true;            //checkBoxGPU.Checked;

            radioButtonSignalX_CheckedChanged(null, EventArgs.Empty);
            radioButtonSignalY_CheckedChanged(null, EventArgs.Empty);

            Application.Idle += Application_Idle;
        }
コード例 #4
0
ファイル: Form1.cs プロジェクト: vr3d/GodComplex
        protected unsafe override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            using (fftwlib.FFT2D FFT = new fftwlib.FFT2D(256, 256))
            {
                // Build the source data
//				FillInput( FFT.Input );

                {
                    const double Lx = 400.0;
                    const double Lz = Lx;

                    const double WindAngle    = 45.0 * Math.PI / 180.0;
                    const double WindVelocity = 20.0;

                    double Wx = Math.Cos(WindAngle);
                    double Wz = Math.Sin(WindAngle);

                    double U1, U2, fX, fZ;

                    Random RNG = new Random(1);

                    FFT.FillInputFrequency((int Fx, int Fy, out float r, out float i) => {
                        double kx = (2.0 * Math.PI / Lx) * Fx;
                        double kz = (2.0 * Math.PI / Lz) * Fy;

                        // Build white gaussian noise
                        // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise)
                        U1 = 1e-10 + RNG.NextDouble();
                        U2 = RNG.NextDouble();
                        fX = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2);
                        U1 = 1e-10 + RNG.NextDouble();
                        U2 = RNG.NextDouble();
                        fZ = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2);

                        fX = fZ = 1.0;

                        // Build Phillips spectrum
                        double SqrtPhillips = Math.Sqrt(Phillips(kx, kz, WindVelocity, Wx, Wz));
                        r = (float)(1.0 / Math.Sqrt(2.0) * fX * SqrtPhillips);
                        i = (float)(1.0 / Math.Sqrt(2.0) * fZ * SqrtPhillips);

                        r = (float)(U1); // * Math.Exp( -0.001 * Math.Abs( Fx ) ));
                        i = 0.0f;        //(float) U2;

// r = 0.0;
// for ( int j=1; j < 100; j++ )
//  r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j;
// i = 0.0;

// r = Math.Exp( -0.1 * kx );
// i = Math.Exp( -0.1 * kz );
                    });
                }


                // Fill in bitmap
                outputPanelFrequency.FillBitmap((int _X, int _Y, int _Width, int _Height) =>
                {
                    int X  = 256 * _X / _Width;
                    int Y  = 256 * _Y / _Height;
                    byte R = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 0])));
                    byte I = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 1])));

                    return(0xFF000000 | (uint)((R << 16) | (I << 8)));
                });

                // Inverse FFT
                FFT.InputIsSpatial = false;                     // We fed frequencies and need an inverse transform
                FFT.Execute(fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT);

// DEBUG: Test we get back what we fed!
// FFT.SwapInputOutput();
// FFT.InputIsSpatial = false;
// FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT );

                // Retrieve results
                outputPanelSpatial.FillBitmap((int _X, int _Y, int _Width, int _Height) =>
                {
                    int X  = 256 * _X / _Width;
                    int Y  = 256 * _Y / _Height;
                    byte R = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 0])));
                    byte I = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 1])));
// byte	R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) ));
// byte	I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) ));

                    return(0xFF000000 | (uint)((R << 16) | (I << 8)));
                });

                //////////////////////////////////////////////////////////////////////////
                // Save the results
                System.IO.FileInfo     F      = new System.IO.FileInfo(@".\Water0_256x256.complex");
                System.IO.FileStream   S      = F.Create();
                System.IO.BinaryWriter Writer = new System.IO.BinaryWriter(S);

                for (int Y = 0; Y < 256; Y++)
                {
                    for (int X = 0; X < 256; X++)
                    {
                        Writer.Write(FFT.Output[2 * (256 * Y + X) + 0]);
                        Writer.Write(FFT.Output[2 * (256 * Y + X) + 1]);
                    }
                }

                Writer.Close();
                S.Close();
            }
        }