private double[] FFT_from_PCM(double[] pcm) { // use the largest FFT size we can given the data (must be a power of 2) int fftPoints = 2; while (fftPoints * 2 <= pcm.Length) { fftPoints *= 2; } // prepare the complex data which will be FFT'd (using a window function) NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints]; for (int i = 0; i < fftPoints; i++) { fftFull[i].X = (float)(pcm[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints)); } // perform the FFT NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull); // average (sum) the mirror image frequency powers double[] fft = new double[fftPoints / 2]; for (int i = 0; i < fftPoints / 2; i++) { double fftLeft = Math.Abs(fftFull[i].X + fftFull[i].Y); double fftRight = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y); fft[i] = fftLeft + fftRight; } return(fft); }
private void updateFFT() { // the PCM size to be analyzed with FFT must be a power of 2 int fftPoints = 2; while (fftPoints * 2 <= dataPcm.Length) { fftPoints *= 2; } // apply a Hamming window function as we load the FFT array then calculate the FFT NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints]; for (int i = 0; i < fftPoints; i++) { fftFull[i].X = (float)(dataPcm[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints)); } NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull); // copy the complex values into the double array that will be plotted if (dataFft == null) { dataFft = new double[fftPoints]; } for (int i = 0; i < fftPoints; i++) { double fftLeft = Math.Abs(fftFull[i].X + fftFull[i].Y); double fftRight = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y); dataFft[i] = fftLeft + fftRight; //dataFft[i] = Math.Sqrt(fftFull[i].X * fftFull[i].X + fftFull[i].Y * fftFull[i].Y); } }
private void updateFFT() { // размер PCM для анализа с помощью БПФ должен быть степенью 2 int fftPoints = 2; while (fftPoints * 2 <= dataPcm.Length) { fftPoints *= 2; } // применяем оконную функцию Хэмминга при загрузке массива FFT, затем вычисляем FFT NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints]; for (int i = 0; i < fftPoints; i++) { fftFull[i].X = (float)(dataPcm[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints)); } NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull); // копируем комплексные значения в двойной массив, который будет построен if (dataFft == null) { dataFft = new double[fftPoints / 2]; } for (int i = 0; i < fftPoints / 2; i++) { double fftLeft = Math.Abs(fftFull[i].X + fftFull[i].Y); double fftRight = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y); dataFft[i] = fftLeft + fftRight; } }
private void updateFFT() { if (dataPcm == null) { return; } int fftPoints = 2; while (fftPoints * 2 <= dataPcm.Length) { fftPoints *= 2; } NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints]; for (int i = 0; i < fftPoints; i++) { fftFull[i].X = (float)(dataPcm[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints)); } NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull); if (dataFft == null) { dataFft = new double[fftPoints / 2]; } for (int i = 0; i < fftPoints / 2; i++) { double fftLeft = Math.Abs(fftFull[i].X + fftFull[i].Y); double fftRight = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y); dataFft[i] = fftLeft + fftRight; } }
public override void Draw() { Graphics.SetColor(1, 1, 1); if (buffer == null) { Graphics.Print("No buffer available"); return; } int len = buffer.FloatBuffer.Length / 8; // fft NAudio.Dsp.Complex[] values = new NAudio.Dsp.Complex[len]; for (int i = 0; i < len; i++) { values[i].Y = 0; values[i].X = buffer.FloatBuffer[i]; } NAudio.Dsp.FastFourierTransform.FFT(true, M, values); float size = (float)WindowWidth / ((float)Math.Pow(2, M) / 2); for (int i = 1; i < Math.Pow(2, M) / 2; i++) { //Graphics.Print(i.ToString() + ": " + values[i].X.ToString("N2") + " i " + (values[i].Y + 0.50f).ToString("N2"), 0, (i + 1) * 16); Graphics.Rectangle(DrawMode.Fill, (i - 1) * size, WindowHeight / 2, size, -Math.Abs(values[i].X) * (WindowHeight / 2) * 10); } }
public static float[] FFT(float[] values, WindowFunction window = WindowFunction.hanning) { int fftSize = values.Length; if (!IsPowerOfTwo(fftSize)) { throw new ArgumentException("FFT Size must be a power of 2"); } NAudio.Dsp.Complex[] fft_buffer = new NAudio.Dsp.Complex[fftSize]; for (int i = 0; i < fftSize; i++) { fft_buffer[i].X = (float)values[i]; fft_buffer[i].Y = 0; switch (window) { case WindowFunction.none: break; case WindowFunction.hanning: fft_buffer[i].X *= (float)NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftSize); break; case WindowFunction.triangle: fft_buffer[i].X *= (float)TriangleWindow(i, fftSize); break; default: throw new NotImplementedException("unsupported window function"); } } NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftSize, 2.0), fft_buffer); float[] fft = new float[fftSize / 2]; for (int i = 0; i < fft.Length; i++) { var fftL = fft_buffer[i]; var fftR = fft_buffer[fft_buffer.Length - i - 1]; // note that this is different than just taking the absolute value float absL = (float)Math.Sqrt(fftL.X * fftL.X + fftL.Y * fftL.Y); float absR = (float)Math.Sqrt(fftR.X * fftR.X + fftR.Y * fftR.Y); fft[i] = (absL + absR) / 2; } return(fft); }
private void SetDataFFT(WaveInEventArgs args) { int bytesPerSample = _wi.WaveFormat.BitsPerSample / 8; int samplesRecorded = args.BytesRecorded / bytesPerSample; Int16[] dataPcm = new Int16[samplesRecorded]; for (int i = 0; i < samplesRecorded; i++) { dataPcm[i] = BitConverter.ToInt16(args.Buffer, i * bytesPerSample); } // the PCM size to be analyzed with FFT must be a power of 2 int fftPoints = 2; while (fftPoints * 2 <= dataPcm.Length) { fftPoints *= 2; } // apply a Hamming window function as we load the FFT array then calculate the FFT NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints]; for (int i = 0; i < fftPoints; i++) { fftFull[i].X = (float)(dataPcm[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints)); } NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull); double[] dataFft = new double[fftPoints / 2]; byte[] data = new byte[fftPoints / 2]; for (int i = 0; i < fftPoints / 2; i++) { double fftLeft = Math.Abs(fftFull[i].X + fftFull[i].Y); double fftRight = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y); dataFft[i] = fftLeft + fftRight; data[i] = (byte)(fftLeft + fftRight); } /*if(SpectrumVisualizer.GetType().Name == "CircleSpectrumVisualizer") * SpectrumVisualizer.Set(GetNiceCircleFFT(data)); * else * SpectrumVisualizer.Set(data);*/ SpectrumVisualizer.Set(GetNiceFftData(data, SpectrumVisualizer.GetType().Name == "CircleSpectrumVisualizer")); }
public static void NAaudioFFTTestUsingDouble(string CSVFilePath=null, double[] audio_data=null, int testLoopCount=1) { if (audio_data == null) { audio_data = GetSignalTestData(); } int windowLength = audio_data.Length; int binaryExponentitation = (int)Math.Log(windowLength, 2); NAudio.Dsp.Complex[] complexArray = new NAudio.Dsp.Complex[windowLength]; for (int i = 0; i < windowLength; i++) { complexArray[i].X = (float) audio_data[i]; complexArray[i].Y = 0; } // loop if neccesary - e.g. for performance test purposes for (int i = 0; i < testLoopCount; i++) { // perform the FFT NAudio.Dsp.FastFourierTransform.FFT(true, binaryExponentitation, complexArray); } // get the result double[] spectrum_fft_real = new double[complexArray.Length]; double[] spectrum_fft_imag = new double[complexArray.Length]; double[] spectrum_fft_abs = new double[complexArray.Length]; for (int i = 0; i < complexArray.Length; i++) { float re = complexArray[i].X; float img = complexArray[i].Y; spectrum_fft_real[i] = re * windowLength; spectrum_fft_imag[i] = img * windowLength; spectrum_fft_abs[i] = (float) Math.Sqrt(re*re + img*img) * windowLength; } // perform the inverse FFT (IFFT) NAudio.Dsp.FastFourierTransform.FFT(false, binaryExponentitation, complexArray); // get the result double[] spectrum_inverse_real = new double[complexArray.Length]; double[] spectrum_inverse_imag = new double[complexArray.Length]; double[] spectrum_inverse_abs = new double[complexArray.Length]; for (int i = 0; i < complexArray.Length; i++) { float re = complexArray[i].X; float img = complexArray[i].Y; spectrum_inverse_real[i] = re; spectrum_inverse_imag[i] = img; spectrum_inverse_abs[i] = (float) Math.Sqrt(re*re + img*img); } if (CSVFilePath!=null) { CommonUtils.Export.exportCSV(CSVFilePath, audio_data, spectrum_fft_real, spectrum_fft_imag, spectrum_fft_abs, spectrum_inverse_real, spectrum_inverse_imag, spectrum_inverse_abs); } }
public void DrawVisualizerTimer(object sender, EventArgs e) { if (buffer == null) { Console.WriteLine("No buffer available"); return; } int len = buffer.FloatBuffer.Length / 8; int M = 6; // fft NAudio.Dsp.Complex[] values = new NAudio.Dsp.Complex[len]; for (int i = 0; i < len; i++) { values[i].Y = 0; values[i].X = buffer.FloatBuffer[i]; } NAudio.Dsp.FastFourierTransform.FFT(true, M, values); double scale = 0; for (int i = 0; i < Math.Pow(2, M) / 2; i++) { //Console.Write(" " + values[i].X.ToString("N2")); scale += values[i].X; } if (scale < 0) { scale *= -1; } audioScale = scale * 5; //Console.WriteLine(" > " + scale); if (audioScale > 0) { outterFireScaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, new DoubleAnimation(1, 1 + audioScale, TimeSpan.FromMilliseconds(100))); outterFireScaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, new DoubleAnimation(1, 1 + audioScale, TimeSpan.FromMilliseconds(100))); outterFireScaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, new DoubleAnimation(1 + audioScale, 1, TimeSpan.FromMilliseconds(100))); outterFireScaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, new DoubleAnimation(1 + audioScale, 1, TimeSpan.FromMilliseconds(100))); } if (audioScale > 0.05) { if (!faceControlTimer.IsEnabled) { String leftBefore = (String)leftEye.Content; String rightBefore = (String)rightEye.Content; leftEye.Content = "^"; rightEye.Content = "^"; faceControlTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) }; faceControlTimer.Start(); faceControlTimer.Tick += (s, args) => { faceControlTimer.Stop(); leftEye.Content = leftBefore; rightEye.Content = rightBefore; }; } } }