Beispiel #1
0
 /* This method duplicates exactly the function
  * fft(input) in MATLAB
  * Input is e.g. an audio signal
  * Return a complex return arrray.
  * i.e. the array alternates between a real and an imaginary value
  * */
 public static double[] FFT(double[] input)
 {
     Lomont.LomontFFT fft           = new Lomont.LomontFFT();
     double[]         complexSignal = DoubleToComplexDouble(input);
     fft.FFT(complexSignal, true);
     return(complexSignal);
 }
Beispiel #2
0
        public const double TWO_PI = 2 * Math.PI; //6.283186F;

        #endregion Fields

        #region Methods

        /*
         * Mimic the original DFT function that was a part of
         * Wav2Zebra2Java.
         * Does a 2 x abs() / N before returning the value
         * */
        public static float[] DFTLomont(float[] input)
        {
            int N = input.Length;

            Lomont.LomontFFT fft = new Lomont.LomontFFT();

            // even - Re, odd - Img
            double[] complexSignal = new double[2 * N];
            for (int j = 0; j < N; j++) {
                complexSignal[2*j] = (double) input[j];
                complexSignal[2*j + 1] = 0;  // need to clear out as fft modifies buffer (phase)
            }

            fft.FFT(complexSignal, true);

            // get power spectral density
            float[] mag = new float[N];
            for (int j = 0; j < N; j++) {
                double re = complexSignal[2*j];
                double img = complexSignal[2*j + 1];
                mag[j] = (float) (2 * Math.Sqrt(re*re + img*img) / N);
            }

            // rotate left (i.e. shift the first element so it becomes the last
            float temp = mag[0];
            Array.Copy(mag, 1, mag, 0, mag.Length - 1);
            mag[mag.Length-1] = temp;
            return mag;
        }
Beispiel #3
0
        /* This method duplicates exactly the function
         * ifft(input) in MATLAB
         * Requires a complex input number to be able to exactly
         * transform back to an orginal signal
         * i.e. x = ifft(fft(x))
         * Parameter: inputComplex
         * If true, the input array is a complex arrray.
         * i.e. the array alternates between a real and an imaginary value
         * If false, the array contains only real values
         * Parameter: returnComplex
         * If true, return a complex return arrray.
         * i.e. the array alternates between a real and an imaginary value
         * If false, return only the positive real value
         * */
        public static double[] IFFT(double[] input, bool inputComplex = true, bool returnComplex = true)
        {
            Lomont.LomontFFT fft = new Lomont.LomontFFT();

            double[] complexSignal;
            if (inputComplex)
            {
                complexSignal = input;
            }
            else
            {
                complexSignal = DoubleToComplexDouble(input);
            }

            fft.FFT(complexSignal, false);

            if (returnComplex)
            {
                return(complexSignal);
            }
            else
            {
                return(Real(complexSignal));
            }
        }
