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); } }
private void MicrophoneBufferRecieved(object sender, Helpers.EventArgs <float[]> e) { var buffer = e.Item; //FFTW.NET.FftwArrayDouble fftwArrayDouble = buffer. Fourier.ForwardReal(buffer, _bufferSize); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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++; } }
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); } }
//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++; } }
/// <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(); }
// 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 }