public void RealMatchesComplex(FourierOptions options, int n)
        {
            var real = Generate.Random(n.IsEven() ? n + 2 : n + 1, GetUniform(1));

            real[n] = 0d;
            if (n.IsEven())
            {
                real[n + 1] = 0d;
            }
            var complex = new Complex[n];

            for (int i = 0; i < complex.Length; i++)
            {
                complex[i] = new Complex(real[i], 0d);
            }

            Fourier.Forward(complex, options);
            Fourier.ForwardReal(real, n, options);

            int m = (n + 1) / 2;

            for (int i = 0, j = 0; i < m; i++)
            {
                AssertHelpers.AlmostEqual(complex[i], new Complex(real[j++], real[j++]), 10);
            }
        }
Пример #2
0
        private void MicrophoneBufferRecieved(object sender, Helpers.EventArgs <float[]> e)
        {
            var buffer = e.Item;

            //FFTW.NET.FftwArrayDouble fftwArrayDouble = buffer.
            Fourier.ForwardReal(buffer, _bufferSize);
        }
Пример #3
0
        void ProcessEmissionNoiseGesture(Matrix <double> P, Matrix <double> Rot)
        {
            var series = P.Multiply(Rot.Row(0));

            var n = series.Count;

            double[] fft = new double[n + 1 + ((n % 2 == 0) ? 1 : 0)];
            series.ToArray().CopyTo(fft, 0);

            Fourier.ForwardReal(fft, n, FourierOptions.Matlab);

            int    maxFreq = 0;
            double maxAmp  = 0.0f;

            for (int i = 1; i < n; ++i)
            {
                if (Math.Abs(fft[i]) > maxAmp)
                {
                    maxAmp  = Math.Abs(fft[i]);
                    maxFreq = i;
                }
            }

            float timePeriod = (n / (float)maxFreq) * Globals.OCULUS_TRACKING_UPDATE_TIME;

            TimeManager.StackEmissionNoise(Tuple.Create(MaxPositionNoise, PositionNoiseFrequency), animScript);

            MaxPositionNoise       = (float)maxAmp / n;
            PositionNoiseFrequency = 1 / timePeriod;

            MaxRotationNoise       = MaxPositionNoise * 360;
            RotationNoiseFrequency = 1 / timePeriod;

            Debug.Log("Noise freq: " + PositionNoiseFrequency + " Amplitude: " + maxAmp / n);
        }
Пример #4
0
 public static float[] FFT(float[] iF, UInt32 iOffset)
 {
     float[] buf = new float[FFT_Samples + 2];
     Array.Copy(iF, iOffset, buf, 0, FFT_Samples);
     Fourier.ForwardReal(buf, FFT_Samples);
     ArrayABS(ref buf);
     return(buf);
 }
 void OnDataRecieved(object sender, WaveInEventArgs e)
 {
     for (int i = 0; i < e.Buffer.Length / 4; i++)
     {
         sampleBuffer[i] = Convert.ToSingle(e.Buffer[i] + e.Buffer[i + 1] + e.Buffer[i + 2] + e.Buffer[i + 3]);
     }
     Fourier.ForwardReal(sampleBuffer, 4410);
 }
Пример #6
0
 public void Test()
 {
     double[] data = new double[1026];
     for (int i = 0; i < data.Length; i++)
     {
         data[i] = (i + 1) * 1.0f;
     }
     Fourier.ForwardReal(data, 1024);
     Console.WriteLine(data);
 }
        public void FourierRealIsReversible64(FourierOptions options)
        {
            var samples = Generate.Random(0x7FFF, GetUniform(1));
            var work    = new double[samples.Length + 2];

            samples.CopyTo(work, 0);

            Fourier.ForwardReal(work, samples.Length, options);
            Assert.IsFalse(work.ListAlmostEqual(samples, 6));

            Fourier.InverseReal(work, samples.Length, options);
            AssertHelpers.AlmostEqual(samples, work, 10);
        }