Beispiel #4
0
        /*
         * Mimic the original DFT function that was a part of
         * Wav2Zebra2Java.
         * Does a 2 x abs() / N before returning the value
         * */
        public static float[] DFTLomont(float[] input)
        {
            int N = input.Length;

            Lomont.LomontFFT fft = new Lomont.LomontFFT();

            // even - Re, odd - Img
            double[] complexSignal = new double[2 * N];
            for (int j = 0; j < N; j++)
            {
                complexSignal[2 * j]     = (double)input[j];
                complexSignal[2 * j + 1] = 0;                // need to clear out as fft modifies buffer (phase)
            }

            fft.FFT(complexSignal, true);

            // get power spectral density
            float[] mag = new float[N];
            for (int j = 0; j < N; j++)
            {
                double re  = complexSignal[2 * j];
                double img = complexSignal[2 * j + 1];
                mag[j] = (float)(2 * Math.Sqrt(re * re + img * img) / N);
            }

            // rotate left (i.e. shift the first element so it becomes the last
            float temp = mag[0];

            Array.Copy(mag, 1, mag, 0, mag.Length - 1);
            mag[mag.Length - 1] = temp;
            return(mag);
        }
        /// <summary>
        /// Generate a spectrogram array spaced logarithmically
        /// </summary>
        /// <param name="samples">audio data</param>
        /// <param name="fftWindowsSize">fft window size</param>
        /// <param name="fftOverlap">overlap</param>
        /// <param name="logBins">number of log bins along the frequency axis</param>
        /// <param name="logFrequenciesIndex">array of log frequency indexes</param>
        /// <param name="logFrequencies">array of log frequencies</param>
        /// <returns>log spectrogram jagged array</returns>
        public static float[][] CreateLogSpectrogramLomont(float[] samples, int fftWindowsSize, int fftOverlap, int logBins, int[] logFrequenciesIndex, float[] logFrequencies)
        {
            LomontFFT fft = new LomontFFT();

            int numberOfSamples = samples.Length;

            // overlap must be an integer smaller than the window size
            // half the windows size is quite normal
            double[] windowArray = FFTWindowFunctions.GetWindowFunction(FFTWindowFunctions.HANNING, fftWindowsSize);

            // width of the segment - e.g. split the file into 78 time slots (numberOfSegments) and do analysis on each slot
            int numberOfSegments = (numberOfSamples - fftWindowsSize)/fftOverlap;
            float[][] frames = new float[numberOfSegments][];

            // even - Re, odd - Img
            double[] complexSignal = new double[2*fftWindowsSize];
            for (int i = 0; i < numberOfSegments; i++)
            {
                // apply Hanning Window
                for (int j = 0; j < fftWindowsSize; j++)
                {
                    // Weight by Hann Window
                    complexSignal[2*j] = (double) (windowArray[j] * samples[i * fftOverlap + j]);

                    // need to clear out as fft modifies buffer (phase)
                    complexSignal[2*j + 1] = 0;
                }

                // FFT transform for gathering the spectrum
                fft.FFT(complexSignal, true);

                frames[i] = ExtractLogBins(complexSignal, logBins, logFrequenciesIndex);
            }
            return frames;
        }
Beispiel #6
0
        /* This method duplicates exactly the function
         * ifft(input) in MATLAB
         * Requires a complex input number to be able to exactly
         * transform back to an orginal signal
         * i.e. x = ifft(fft(x))
         * Parameter: inputComplex
         * If true, the input array is a complex arrray.
         * i.e. the array alternates between a real and an imaginary value
         * If false, the array contains only real values
         * Parameter: returnComplex
         * If true, return a complex return arrray.
         * i.e. the array alternates between a real and an imaginary value
         * If false, return only the positive real value
         * */
        public static double[] IFFT(double[] input, bool inputComplex=true, bool returnComplex=true)
        {
            Lomont.LomontFFT fft = new Lomont.LomontFFT();

            double[] complexSignal;
            if (inputComplex) {
                complexSignal = input;
            } else {
                complexSignal = DoubleToComplexDouble(input);
            }

            fft.FFT(complexSignal, false);

            if (returnComplex) {
                return complexSignal;
            } else {
                return Real(complexSignal);
            }
        }
Beispiel #7
0
 /* This method duplicates exactly the function
  * fft(input) in MATLAB
  * Input is e.g. an audio signal
  * Return a complex return arrray.
  * i.e. the array alternates between a real and an imaginary value
  * */
 public static double[] FFT(double[] input)
 {
     Lomont.LomontFFT fft = new Lomont.LomontFFT();
     double[] complexSignal = DoubleToComplexDouble(input);
     fft.FFT(complexSignal, true);
     return complexSignal;
 }
