12,251,364 members (40,980 online)

34.5K views
57 bookmarked
Posted

Visualizing Sound

, 6 Nov 2012 CPOL
Listen or playback sound and visualize the frequency spread.
 ```﻿// ----------------------------------------------------------------------- // // By Philip R. Braica (HoshiKata@aol.com, VeryMadSci@gmail.com) // // Distributed under the The Code Project Open License (CPOL) // http://www.codeproject.com/info/cpol10.aspx // // ----------------------------------------------------------------------- namespace Math { using System; using System.Collections.Generic; using System.Linq; using System.Text; /// /// Simple fast FFT, lots of the usual overloads. /// /// There are a bunch of "Forward" and "Inverse" calls, all of then /// support seperate buffers. There is also the popular "interlaced" /// style where real and imaginary data is interlaced in the same buffer. /// That isn't supported in this version. /// /// The algorithm is Cooley-Tukey, classic and so textbook I can't /// really call any of it "mine" it just is the way it is done. /// public class FFT { #region Public: Forward, Inverse, doubles. /// /// Compute the FFT forward in place for real data. /// /// Reals public static void Forward(double[] reals) { doFFT(reals, true); } /// /// Compute the FFT forward for real data. /// /// Reals in. /// Reals Out. public static void Forward(double[] realIn, double[] realOut) { doFFTReals(realIn, realOut, true); } /// /// Compute forward FFT for real in, complex out. /// /// /// /// public static void Forward(double[] realIn, double[] realOut, double[] imagOut) { doFFTReals(realIn, realOut, imagOut, true); } /// /// Compute forward FFT for complex in, complex out. /// /// /// /// /// public static void Forward(double[] realIn, double [] imagIn, double[] realOut, double[] imagOut) { doFFT(realIn, imagIn, realOut, imagOut, true); } /// /// Compute the FFT inverse in place for real data. /// /// Reals in and out. public static void Inverse(double[] reals) { doFFT(reals, false); } /// /// Compute the FFT inverse for real data. /// /// Reals in. /// Reals Out. public static void Inverse(double[] realIn, double[] realOut) { doFFTReals(realIn, realOut, false); } /// /// Compute inverse FFT for real in, complex out. /// /// /// /// public static void Inverse(double[] realIn, double[] realOut, double[] imagOut) { doFFTReals(realIn, realOut, imagOut, true); } /// /// Compute inverse FFT for complex in, complex out. /// /// /// /// public static void Inverse(double[] realIn, double[] imagIn, double[] realOut, double[] imagOut) { doFFT(realIn, imagIn, realOut, imagOut, false); } #endregion #region Public: Forward, Inverse, floats. /// /// Compute the FFT forward in place for real data. /// /// Reals public static void Forward(float[] reals) { doFFT(reals, true); } /// /// Compute the FFT forward for real data. /// /// Reals in. /// Reals Out. public static void Forward(float[] realIn, float[] magOut) { doFFTReals(realIn, magOut, true); } /// /// Compute forward FFT for real in, complex out. /// /// /// /// public static void Forward(float[] realIn, float[] imagIn, float[] realOut) { doFFTReals(realIn, imagIn, realOut, true); } /// /// Compute forward FFT for complex in, complex out. /// /// /// /// public static void Forward(float[] realIn, float[] imagIn, float[] realOut, float[] imagOut) { doFFT(realIn, imagIn, realOut, imagOut, true); } /// /// Compute the FFT inverse in place for real data. /// /// Reals in and out. public static void Inverse(float[] reals) { doFFT(reals, false); } /// /// Compute the FFT inverse for real data. /// /// Reals in. /// Reals Out. public static void Inverse(float[] realIn, float[] realOut) { doFFTReals(realIn, realOut, false); } /// /// Compute inverse FFT for real in, complex out. /// /// /// /// public static void Inverse(float[] realIn, float[] realOut, float[] imagOut) { doFFTReals(realIn, realOut, imagOut, true); } /// /// Compute inverse FFT for complex in, complex out. /// /// /// /// public static void Inverse(float[] realIn, float[] imagIn, float[] realOut, float[] imagOut) { doFFT(realIn, imagIn, realOut, imagOut, false); } #endregion #region Protected static: Sine and cosine tables. /// /// Table is sin(pi/2), sin(pi/4), sin(pi/8) ... /// protected static double[] m_sinDouble = null; /// /// Same as m_sinDouble but as floats. /// protected static float[] m_sinFloat = null; /// /// Table is sin(pi/2), sin(pi/4), sin(pi/8) ... /// protected static double[] m_cosDouble = null; /// /// Same as m_sinDouble but as floats. /// protected static float[] m_cosFloat = null; /// /// Prevent race condition. /// protected static object m_tableLock = new object(); /// /// Make the tables. /// /// protected static void MakeTables() { if (m_sinDouble != null) return; lock (m_tableLock) { if (m_sinDouble != null) return; int size = 20; double [] nsd = new double[size]; float [] nsf = new float[size]; double[] ncd = new double[size]; float[] ncf = new float[size]; double pi = System.Math.PI; for (int i = 0; i < size; i++) { nsd[i] = System.Math.Sin(pi); nsf[i] = (float)(nsd[i]); ncd[i] = System.Math.Cos(pi); ncf[i] = (float)(ncd[i]); pi = pi / 2; } m_sinFloat = nsf; m_sinDouble = nsd; m_cosFloat = ncf; m_cosDouble = ncd; } } #endregion #region Protected: Compute the FFT, doubles. /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( double[] realIn, bool forward) { double[] realOut = new double[realIn.Length]; double[] imagIn = new double[realIn.Length]; double[] imagOut = new double[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { imagIn[i] = 0; } doFFT(realIn, imagIn, realOut, imagOut, forward); for (int i = 0; i < realIn.Length; i++) { realOut[i] = System.Math.Sqrt((realOut[i] * realOut[i]) + (imagOut[i] * imagOut[i])); } } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFTReals( double[] realIn, double[] realOut, bool forward) { double[] imagIn = new double[realIn.Length]; double[] imagOut = new double[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { imagIn[i] = 0; } doFFT(realIn, imagIn, realOut, imagOut, forward); for (int i = 0; i < realIn.Length; i++) { realOut[i] = System.Math.Sqrt((realOut[i] * realOut[i]) + (imagOut[i] * imagOut[i])); } } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFTReals( double[] realIn, double[] realOut, double [] imagOut, bool forward) { double[] imagIn = new double[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { imagIn[i] = 0; } doFFT(realIn, imagIn, realOut, imagOut, forward); } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( double[] realIn, double[] imagIn, bool forward) { double[] realOut = new double[realIn.Length]; double[] imagOut = new double[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { realOut[i] = realIn[i]; imagOut[i] = imagIn[i]; } doFFT(realOut, imagOut, realIn, imagIn, forward); } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( double[] realIn, double[] imagIn, double[] realOut, double[] imagOut, bool forward) { MakeTables(); int n = realIn.Length; int i; // Calculate the number of bits required int bits = 0; for (i = 1; i < n; i <<= 1) { bits++; } // Copy bitreversed. for (i = 0; i < n; i++) { int p = bitrev(i, bits); realOut[p] = realIn[i]; imagOut[p] = imagIn[i]; } performFFT(realOut, imagOut, forward); } /// /// Do a bit reversal. /// /// Value to reverse. /// The bits. /// The reversal. protected static int bitrev(int value, int bits) { // Reverse bits int rev = 0; for (int b = 0; b < bits; ++b) { rev <<= 1; rev |= value & 1; value >>= 1; } // Return reversed-bit value return rev; } /// /// Radix 2 in place. /// /// /// /// protected static void performFFT(double[] r, double[] i, bool forward) { int len = r.Length; // Perform Cooley-Tukey fft double sign = forward ? 1 : -1; int index = 0; for (int p = 1; p < len; p <<= 1) { int p2 = p << 1; // Calculate sine and cosine for angle advancing double sine = sign * m_sinDouble[index]; double cosine = m_cosDouble[index++]; // Seed the angle for the butterfly loops double wr = 1.0; double wi = 0.0; // Perform butterfly loops, just like most text books. int j; for (j = 0; j < p; ++j) { int k; for (k = j; k < len; k += p2) { int k2 = k + p; // Perform butterfly double tr = (wr * r[k2]) - (wi * i[k2]); double ti = (wr * i[k2]) + (wi * r[k2]); r[k2] = r[k] - tr; i[k2] = i[k] - ti; r[k] += tr; i[k] += ti; } // Advance angle double nwr = (wr * cosine) - (wi * sine); double nwi = (wi * cosine) + (wr * sine); wr = nwr; wi = nwi; } } } #endregion #region Protected: Compute the FFT, float. /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( float[] realIn, bool forward) { float[] realOut = new float[realIn.Length]; float[] imagIn = new float[realIn.Length]; float[] imagOut = new float[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { imagIn[i] = 0; } doFFT(realIn, imagIn, realOut, imagOut, forward); for (int i = 0; i < realIn.Length; i++) { realOut[i] = (float)System.Math.Sqrt((realOut[i] * realOut[i]) + (imagOut[i] * imagOut[i])); } } /// /// Compute the FFT. /// /// Reals in. /// Real out. protected static void doFFTReals( float[] realIn, float[] magOut, bool forward) { float[] imagIn = new float[realIn.Length]; float[] imagOut = new float[realIn.Length]; float[] realOut = new float[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { imagIn[i] = 0; } doFFT(realIn, imagIn, realOut, imagOut, forward); for (int i = 0; i < magOut.Length; i++) { magOut[i] = (float)System.Math.Sqrt((realOut[i] * realOut[i]) + (imagOut[i] * imagOut[i])); } } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFTReals( float[] realIn, float[] imagIn, float[] realOut, bool forward) { float[] imagOut = new float[realIn.Length]; doFFT(realIn, imagIn, realOut, imagOut, forward); for (int i = 0; i < realIn.Length; i++) { realOut[i] = (float)System.Math.Sqrt((realOut[i] * realOut[i]) + (imagOut[i] * imagOut[i])); } } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( float[] realIn, float[] imagIn, bool forward) { float[] realOut = new float[realIn.Length]; float[] imagOut = new float[realIn.Length]; for (int i = 0; i < realIn.Length; i++) { realOut[i] = realIn[i]; imagOut[i] = imagIn[i]; } doFFT(realOut, imagOut, realIn, imagIn, forward); } /// /// Compute the FFT. /// /// Reals in. /// Imaginary in. /// Real out. /// Imaginary out. protected static void doFFT( float[] realIn, float[] imagIn, float[] realOut, float[] imagOut, bool forward) { MakeTables(); int n = realIn.Length; int i; // Calculate the number of bits required int bits = 0; for (i = 1; i < n; i <<= 1) { bits++; } n = 1 << (bits-1); // Copy bitreversed. for (i = 0; i < n; i++) { int p = bitrev(i, bits); realOut[p] = realIn[i]; imagOut[p] = imagIn[i]; } performFFT(realOut, imagOut, forward); } /// /// Radix 2 in place. /// /// /// /// protected static void performFFT(float[] r, float[] i, bool forward) { int len = r.Length; // Perform Cooley-Tukey fft float sign = forward ? 1 : -1; int index = 0; for (int p = 1; p < len; p <<= 1) { int p2 = p << 1; // Calculate sine and cosine for angle advancing float sine = sign * m_sinFloat[index]; float cosine = m_cosFloat[index++]; // Seed the angle for the butterfly loops float wr = 1.0f; float wi = 0.0f; // Perform butterfly loops, just like most text books. int j; for (j = 0; j < p; j++) { int k; for (k = j; k < len; k += p2) { int k2 = k + p; // Perform butterfly float tr = (wr * r[k2]) - (wi * i[k2]); float ti = (wr * i[k2]) + (wi * r[k2]); r[k2] = r[k] - tr; i[k2] = i[k] - ti; r[k] += tr; i[k] += ti; } // Advance angle float nwr = (wr * cosine) - (wi * sine); float nwi = (wi * cosine) + (wr * sine); wr = nwr; wi = nwi; } } } #endregion } } ```

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.