Пример #8
0
        private void ComputeKernelTilde()
        {
            //Evaluate the kernel at the interpolation nodes and form the embedded generating kernel vector for a circulant matrix
            for (int i = 0; i < n_interpolation_points_1d; i++)
            {
                kernel_tilde[n_interpolation_points_1d + i]
                      = kernel_tilde[n_interpolation_points_1d - i]
                      = SquaredCauchy(tilde[0], tilde[i]);
            }

            // Precompute the FFT of the kernel generating matrix
            Fourier.ForwardReal(kernel_tilde, 2 * n_interpolation_points_1d, FourierOptions.NoScaling);
        }
Пример #9
0
        public void FFT(Signal signalIn, out Signal signal)
        {
            if (signalIn.Length == 0)
            {
                signal = new Signal(0);
                return;
            }

            float[] values = new float[signalIn.Length + 2];
            Buffer.BlockCopy(signalIn.Values, 0, values, 0, signalIn.Length);
            Fourier.ForwardReal(values, signalIn.Length);

            signal = new Signal(values);
        }
Пример #10
0
        public static float[] resample(float[] x, int M)
        {
            int N      = x.Length;
            var buffer = new float[2 * (Math.Max(M, N) / 2 + 1)];

            Array.Copy(x, buffer, N);
            Fourier.ForwardReal(buffer, N, FourierOptions.NoScaling);
            Fourier.InverseReal(buffer, M, FourierOptions.NoScaling);
            var result = new float[M];

            for (int k = 0; k < M; k++)
            {
                result[k] = buffer[k] / N;
            }
            return(result);
        }
Пример #11
0
        private void FreqDomain(IReadOnlyList <float> xTemp, int dotsNum)
        {
            int   k       = 0;
            float average = xTemp.Average();

            for (int i = 0; i < dotsNum; i++)
            {
                _xTemp2[i] = xTemp[i] - average;
            }

            Fourier.ForwardReal(_xTemp2, dotsNum, _fourierOptions);

            for (int j = 0; j < dotsNum; j = j + 2)
            {
                Finalresult[k] = 10 * Math.Log(Math.Sqrt(_xTemp2[j] * _xTemp2[j] + _xTemp2[j + 1] * _xTemp2[j + 1]));
                Xaxis[k]       = _fs / dotsNum * k;
                k++;
            }

            Finalresult[0] = 0;
        }
Пример #12
0
        private void FreqDomain(IReadOnlyList <float> xTemp, int dotsNum)
        {
            int    k       = 0;
            float  average = xTemp.Average();
            double temp    = 0;

            for (int i = 0; i < dotsNum; i++)
            {
                _xTemp2[i] = xTemp[i] - average;
            }

            Fourier.ForwardReal(_xTemp2, dotsNum, _fourierOptions);

            for (int j = 0; j < dotsNum; j = j + 2)
            {
                Finresult[k] = Math.Sqrt(_xTemp2[j] * _xTemp2[j] + _xTemp2[j + 1] * _xTemp2[j + 1]);
                //temp = Math.Sqrt(xTemp2[j] * xTemp2[j] + xTemp2[j + 1] * xTemp2[j + 1]);
                //Finresult[k] = Math.Log10(temp);
                Xaxis[k] = fs / dotsNum * k;
                k++;
            }
        }
Пример #13
0
        public IEnumerator <Complex32[]> GetEnumerator()
        {
            int resultLen = this.nPerSeg / 2 + 1;
            var buffer    = new float[2 * resultLen];

            for (int offset = 0; offset < N; offset += this.step)
            {
                for (int n = 0; n < this.nPerSeg; n++)
                {
                    buffer[n] = this.w[n] * this.x[offset + n];
                }
                Fourier.ForwardReal(buffer, this.nPerSeg, FourierOptions.NoScaling);

                var result = new Complex32[resultLen];
                for (int k = 0; k < resultLen; k++)
                {
                    result[k] = (new Complex32(buffer[2 * k], buffer[2 * k + 1])) * 2 / this.nPerSeg
                                / this.wNorm;
                }
                yield return(result);
            }
        }