Beispiel #8
0
        public static void LomontFFTTestUsingDouble(string CSVFilePath=null, double[] audio_data=null, int testLoopCount=1)
        {
            LomontFFT fft = new LomontFFT();

            if (audio_data == null) {
                audio_data = GetSignalTestData();
            }

            double[] complexSignal = FFTUtils.DoubleToComplexDouble(audio_data);

            // loop if neccesary - e.g. for performance test purposes
            for (int i = 0; i < testLoopCount; i++) {

                // perform the FFT
                fft.FFT(complexSignal, true);
            }

            // get the result
            double lengthSqrt = Math.Sqrt(audio_data.Length);

            int N = complexSignal.Length / 2;

            double[] spectrum_fft_real = new double[N];
            double[] spectrum_fft_imag = new double[N];
            double[] spectrum_fft_abs = new double[N];

            for (int j = 0; j < N; j++) {
                double re = complexSignal[2*j] * lengthSqrt;
                double img = complexSignal[2*j + 1] * lengthSqrt;

                spectrum_fft_real[j] = re;
                spectrum_fft_imag[j] = img;
                spectrum_fft_abs[j] = Math.Sqrt(re*re + img*img);
            }

            // perform the inverse FFT (IFFT)
            fft.FFT(complexSignal, false);

            double[] spectrum_inverse_real = new double[N];
            double[] spectrum_inverse_imag = new double[N];
            double[] spectrum_inverse_abs = new double[N];

            // get the result
            for (int j = 0; j < N; j++) {
                double re = complexSignal[2*j];
                double img = complexSignal[2*j + 1];

                spectrum_inverse_real[j] = re;
                spectrum_inverse_imag[j] = img;
                spectrum_inverse_abs[j] = 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);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Generate a spectrogram array spaced linearily
        /// </summary>
        /// <param name="samples">audio data</param>
        /// <param name="fftWindowsSize">fft window size</param>
        /// <param name="fftOverlap">overlap in number of samples (normaly half of the fft window size) [low number = high overlap]</param>
        /// <returns>spectrogram jagged array</returns>
        public static float[][] CreateSpectrogramLomont(float[] samples, int fftWindowsSize, int fftOverlap)
        {
            LomontFFT fft = new LomontFFT();

            int numberOfSamples = samples.Length;

            // overlap must be an integer smaller than the window size
            // half the windows size is quite normal
            double[] windowArray = FFTWindowFunctions.GetWindowFunction(FFTWindowFunctions.HANNING, fftWindowsSize);

            // width of the segment - e.g. split the file into 78 time slots (numberOfSegments) and do analysis on each slot
            int numberOfSegments = (numberOfSamples - fftWindowsSize)/fftOverlap;
            float[][] frames = new float[numberOfSegments][];

            // even - Re, odd - Img
            double[] complexSignal = new double[2*fftWindowsSize];
            for (int i = 0; i < numberOfSegments; i++)
            {
                // apply Hanning Window
                for (int j = 0; j < fftWindowsSize; j++)
                {
                    // Weight by Hann Window
                    complexSignal[2*j] = (double) (windowArray[j] * samples[i * fftOverlap + j]);

                    // need to clear out as fft modifies buffer (phase)
                    complexSignal[2*j + 1] = 0;
                }

                // FFT transform for gathering the spectrum
                fft.FFT(complexSignal, true);

                // get the ABS of the complex signal
                float[] band = new float[fftWindowsSize/2];
                for (int j = 0; j < fftWindowsSize/2; j++)
                {
                    double re = complexSignal[2*j];
                    double img = complexSignal[2*j + 1];

                    band[j] = (float) Math.Sqrt(re*re + img*img) * 4;
                }
                frames[i] = band;
            }
            return frames;
        }
Beispiel #10
0
        /// <summary>
        /// Generate a spectrum graph array spaced linearily
        /// </summary>
        /// <param name="samples">audio data</param>
        /// <param name="fftWindowsSize">fft window size</param>
        /// <param name="fftOverlap">overlap</param>
        /// <returns>spectrum graph array</returns>
        public static float[] CreateSpectrumAnalysisLomont(float[] samples, int fftWindowsSize)
        {
            LomontFFT fft = new LomontFFT();

            int numberOfSamples = samples.Length;

            // overlap must be an integer smaller than the window size
            // half the windows size is quite normal
            double[] windowArray = FFTWindowFunctions.GetWindowFunction(FFTWindowFunctions.HANNING, fftWindowsSize);

            // even - Re, odd - Img
            double[] complexSignal = new double[2*fftWindowsSize];

            // apply Hanning Window
            // e.g. take 371 ms each 11.6 ms (2048 samples each 64 samples)
            for (int j = 0; (j < fftWindowsSize) && (samples.Length > j); j++)
            {
                // Weight by Hann Window
                complexSignal[2*j] = (double) (windowArray[j] * samples[j]);

                // need to clear out as fft modifies buffer (phase)
                complexSignal[2*j + 1] = 0;
            }

            // FFT transform for gathering the spectrum
            fft.FFT(complexSignal, true);

            float[] band = new float[fftWindowsSize/2];
            double lengthSqrt = Math.Sqrt(fftWindowsSize);
            for (int j = 0; j < fftWindowsSize/2; j++)
            {
                double re = complexSignal[2*j] * lengthSqrt;
                double img = complexSignal[2*j + 1] * lengthSqrt;

                // do the Abs calculation and add with Math.Sqrt(audio_data.Length);
                // i.e. the magnitude spectrum
                band[j] = (float) (Math.Sqrt(re*re + img*img) * lengthSqrt);
            }
            return band;
        }