コード例 #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
ファイル: FourierTestForm.cs プロジェクト: vr3d/GodComplex
        void    TestTransform1D(double _time)
        {
            // Build the input signal
            Array.Clear(m_signalSource, 0, m_signalSource.Length);
            switch (m_signalType1D)
            {
            case SIGNAL_TYPE.SQUARE:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((i + 50.0 * _time) % (SIGNAL_SIZE / 2.0) < (SIGNAL_SIZE / 4.0) ? 0.5 : -0.5);
                }
                break;

            case SIGNAL_TYPE.SINE:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
//						m_signalSource[i].r = Math.Cos( 2.0 * Math.PI * i / SIGNAL_SIZE + _time );
                    m_signalSource[i].r = Math.Cos((4.0 * (1.0 + Math.Sin(_time))) * 2.0 * Math.PI * i / SIGNAL_SIZE);
                }
                break;

            case SIGNAL_TYPE.SAW:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((((i + 50.0 * _time) / 128.0) % 1.0) - 0.5);
                }
                break;

            case SIGNAL_TYPE.SINC:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
//						double	a = 4.0 * (1.0 + Math.Sin( _time )) * 2.0 * Math.PI * (1+i) / SIGNAL_SIZE;						// Asymmetrical
                    double a = 4.0 * (1.0 + Math.Sin(_time)) * 2.0 * Math.PI * (i - SIGNAL_SIZE / 2.0) * 2.0 / SIGNAL_SIZE;                             // Symmetrical
                    m_signalSource[i].r = Math.Abs(a) > 0.0 ? Math.Sin(a) / a : 1.0;
                }
                break;

            case SIGNAL_TYPE.RANDOM:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = SimpleRNG.GetUniform();
                }
//						m_signalSource[i].r = SimpleRNG.GetExponential();
//						m_signalSource[i].r = SimpleRNG.GetBeta( 0.5, 1 );
//						m_signalSource[i].r = SimpleRNG.GetGamma( 1.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetCauchy( 0.0, 1.0 );
//						m_signalSource[i].r = SimpleRNG.GetChiSquare( 1.0 );
//						m_signalSource[i].r = SimpleRNG.GetNormal( 0.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetLaplace( 0.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetStudentT( 2.0 );
                break;
            }

            // Transform
            if (m_FFTW_1D != null && checkBoxUseFFTW.Checked)
            {
                m_FFTW_1D.FillInputSpatial((int x, int y, out float r, out float i) => {
                    r = (float)m_signalSource[x].r;
                    i = (float)m_signalSource[x].i;
                });
                m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.DIMENSIONS_PRODUCT);
                m_FFTW_1D.GetOutput((int x, int y, float r, float i) => {
                    m_spectrum[x].Set(r, i);
                });
            }
            else
            {
//				DFT1D.DFT_Forward( m_signalSource, m_spectrum );
                FFT1D.FFT_Forward(m_signalSource, m_spectrum);
            }

            // Try the GPU version
            m_FFT1D_GPU.FFT_Forward(m_signalSource, m_spectrumGPU);
//			m_FFT1D_GPU.FFT_Forward( m_signalSource, m_spectrum );

            double sumSqDiffR = 0.0;
            double sumSqDiffI = 0.0;

            for (int i = 0; i < m_spectrum.Length; i++)
            {
                Complex diff = m_spectrum[i] - m_spectrumGPU[i];
                sumSqDiffR += diff.r * diff.r;
                sumSqDiffI += diff.i * diff.i;
            }
            labelDiff.Text = "SqDiff = " + sumSqDiffR.ToString("G3") + " , " + sumSqDiffI.ToString("G3");
            if (m_FFTW_1D == null && checkBoxUseFFTW.Checked)
            {
                labelDiff.Text += "\r\nERROR: Can't use FFTW because of an initialization error!";
            }

            if (checkBoxInvertFilter.Checked)
            {
                for (int i = 0; i < m_spectrum.Length; i++)
                {
                    m_spectrum[i] = m_spectrumGPU[i];
                }
            }
// else
//  for ( int i=0; i < m_spectrum.Length; i++ )
//      m_spectrum[i] *= 2.0;


            // Filter
            FilterDelegate filter = null;

            switch (m_filter1D)
            {
            case FILTER_TYPE.CUT_LARGE:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 256 ? 0 : 1.0); };                                            // Cut
                break;

            case FILTER_TYPE.CUT_MEDIUM:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 128 ? 0 : 1.0); };                                            // Cut
                break;

            case FILTER_TYPE.CUT_SHORT:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 64 ? 0 : 1.0); };                                             // Cut
                break;

            case FILTER_TYPE.EXP:
                filter = (int i, int frequency) => { return(Math.Exp(-0.01f * Math.Abs(frequency))); };                                         // Exponential
                break;

            case FILTER_TYPE.GAUSSIAN:
                filter = (int i, int frequency) => { return(Math.Exp(-0.005f * frequency * frequency)); };                                      // Gaussian
                break;

            case FILTER_TYPE.INVERSE:
                filter = (int i, int frequency) => { return(Math.Min(1.0, 4.0 / (1 + Math.Abs(frequency)))); };                                 // Inverse
                break;
//              case FILTER_TYPE.SINUS:
//                  filter = ( int i, int frequency ) => { return Math.Sin( -2.0f * Math.PI * frequency / 32 ); };		// Gni ?
//                  break;
            }
            if (filter != null)
            {
                int size     = m_spectrum.Length;
                int halfSize = size >> 1;
                if (!checkBoxInvertFilter.Checked)
                {
                    for (int i = 0; i < size; i++)
                    {
                        int    frequency   = ((i + halfSize) % size) - halfSize;
                        double filterValue = filter(i, frequency);
                        m_spectrum[i] *= filterValue;
                    }
                }
                else
                {
                    for (int i = 0; i < size; i++)
                    {
                        int    frequency   = ((size - i) % size) - halfSize;
                        double filterValue = filter(i, frequency);
                        m_spectrum[i] *= filterValue;
                    }
                }
            }

            // Inverse Transform
            if (m_FFTW_1D != null && checkBoxUseFFTW.Checked)
            {
                m_FFTW_1D.FillInputFrequency((int x, int y, out float r, out float i) => {
                    r = (float)m_spectrum[x].r;
                    i = (float)m_spectrum[x].i;
                });
                m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.NONE);
                m_FFTW_1D.GetOutput((int x, int y, float r, float i) => {
                    m_signalReconstructed[x].Set(r, i);
                });
            }
            else
            {
//				DFT1D.DFT_Inverse( m_spectrum, m_signalReconstructed );
                FFT1D.FFT_Inverse(m_spectrum, m_signalReconstructed);
            }
        }