Пример #14
0
        //Callback for when data is available from the sound card
        private void WaveInDataAvailable(object sender, WaveInEventArgs e)
        {
            //Calculate the length of the fft buffer
            fftBufferLength = e.Buffer.Length / (waveIn.WaveFormat.BitsPerSample * waveIn.WaveFormat.Channels);
            dataLength      = fftBufferLength / 2;

            double[] data = new double[e.Buffer.Length / 32];
            for (int i = 0; i < data.Length; i += 1)
            {
                data[i] = BitConverter.ToSingle(e.Buffer, (i) * 4);
            }

            data.CopyTo(allData, 0);

            leftSample    = new double[fftBufferLength + 2];
            rightSample   = new double[fftBufferLength + 2];
            fftInputLeft  = new double[fftBufferLength + 2];
            fftInputRight = new double[fftBufferLength + 2];

            int sampleSize = waveIn.WaveFormat.BitsPerSample / 2;

            //Read the buffer and copy the data to left and right channel arrays
            for (int i = 0; i < fftBufferLength; i += 2)
            {
                leftSample[i]  = BitConverter.ToSingle(e.Buffer, i * 4);
                rightSample[i] = BitConverter.ToSingle(e.Buffer, (i + 1) * 4);
            }

            //Copy the data to a seperate array to prevent the data to be overwritten and preform Fourier transform
            leftSample.CopyTo(fftInputLeft, 0);
            rightSample.CopyTo(fftInputRight, 0);
            Fourier.ForwardReal(fftInputLeft, fftBufferLength);
            Fourier.ForwardReal(fftInputRight, fftBufferLength);
            for (int i = 0; i < fftInputLeft.Length; i++)
            {
                fftInputLeft[i]  = Math.Abs(fftInputLeft[i]);
                fftInputRight[i] = Math.Abs(fftInputRight[i]);
            }
            fftOutputLeft  = new double[fftBufferLength / 2];
            fftOutputRight = new double[fftBufferLength / 2];
            Array.Copy(fftInputLeft, 0, fftOutputLeft, 0, 300);
            Array.Copy(fftInputRight, 0, fftOutputRight, 0, 300);

            //Check which LED visualisation mode is selected and preform the selected calculations
            if (LED_Mode == "Average")
            {
                //Bands in Hz
                int[] ranges = { 0, 300, 1200, (int)(dataLength * dataToHzMultiplier) };

                double[] outputDataLeft  = new double[ranges.Length - 1];
                double[] outputDataRight = new double[ranges.Length - 1];

                //Calculate the averages of the frequency bands
                for (int i = 0; i < ranges.Length - 1; i++)
                {
                    for (int n = (int)(ranges[i] / dataToHzMultiplier); n < (int)(ranges[i + 1] / dataToHzMultiplier); n++)
                    {
                        outputDataLeft[i]  += fftOutputLeft[n];
                        outputDataRight[i] += fftOutputRight[n];
                    }
                    outputDataLeft[i]  /= (ranges[i + 1] / dataToHzMultiplier) - (ranges[i] / dataToHzMultiplier);
                    outputDataRight[i] /= (ranges[i + 1] / dataToHzMultiplier) - (ranges[i] / dataToHzMultiplier);
                }

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputDataLeft[2],
                    outputDataLeft[1],
                    outputDataLeft[0],
                    outputDataRight[2],
                    outputDataRight[1],
                    outputDataRight[0]
                });
            }
            else if (LED_Mode == "Peak")
            {
                //Bands in Hz
                int[] ranges = { 0, 300, 1200, (int)(dataLength * dataToHzMultiplier) };

                double[] outputDataLeft  = new double[ranges.Length - 1];
                double[] outputDataRight = new double[ranges.Length - 1];

                //Get the peak value of every frequency band
                for (int i = 0; i < ranges.Length - 1; i++)
                {
                    outputDataLeft[i]  = 0;
                    outputDataRight[i] = 0;
                    for (int n = (int)(ranges[i] / dataToHzMultiplier); n < (int)(ranges[i + 1] / dataToHzMultiplier); n++)
                    {
                        if (outputDataLeft[i] < fftOutputLeft[n])
                        {
                            outputDataLeft[i] = fftOutputLeft[n];
                        }

                        if (outputDataRight[i] < fftOutputRight[n])
                        {
                            outputDataRight[i] = fftOutputRight[n];
                        }
                    }
                }

                //Ensure the values are between 0 and 1
                for (int i = 0; i < outputDataLeft.Length; i++)
                {
                    outputDataLeft[i]  /= outputDataLeft[i] + 1;
                    outputDataRight[i] /= outputDataRight[i] + 1;
                }

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputDataLeft[2],
                    outputDataLeft[1],
                    outputDataLeft[0],
                    outputDataRight[2],
                    outputDataRight[1],
                    outputDataRight[0]
                });
            }
            else if (LED_Mode == "Average hue")
            {
                //Convert the fft output to RGB based on the hsv color space
                RGBcolor outputLeft  = new RGBcolor();
                RGBcolor outputRight = new RGBcolor();
                for (int i = 0; i < dataLength; i++)
                {
                    outputLeft.r += colors[i].r * fftOutputLeft[i];
                    outputLeft.g += colors[i].g * fftOutputLeft[i];
                    outputLeft.b += colors[i].b * fftOutputLeft[i];

                    outputRight.r += colors[i].r * fftOutputRight[i];
                    outputRight.g += colors[i].g * fftOutputRight[i];
                    outputRight.b += colors[i].b * fftOutputRight[i];
                }

                outputLeft.r  /= dataLength;
                outputLeft.g  /= dataLength;
                outputLeft.b  /= dataLength;
                outputRight.r /= dataLength;
                outputRight.g /= dataLength;
                outputRight.b /= dataLength;

                //Proccess the colors a bit
                float x = 400;

                outputLeft.r  *= x;
                outputLeft.g  *= x;
                outputLeft.b  *= x;
                outputRight.r *= x;
                outputRight.g *= x;
                outputRight.b *= x;

                outputLeft.r  = Math.Pow(outputLeft.r, magnitude);
                outputLeft.g  = Math.Pow(outputLeft.g, magnitude);
                outputLeft.b  = Math.Pow(outputLeft.b, magnitude);
                outputRight.r = Math.Pow(outputRight.r, magnitude);
                outputRight.g = Math.Pow(outputRight.g, magnitude);
                outputRight.b = Math.Pow(outputRight.b, magnitude);


                outputLeft.r  /= x;
                outputLeft.g  /= x;
                outputLeft.b  /= x;
                outputRight.r /= x;
                outputRight.g /= x;
                outputRight.b /= x;

                //I'm trying to figure out a way to have the brightness adapt to the volume so there would be more detail. Now That I think about it it does sound like HDR haha...

                /*double maxLeft = Math.Max(outputLeft.r,Math.Max(outputLeft.g, outputLeft.b));
                 * outputLeft.r /= maxLeft;
                 * outputLeft.g /= maxLeft;
                 * outputLeft.b /= maxLeft;
                 * double maxRight = Math.Max(outputRight.r, Math.Max(outputRight.g, outputRight.b));
                 * outputRight.r /= maxRight;
                 * outputRight.g /= maxRight;
                 * outputRight.b /= maxRight;*/


                //Ensure the RGB chanels are between 0 and 1
                outputLeft.r  /= outputLeft.r + 1;
                outputLeft.g  /= outputLeft.g + 1;
                outputLeft.b  /= outputLeft.b + 1;
                outputRight.r /= outputRight.r + 1;
                outputRight.g /= outputRight.g + 1;
                outputRight.b /= outputRight.b + 1;

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputLeft.r,
                    outputLeft.g,
                    outputLeft.b,
                    outputRight.r,
                    outputRight.g,
                    outputRight.b
                });
            }
            else if (LED_Mode == "Average frequency hue")
            {
                //Calculate average frequency and amplitude
                RGBcolor outputLeft            = new RGBcolor();
                RGBcolor outputRight           = new RGBcolor();
                double   totalAmplitudeLeft    = 0;
                double   totalAmplitudeRight   = 0;
                double   averagefrequencyLeft  = 0;
                double   averagefrequencyRight = 0;
                double   averageAmplitudeLeft  = 0;
                double   averageAmplitudeRight = 0;
                for (int i = 0; i < dataLength; i++)
                {
                    totalAmplitudeLeft  += fftOutputLeft[i];
                    totalAmplitudeRight += fftOutputRight[i];

                    averagefrequencyLeft  += fftOutputLeft[i] * i;
                    averagefrequencyRight += fftOutputRight[i] * i;
                }

                averagefrequencyLeft  /= totalAmplitudeLeft;
                averagefrequencyRight /= totalAmplitudeRight;
                averageAmplitudeLeft   = totalAmplitudeLeft / dataLength;
                averageAmplitudeRight  = totalAmplitudeRight / dataLength;

                if (!Double.IsNaN(averagefrequencyLeft))
                {
                    outputLeft    = colors[(int)averagefrequencyLeft];
                    outputLeft.r *= averageAmplitudeLeft;
                    outputLeft.g *= averageAmplitudeLeft;
                    outputLeft.b *= averageAmplitudeLeft;
                }
                else
                {
                    outputLeft = new RGBcolor();
                }

                if (!Double.IsNaN(averagefrequencyRight))
                {
                    outputRight    = colors[(int)averagefrequencyRight];
                    outputRight.r *= averageAmplitudeRight;
                    outputRight.g *= averageAmplitudeRight;
                    outputRight.b *= averageAmplitudeRight;
                }
                else
                {
                    outputRight = new RGBcolor();
                }

                int x = 20;

                outputLeft.r *= x;
                outputLeft.g *= x;
                outputLeft.b *= x;

                outputRight.r *= x;
                outputRight.g *= x;
                outputRight.b *= x;

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputLeft.r,
                    outputLeft.g,
                    outputLeft.b,
                    outputRight.r,
                    outputRight.g,
                    outputRight.b
                });
            }
            else if (LED_Mode == "Saturation enhancement - 1")
            {
                RGBcolor outputLeft  = new RGBcolor();
                RGBcolor outputRight = new RGBcolor();
                for (int i = 0; i < dataLength; i++)
                {
                    outputLeft.r += colors[i].r * fftOutputLeft[i];
                    outputLeft.g += colors[i].g * fftOutputLeft[i];
                    outputLeft.b += colors[i].b * fftOutputLeft[i];

                    outputRight.r += colors[i].r * fftOutputRight[i];
                    outputRight.g += colors[i].g * fftOutputRight[i];
                    outputRight.b += colors[i].b * fftOutputRight[i];
                }

                outputLeft.r  /= dataLength;
                outputLeft.g  /= dataLength;
                outputLeft.b  /= dataLength;
                outputRight.r /= dataLength;
                outputRight.g /= dataLength;
                outputRight.b /= dataLength;

                float x = 10;

                outputLeft.r  *= x;
                outputLeft.g  *= x;
                outputLeft.b  *= x;
                outputRight.r *= x;
                outputRight.g *= x;
                outputRight.b *= x;

                HSVcolor hsvLeft = RGBtoHSV(outputLeft);
                hsvLeft.s *= saturationMultiplier;
                outputLeft = HSVToRGB(hsvLeft);

                HSVcolor hsvRight = RGBtoHSV(outputRight);
                hsvRight.s *= saturationMultiplier;
                outputRight = HSVToRGB(hsvRight);

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputLeft.r,
                    outputLeft.g,
                    outputLeft.b,
                    outputRight.r,
                    outputRight.g,
                    outputRight.b
                });
            }
            else if (LED_Mode == "Saturation enhancement - 2")
            {
                //Calculate average frequency and amplitude
                RGBcolor outputLeft            = new RGBcolor();
                RGBcolor outputRight           = new RGBcolor();
                double   totalAmplitudeLeft    = 0;
                double   totalAmplitudeRight   = 0;
                double   averagefrequencyLeft  = 0;
                double   averagefrequencyRight = 0;
                double   averageAmplitudeLeft  = 0;
                double   averageAmplitudeRight = 0;
                for (int i = 0; i < dataLength; i++)
                {
                    totalAmplitudeLeft  += fftOutputLeft[i];
                    totalAmplitudeRight += fftOutputRight[i];

                    averagefrequencyLeft  += fftOutputLeft[i] * i;
                    averagefrequencyRight += fftOutputRight[i] * i;
                }

                averagefrequencyLeft  /= totalAmplitudeLeft;
                averagefrequencyRight /= totalAmplitudeRight;
                averageAmplitudeLeft   = totalAmplitudeLeft / dataLength;
                averageAmplitudeRight  = totalAmplitudeRight / dataLength;

                if (!Double.IsNaN(averagefrequencyLeft))
                {
                    outputLeft    = colors[(int)averagefrequencyLeft];
                    outputLeft.r *= averageAmplitudeLeft;
                    outputLeft.g *= averageAmplitudeLeft;
                    outputLeft.b *= averageAmplitudeLeft;
                }
                else
                {
                    outputLeft = new RGBcolor();
                }

                if (!Double.IsNaN(averagefrequencyRight))
                {
                    outputRight    = colors[(int)averagefrequencyRight];
                    outputRight.r *= averageAmplitudeRight;
                    outputRight.g *= averageAmplitudeRight;
                    outputRight.b *= averageAmplitudeRight;
                }
                else
                {
                    outputRight = new RGBcolor();
                }

                int x = 10;

                outputLeft.r *= x;
                outputLeft.g *= x;
                outputLeft.b *= x;

                outputRight.r *= x;
                outputRight.g *= x;
                outputRight.b *= x;

                HSVcolor hsvLeft = RGBtoHSV(outputLeft);
                hsvLeft.s *= saturationMultiplier;
                outputLeft = HSVToRGB(hsvLeft);

                HSVcolor hsvRight = RGBtoHSV(outputRight);
                hsvRight.s *= saturationMultiplier;
                outputRight = HSVToRGB(hsvRight);

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputLeft.r,
                    outputLeft.g,
                    outputLeft.b,
                    outputRight.r,
                    outputRight.g,
                    outputRight.b
                });
            }
            else if (LED_Mode == "DEBUG")
            {
                RGBcolor outputLeft  = new RGBcolor();
                RGBcolor outputRight = new RGBcolor();

                HSVcolor color = new HSVcolor();
                color.h     = counter / 100.0f;
                color.s     = 0.5f;
                color.v     = 1;
                outputLeft  = HSVToRGB(color);
                outputRight = HSVToRGB(color);

                HSVcolor hsvLeft = RGBtoHSV(outputLeft);
                hsvLeft.s  = 1;
                outputLeft = HSVToRGB(hsvLeft);

                //HSVcolor hsvRight = RGBtoHSV(outputRight);
                //hsvRight.s = 1;
                //outputRight = HSVToRGB(hsvRight);

                //Call the function that sends the data to a microcontroller
                SendData(new double[] {
                    outputLeft.r,
                    outputLeft.g,
                    outputLeft.b,
                    outputRight.r,
                    outputRight.g,
                    outputRight.b
                });

                counter %= 100;
                counter++;
            }
        }
