Example #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);
 }
Example #2
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);
        }
Example #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));
            }
        }
Example #4
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;
        }
Example #5
0
        /// <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;
        }
Example #6
0
        /// <summary>
        /// The main.
        /// </summary>
        /// <param name="args">
        /// The args.
        /// </param>
        static void Main(string[] args)
        {
            var audioBuffer = new byte[256];
            var fftData = new byte[256];
            var fft = new double[256];
            double fftavg = 0;
            float amplitude = 10.0f;

            var fftTransoformer = new LomontFFT();

            var writers = new List<IWriter>();
            writers.Add(new KeyboardWriter());
            writers.Add(new ConsoleWriter());

            var audioCapture = new AudioCapture(AudioCapture.DefaultDevice, 8000, ALFormat.Mono8, 256);
            audioCapture.Start();
            audioCapture.ReadSamples(audioBuffer, 256);
           
            while (true)
            {
                for (int j = 0; j < 92; j++)
                {
                    // reset mem
                    for (int i = 0; i < 256; i++)
                    {
                        audioBuffer[i] = 0;
                        fftData[i] = 0;
                        fft[i] = 0;
                    }

                    audioCapture.ReadSamples(audioBuffer, 256);

                    for (int i = 0; i < 256; i++)
                    {
                        fft[i] = (audioBuffer[i] - 128) * amplitude;
                    }

                    fftTransoformer.TableFFT(fft, true);
                    
                    for (int i = 0; i < 256; i += 2)
                    {
                        double fftmag = Math.Sqrt((fft[i] * fft[i]) + (fft[i + 1] * fft[i + 1]));
                        fftavg += fftmag;
                        fftData[i] = (byte)fftmag;
                        fftData[i + 1] = fftData[i];
                    }

                    fftavg /= 10;

                    writers.ForEach(x => x.Write(j, fftData));

                    //Thread.Sleep(15);
                    Thread.Sleep(20);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Return true if unit tests pass
        /// </summary>
        /// <returns>true if and only if the tests all passed</returns>
        public static bool UnitTest()
        {
            #region Test Data
            // some tests of various lengths. Answers are for (A,B) types (1,1), (0,1), (1,-1), and (-1,1)
            double[]   t4   = { 0.9463910302640065255, 2.1719817340114636428, 0.5408022840459105995546, 1.5560308568160938805 };
            double[]   t8   = { -0.00585152907659816402, -0.38747973044006503981, -0.07599531911180304592, 0.45076971245423087174, 0.26739426495460068114, -0.26125937528189408420, 0.41416072137518122013, -0.01641988546867230817 };
            double[]   t16  = { 1.315477046808896429519, 1.207210985661466858068, 0.121056790034505835908, -0.25379277220838383483, 0.913644534255553004335, 0.927677591320202188087, 2.235664368076910734991, -0.375686965597889518826, 2.301831908175541205636, 1.06141993445964001079, -0.06885421111166161113, 0.537848193477814512702, 1.776371630015752925985, -0.337293413841513571577, 2.476154181731257139688, -0.246423441467474887253 };
            double[]   t32  = { 0.43456805587961525780, -0.06380054971262695336, -0.488558284014200504051, -0.416304883965628375255, -0.469871270992736403590, -0.25166411067679778788, 0.40215502170455820014, -0.35830084570211135293, -0.05852687773965932269, 0.06837143745059148373, 0.39433540724645248849, -0.24284994799967130717, 0.35674139694999335405, -0.12888862317683722326, -0.483481846064623712881, 0.31470624594663715993, -0.36261847505420561595, 0.45600311160472028856, -0.32101981739601821164, -0.39660499028915120615, 0.12690816916754634235, -0.15432871988088497073, -0.20789746477910645318, 0.11641012713093763133, 0.15442520359906394183, 0.45398815306631095852, 0.26643905565987603855, -0.443374926998731886764, 0.34684336103208890521, 0.11453023518323556461, -0.24188480129115013822, -0.37645566690319011335 };
            double[][] a4R  = { new[] { 5.215205905137474648, -2.240819276517640398, 0.405588746218095926, 0.615950877195369762 }, new[] { 2.607602952568737324, -1.120409638258820199, 0.2027943731090479630, 0.307975438597684881 }, new[] { 5.215205905137474648, -2.240819276517640398, 0.405588746218095926, -0.615950877195369762 }, new[] { 1.303801476284368662, -0.560204819129410100, 0.1013971865545239815, 0.153987719298842441 } };
            double[][] a4C  = { new[] { 1.487193314309917125, 3.728012590827557523, 0.405588746218095926, 0.615950877195369762 }, new[] { 1.051604477483838966, 2.636102983322995846, 0.286794552823765311, 0.435543042142648332 }, new[] { 1.487193314309917125, 3.728012590827557523, 0.405588746218095926, 0.615950877195369762 }, new[] { 0.743596657154958563, 1.864006295413778762, 0.2027943731090479630, 0.307975438597684881 } };
            double[][] a8R  = { new[] { 0.38531885940498013, 0.81409741687778125, -0.69284999587841737, -0.24905437675199995, -0.07662266638537566, -1.08308893270751769, 0.14635840781601968, 0.73125770422196858 }, new[] { 0.13623078920216368, 0.28782690201036541, -0.24495946521535021, -0.08805401934276420, -0.027090203496846828, -0.38292976447279300, 0.05174551132518686, 0.25853864072513031 }, new[] { 0.38531885940498013, 0.81409741687778125, -0.69284999587841737, 0.24905437675199995, -0.07662266638537566, 1.08308893270751769, 0.14635840781601968, -0.73125770422196858 }, new[] { 0.048164857425622516, 0.101762177109722656, -0.086606249484802171, -0.031131797093999994, -0.009577833298171957, -0.135386116588439711, 0.018294800977002460, 0.091407213027746072 } };
            double[][] a8C  = { new[] { 0.5997081381413806913, -0.2143892787364005604, -0.7404353919541020251, -0.6163763956451552217, -0.0766226663853756571, -1.0830889327075176876, 0.1939438038917043347, 0.3639356853288133104 }, new[] { 0.2998540690706903457, -0.1071946393682002802, -0.3702176959770510125, -0.3081881978225776108, -0.0383113331926878286, -0.5415444663537588438, 0.0969719019458521674, 0.1819678426644066552 }, new[] { 0.5997081381413806913, -0.2143892787364005604, 0.1939438038917043347, 0.3639356853288133104, -0.0766226663853756571, -1.0830889327075176876, -0.7404353919541020251, -0.6163763956451552217 }, new[] { 0.1499270345353451728, -0.05359731968410014011, -0.1851088479885255063, -0.1540940989112888054, -0.01915566659634391428, -0.2707722331768794219, 0.04848595097292608369, 0.09098392133220332761 } };
            double[][] t16R = { new[] { 13.59230635979061742, 8.55038613618289391, -1.21492956216715601, -0.45486697068671133, 1.47323644084476175, -2.83216031656357654, 0.71462633901964782, 0.66109635428761313, 1.54330399052473147, 3.197070083395729214, -3.29601473130025480, -0.99282859461499410, 0.38134914058150166, 6.48707162520707076, -0.14910149101881611, 1.34211646345148113 }, new[] { 3.39807658994765436, 2.137596534045723477, -0.303732390541789004, -0.113716742671677833, 0.368309110211190438, -0.708040079140894134, 0.178656584754911956, 0.165274088571903281, 0.385825997631182867, 0.799267520848932303, -0.82400368282506370, -0.248207148653748524, 0.095337285145375415, 1.62176790630176769, -0.037275372754704028, 0.335529115862870283 }, new[] { 13.59230635979061742, 8.55038613618289391, -1.21492956216715601, 0.45486697068671133, 1.47323644084476175, 2.83216031656357654, 0.71462633901964782, -0.66109635428761313, 1.54330399052473147, -3.197070083395729214, -3.29601473130025480, 0.99282859461499410, 0.38134914058150166, -6.48707162520707076, -0.14910149101881611, -1.34211646345148113 }, new[] { 0.849519147486913589, 0.534399133511430869, -0.075933097635447251, -0.028429185667919458, 0.092077277552797609, -0.177010019785223534, 0.044664146188727989, 0.041318522142975820, 0.096456499407795717, 0.1998168802122330758, -0.206000920706265925, -0.062051787163437131, 0.023834321286343854, 0.405441976575441923, -0.009318843188676007, 0.083882278965717571 } };
            double[][] t16C = { new[] { 11.071346247986755665, 2.520960111803861757, -1.295808722180236886, -1.221072246496360113, 0.021126962378336621, -2.981369228242905398, 0.625454618595877207, 1.441125106282221185, 1.543303990524731466, 3.197070083395729214, -3.206843010876484186, -0.212799842620386036, 1.833458619047926789, 6.337862713527741902, -0.068222331005735240, 0.575911187641832353 }, new[] { 3.914312004407837382, 0.891293995078653829, -0.458137567287160258, -0.431714232908133866, 0.007469509181797447, -1.054073199255731085, 0.221131601066795241, 0.509514667595171310, 0.545640358566148453, 1.130334967948880571, -1.133790219595723673, -0.075236105876152529, 0.648225511276855981, 2.240772851482419665, -0.024120236441254322, 0.203615353071368931 }, new[] { 11.071346247986755665, 2.520960111803861757, -0.068222331005735240, 0.575911187641832353, 1.833458619047926789, 6.337862713527741902, -3.206843010876484186, -0.212799842620386036, 1.543303990524731466, 3.197070083395729214, 0.625454618595877207, 1.441125106282221185, 0.021126962378336621, -2.981369228242905398, -1.295808722180236886, -1.221072246496360113 }, new[] { 1.3839182809983444581, 0.3151200139754827196, -0.1619760902725296107, -0.1526340308120450141, 0.0026408702972920776, -0.3726711535303631747, 0.0781818273244846509, 0.1801406382852776481, 0.1929129988155914333, 0.3996337604244661517, -0.4008553763595605232, -0.0265999803275482545, 0.2291823273809908486, 0.7922328391909677378, -0.0085277913757169050, 0.0719888984552290441 } };
            double[][] a32R = { new[] { -1.46000712101570392, 1.15712078883069226, -0.56341032896397069, -0.97348179246515461, -1.56634631955235446, -2.03358236992303745, 0.10016779686778672, -0.28982229431706279, 1.59649489283936457, 0.48088940342020419, 0.61889994518995724, -0.94638900654944842, 1.44036681871883545, 0.56879809230684088, -0.40555236689846115, 1.76515791462870041, 1.208382291775918752, 2.296985822638620811, 0.63608517570432352, -0.54113478089643728, 1.89167325112076917, -0.74545011136225907, 2.66767101857698704, -0.02967504673446225, -1.98204239178352045, -0.28372150043265964, 1.51795039241265502, 1.43503462291130686, -1.86148873042323007, 0.83836086563695189, 1.80568061458128929, -0.76801487986712270 }, new[] { -0.258095233962713142, 0.204551989108527394, -0.099597816050241796, -0.172088894203436537, -0.276893526060515187, -0.359489970968497496, 0.017707332105432151, -0.051233827412659624, 0.282223091214101301, 0.085010039539794926, 0.109407087029950338, -0.167299521042878729, 0.254623286228045786, 0.100550247049034749, -0.071692207190039153, 0.312038782824764749, 0.213613828195123352, 0.406053562869282277, 0.112445035288190932, -0.095660018276941854, 0.334403745914174673, -0.131778207195130101, 0.471582066802652984, -0.005245856694491492, -0.350378903957332773, -0.050155349231088902, 0.268338253994942301, 0.253680678274516299, -0.329067826096150775, 0.148202663293328177, 0.319202251806880595, -0.135767132401553529 }, new[] { -1.46000712101570392, 1.15712078883069226, -0.56341032896397069, 0.97348179246515461, -1.56634631955235446, 2.03358236992303745, 0.10016779686778672, 0.28982229431706279, 1.59649489283936457, -0.48088940342020419, 0.61889994518995724, 0.94638900654944842, 1.44036681871883545, -0.56879809230684088, -0.40555236689846115, -1.76515791462870041, 1.208382291775918752, -2.296985822638620811, 0.63608517570432352, 0.54113478089643728, 1.89167325112076917, 0.74545011136225907, 2.66767101857698704, 0.02967504673446225, -1.98204239178352045, 0.28372150043265964, 1.51795039241265502, -1.43503462291130686, -1.86148873042323007, -0.83836086563695189, 1.80568061458128929, 0.76801487986712270 }, new[] { -0.0456252225317407476, 0.0361600246509591330, -0.017606572780124084, -0.030421306014536081, -0.048948322486011077, -0.063549449060094920, 0.003130243652118335, -0.009056946697408212, 0.0498904654012301429, 0.0150277938568813810, 0.019340623287186164, -0.029574656454670263, 0.045011463084963608, 0.017774940384588778, -0.012673511465576911, 0.055161184832146888, 0.0377619466179974610, 0.0717808069574569003, 0.019877661740760110, -0.016910461903013665, 0.059114789097524036, -0.023295315980070596, 0.083364719330530845, -0.000927345210451945, -0.0619388247432350139, -0.0088662968885206138, 0.047435949762895469, 0.044844831965978339, -0.058171522825725940, 0.026198777051154746, 0.056427519205665290, -0.024000464995847585 } };
            double[][] a32C = { new[] { -0.151443166092505834, -1.308563954923198090, 1.244058936325143007, -1.434392792279571653, -1.105324127259872307, -1.528329335338557865, -0.060884434278954178, -1.13372709101066608, 1.002720860253378163, 1.717218822886712110, 1.062676103603080428, -1.433258891213431473, 1.49134454751956007, 0.48916776214349496, -0.51494251390467968, 1.651791582176155218, 1.208382291775918752, 2.296985822638620811, 0.745475322710542044, -0.654501113348982475, 1.840695522320044552, -0.825080441525604990, 2.223894860163863861, -0.51654493139844530, -1.388268359197534037, 0.952607919033848279, 1.679002623559395916, 0.591129826217703575, -2.32251092271571222, 1.34361390022143147, -0.00178865070782441, -1.228925879681539749 }, new[] { -0.037860791523126458, -0.327140988730799523, 0.311014734081285752, -0.358598198069892913, -0.276331031814968077, -0.382082333834639466, -0.015221108569738544, -0.283431772752666519, 0.250680215063344541, 0.429304705721678028, 0.265669025900770107, -0.358314722803357868, 0.372836136879890017, 0.122291940535873739, -0.128735628476169919, 0.412947895544038804, 0.302095572943979688, 0.574246455659655203, 0.186368830677635511, -0.163625278337245619, 0.460173880580011138, -0.206270110381401247, 0.555973715040965965, -0.129136232849611326, -0.347067089799383509, 0.238151979758462070, 0.419750655889848979, 0.147782456554425894, -0.580627730678928055, 0.335903475055357867, -0.000447162676956103, -0.307231469920384937 }, new[] { -0.151443166092505834, -1.308563954923198090, -0.001788650707824411, -1.228925879681539749, -2.322510922715712221, 1.343613900221431469, 1.679002623559395916, 0.591129826217703575, -1.388268359197534037, 0.952607919033848279, 2.223894860163863861, -0.516544931398445303, 1.840695522320044552, -0.825080441525604990, 0.745475322710542044, -0.654501113348982475, 1.208382291775918752, 2.296985822638620811, -0.514942513904679676, 1.651791582176155218, 1.491344547519560067, 0.489167762143494958, 1.062676103603080428, -1.433258891213431473, 1.002720860253378163, 1.717218822886712110, -0.060884434278954178, -1.133727091010666075, -1.105324127259872307, -1.528329335338557865, 1.244058936325143007, -1.434392792279571653 }, new[] { -0.0094651978807816146, -0.0817852471826998806, 0.0777536835203214379, -0.0896495495174732283, -0.0690827579537420192, -0.0955205834586598666, -0.0038052771424346361, -0.0708579431881666297, 0.0626700537658361352, 0.1073261764304195069, 0.0664172564751925267, -0.0895786807008394671, 0.0932090342199725042, 0.0305729851339684349, -0.0321839071190424798, 0.1032369738860097011, 0.0755238932359949220, 0.1435616139149138007, 0.0465922076694088777, -0.0409063195843114047, 0.1150434701450027845, -0.0515675275953503119, 0.1389934287602414913, -0.0322840582124028314, -0.0867667724498458773, 0.0595379949396155175, 0.1049376639724622447, 0.0369456141386064734, -0.1451569326697320138, 0.0839758687638394668, -0.0001117906692390257, -0.0768078674800962343 } };

            double[][]   tests = { t4, t8, t16, t32 };
            double[][][] ansr  = { a4R, a8R, t16R, a32R };
            double[][][] ansc  = { a4C, a8C, t16C, a32C };
            #endregion

            var fftObject = new LomontFFT();

            int[] ab = { 1, 1, 0, 1, 1, -1, -1, 1 }; // A,B parameter pairs

            var success = true;

            // single test action makes debugging easier
            Action <int, int> testAction = (testIndex, paramIndex) =>
            {
                var test = tests[testIndex];
                fftObject.A = ab[2 * paramIndex];
                fftObject.B = ab[2 * paramIndex + 1];
                var answerReal    = ansr[testIndex][paramIndex];
                var answerComplex = ansc[testIndex][paramIndex];
                success &= Test(fftObject.RealFFT, test, answerReal);
                success &= Test(fftObject.FFT, test, answerComplex);
                success &= Test(fftObject.TableFFT, test, answerComplex);
            };

            for (var testIndex = 0; testIndex < tests.Length; testIndex++)
            {
                for (var t = 0; t < ab.Length / 2; t++)
                {
                    testAction(testIndex, t);
                }
            }
            return(success);
        }
Example #8
0
		public Fft(int winsize, IWindowFunction window)
		{
			this.winsize = winsize;
			this.fftsize = 2 * winsize;
			
			fftwData = fftwf_malloc(fftsize * sizeof(float));
			fftwPlan = fftwf_plan_r2r_1d(fftsize, fftwData, fftwData, FFTW_R2HC,
			                             FFTW_ESTIMATE | FFTW_DESTROY_INPUT);

			fft = new float[fftsize];
			window.Initialize(winsize);
			win = window;
			data = new float[fftsize];
			
			lomonFFT = new Lomont.LomontFFT();
		}
Example #9
0
        public Fft(int winsize, IWindowFunction window)
        {
            this.winsize = winsize;
            this.fftsize = 2 * winsize;

            fftwData = fftwf_malloc(fftsize * sizeof(float));
            fftwPlan = fftwf_plan_r2r_1d(fftsize, fftwData, fftwData, FFTW_R2HC,
                                         FFTW_ESTIMATE | FFTW_DESTROY_INPUT);

            fft = new float[fftsize];
            window.Initialize(winsize);
            win  = window;
            data = new float[fftsize];

            lomonFFT = new Lomont.LomontFFT();
        }
Example #10
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;
        }
Example #11
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);
            }
        }
Example #12
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;
 }
Example #13
0
 public AudioService()
 {
     lomonFFT = new Lomont.LomontFFT();
 }
Example #14
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);
            }
        }
Example #15
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;
        }
		///
		/// <summary> * Create an FFT transformer for a given sample size. This preallocates
		/// * resources appropriate to that block size. A specified window
		/// * function will be applied to all input data.
		/// *  </summary>
		/// * <param name="size"> The number of samples in a block that we will
		/// *                      be asked to transform. Must be a power of 2. </param>
		/// * <param name="window"> Window function to apply to all input data.
		/// *                      Its block size must be the same as the size
		/// *                      parameter. </param>
		/// * <exception cref="IllegalArgumentException"> Invalid parameter. </exception>
		///
		public FFTTransformer(int size, Window window)
		{
			if (!IsPowerOf2(size))
			{
				throw new System.ArgumentException("size for FFT must" + " be a power of 2 (was " + size + ")");
			}

			windowFunc = window;
			transformer = new LomontFFT();
			blockSize = size;

			// Allocate working data arrays.
			xre = new double[blockSize];
		}