using System; namespace SoundAnalysis { /// /// Cooley-Tukey FFT algorithm. /// public static class FftAlgorithm { /// /// Calculates FFT using Cooley-Tukey FFT algorithm. /// /// input data /// spectrogram of the data /// /// If amount of data items not equal a power of 2, then algorithm /// automatically pad with 0s to the lowest amount of power of 2. /// public static double[] Calculate(double[] x) { int length; int bitsInLength; if (IsPowerOfTwo(x.Length)) { length = x.Length; bitsInLength = Log2(length) - 1; } else { bitsInLength = Log2(x.Length); length = 1 << bitsInLength; // the items will be pad with zeros } // bit reversal ComplexNumber[] data = new ComplexNumber[length]; for (int i = 0; i < x.Length; i++) { int j = ReverseBits(i, bitsInLength); data[j] = new ComplexNumber(x[i]); } // Cooley-Turkey for (int i = 0; i < bitsInLength; i++) { int m = 1 << i; int n = m * 2; double alpha = -(2 * Math.PI / n); for (int k = 0; k < m; k++) { // e^(-2*pi*i/N*k) ComplexNumber oddPartMultiplier = new ComplexNumber(0, alpha * k).PoweredE(); for (int j = k; j < length; j += n) { ComplexNumber evenPart = data[j]; ComplexNumber oddPart = oddPartMultiplier * data[j + m]; data[j] = evenPart + oddPart; data[j + m] = evenPart - oddPart; } } } // calculate spectrogram double[] spectrogram = new double[length]; for (int i = 0; i < spectrogram.Length; i++) { spectrogram[i] = data[i].AbsPower2(); } return spectrogram; } /// /// Gets number of significat bytes. /// /// Number /// Amount of minimal bits to store the number. private static int Log2(int n) { int i = 0; while (n > 0) { ++i; n >>= 1; } return i; } /// /// Reverses bits in the number. /// /// Number /// Significant bits in the number. /// Reversed binary number. private static int ReverseBits(int n, int bitsCount) { int reversed = 0; for (int i = 0; i < bitsCount; i++) { int nextBit = n & 1; n >>= 1; reversed <<= 1; reversed |= nextBit; } return reversed; } /// /// Checks if number is power of 2. /// /// number /// true if n=2^k and k is positive integer private static bool IsPowerOfTwo(int n) { return n > 1 && (n & (n - 1)) == 0; } } }