Пример #15
0
        /// <summary>
        /// Advance Real FFT
        /// </summary>
        /// <param name="xIn">time domain data</param>
        /// <param name="spectralLines">spectralLines</param>
        /// <param name="windowType">window type</param>
        /// <param name="xOut">spectral out data</param>
        /// <param name="spectralInfo">spectral info</param>
        public static void AdvanceRealFFT(double[] xIn, int spectralLines, WindowType windowType,
                                          double[] xOut, ref SpectralInfo spectralInfo)
        {
            int    n = xIn.Length, windowsize = 0, fftcnt = 0; //做FFT的次数
            int    fftsize = 0;                                //做FFT点数
            double cg = 0, enbw = 0, scale = 0.0;

            double[] xInTmp     = null;
            double[] windowData = null;
            double[] xOutCTmp   = null;

            //输入的线数超过最大支持的线数则使用最大支持线数
            if (spectralLines > MaxSpectralLine)
            {
                spectralLines = MaxSpectralLine;
            }

            //输入的点数小于线数,则窗长度为N,先加窗再补零到2*spectralLines再做FFT
            if (n <= 2 * spectralLines)
            {
                windowsize = n;
                fftcnt     = 1;
            }
            else
            {
                windowsize = 2 * spectralLines;
                fftcnt     = n / (2 * spectralLines);
            }

            fftsize = 2 * spectralLines; //不管N与2*spectralLines的关系是怎么样,FFT的点数都应该为 2*spectralLines

            xInTmp = new double[fftsize];
            //xOutCTmp = new Complex[fftsize / 2 + 1];
            if (xInTmp.Length % 2 == 0)
            {
                xOutCTmp = new double[xInTmp.Length + 2];
            }
            else
            {
                xOutCTmp = new double[xInTmp.Length + 1];
            }

            if (n < (2 * spectralLines))
            {
                //memset(x_in + N, 0, (fftsize - N) * sizeof(double)); //补零至spectralLines
                for (int i = n; i < fftsize; i++)
                {
                    xInTmp[i] = 0;
                }
            }
            //memset(xOut, 0, spectralLines * sizeof(double));
            //生成窗函数的数据
            windowData = new double[windowsize];
            Window.GetWindow(windowType, ref windowData, out cg, out enbw);

            for (int i = 0; i < xOut.Length; i++)
            {
                xOut[i] = 0;
            }
            //CBLASNative.cblas_dscal(windowsize, 1 / cg, windowData, 1); //窗系数归一化
            //CBLASNative.cblas_dscal(xOut.Length, 0, xOut, 1); //将xOut清零
            GCHandle gch    = GCHandle.Alloc(xIn, GCHandleType.Pinned);
            var      xInPtr = gch.AddrOfPinnedObject();

            for (int i = 0; i < fftcnt; i++)
            {
                //拷贝数据到临时内存中
                //memcpy(x_in, x + i * windowsize, fftsize * sizeof(double));
                /*TIME_DOMAIN_WINDOWS(windowType, x_in, &CG, &ENBW, windowsize);*//*(double*)(xIn + i * windowsize)*/
                for (int k = 0; k < windowsize; k++)
                {
                    xInTmp[k] = windowData[k] * xIn[i * fftsize + k];
                }
                Buffer.BlockCopy(xInTmp, 0, xOutCTmp, 0, xInTmp.Length * sizeof(double));
                Fourier.ForwardReal(xOutCTmp, xInTmp.Length, FourierOptions.NoScaling);

                //VMLNative.vdMul(windowsize, windowData, xInPtr + i * fftsize * sizeof(double), xInTmp);
                //BasicFFT.RealFFT(xInTmp, ref xOutCTmp);

                ////计算FFT结果复数的模,复用x_in做中间存储
                //VMLNative.vzAbs(fftsize / 2 + 1, xOutCTmp, xInTmp);
                //xOut[0] += xOutCTmp[0];
                for (int j = 0; j < spectralLines; j++)
                {
                    xOut[j] += Math.Sqrt(xOutCTmp[2 * j + 1] * xOutCTmp[2 * j + 1] + xOutCTmp[2 * j] * xOutCTmp[2 * j]);
                }
                ////每次计算结果累加起来
                //VMLNative.vdAdd(spectralLines, xInTmp, xOut, xOut);
            }

            scale = 2 * (1.0 / fftcnt) / Sqrt2; //双边到单边有一个二倍关系,输出为Vrms要除以根号2
            for (int j = 0; j < spectralLines; j++)
            {
                xOut[j] *= scale;
            }
            ////fftcnt次的频谱做平均
            //CBLASNative.cblas_dscal(spectralLines, scale, xOut, 1);

            xOut[0] = xOut[0] / Sqrt2; //上一步零频上多除了根号2,这里乘回来(Rms在零频上不用除根号2,单双边到单边还是要乘2 ?)

            spectralInfo.spectralLines = spectralLines;
            spectralInfo.FFTSize       = fftsize;
            spectralInfo.windowSize    = windowsize;
            spectralInfo.windowType    = windowType;
            gch.Free();
        }
Пример #16
0
        // My own adaption from the FFTSharp function
        // Original source: https://github.com/swharden/FftSharp/blob/master/src/FftSharp/Transform.cs
        // My goal here was to have it accept an array as a reference without converting to complex etc etc.
        public double[] FFT(double[] buffer, int inputBufferStartPosition, int bufferLength, double[] window)
        {
#if USEMATHNET // About twice as fast as my attempt
            // Testing MathNet as an alternative.
            //FourierOptions fo = new FourierOptions();
            //fo.
            double[] magnitudes    = new double[bufferLength / 2 + 1];
            double[] mathNetBuffer = new double[bufferLength + 2];
            //Array.Copy(buffer, inputBufferStartPosition, mathNetBuffer, 0, bufferLength);
            for (int i = 1; i < bufferLength; i++)
            {
                mathNetBuffer[i] = buffer[inputBufferStartPosition + i] * window[i];
            }
            Fourier.ForwardReal(mathNetBuffer, bufferLength, FourierOptions.NoScaling);
            magnitudes[0] = Math.Sqrt(mathNetBuffer[0] * mathNetBuffer[0] + mathNetBuffer[1] * mathNetBuffer[1]) / bufferLength;
            for (int i = 1; i < magnitudes.Length; i++)
            {
                magnitudes[i] = 2 * Math.Sqrt(mathNetBuffer[i * 2] * mathNetBuffer[i * 2] + mathNetBuffer[i * 2 + 1] * mathNetBuffer[i * 2 + 1]) / bufferLength;
            }
            return(magnitudes);
#else
            // The normal code:


            //double[,] complexBuffer = new double[bufferLength, 2];
            Vector2[] complexBuffer = new Vector2[bufferLength];


            for (int i = 0, sOffset = inputBufferStartPosition; i < bufferLength; i++, sOffset++)
            {
                complexBuffer[i].X = (float)(window[i] * buffer[sOffset]);
            }


            for (int i = 0; i < bitReverseSwapTable.Length; i++)
            {
                (complexBuffer[bitReverseSwapTable[i][1]].X, complexBuffer[bitReverseSwapTable[i][0]].X) = (complexBuffer[bitReverseSwapTable[i][0]].X, complexBuffer[bitReverseSwapTable[i][1]].X);
            }


            double[] realBuffer = new double[bufferLength / 2 + 1];

            Vector2 temp = new Vector2();

            for (int i = 1; i <= bufferLength / 2; i *= 2)
            {
                double mult1 = -Math.PI / i;
                for (int j = 0; j < bufferLength; j += (i * 2))
                {
                    for (int k = 0; k < i; k++)
                    {
                        int evenI = j + k;
                        int oddI  = j + k + i;
                        //(temp[0],temp[1]) = (sinCosTable[i, k][0],sinCosTable[i, k][1]);

                        temp             = sinCosTable[i, k];
                        (temp.X, temp.Y) = (temp.X * complexBuffer[oddI].X - temp.Y * complexBuffer[oddI].Y, temp.X *complexBuffer[oddI].Y + temp.Y * complexBuffer[oddI].X);
                        //Vector2.Transform(temp,new Matrix3x2() { M11= complexBuffer[oddI].X, M12= -complexBuffer[oddI].Y, M21= complexBuffer[oddI].Y, M22= temp.Y * complexBuffer[oddI].X });// forget about this. wrong values and slow!
                        complexBuffer[oddI]   = complexBuffer[evenI] - temp;
                        complexBuffer[evenI] += temp;

                        /*complexBuffer[oddI,0] = complexBuffer[evenI,0] - temp[0]; //buffer[evenI] - temp;
                         * complexBuffer[oddI,1] = complexBuffer[evenI,1] - temp[1]; //buffer[evenI] - temp;
                         * complexBuffer[evenI, 0] += temp[0];//temp;
                         * complexBuffer[evenI, 1] += temp[1];//temp;*/
                    }
                }
            }

            realBuffer[0] = Math.Sqrt(complexBuffer[0].X * complexBuffer[0].X + complexBuffer[0].Y * complexBuffer[0].Y) / bufferLength;
            for (int i = 1; i < realBuffer.Length; i++)
            {
                realBuffer[i] = 2 * Math.Sqrt(complexBuffer[i].X * complexBuffer[i].X + complexBuffer[i].Y * complexBuffer[i].Y) / bufferLength;
            }



            return(realBuffer);
#endif
        }