Example #1
0
        public static double FindFundamentalFrequency_(float[] x, int sampleRate, double minFreq, double maxFreq)
        {
            float[] spectr = FftAlgorithm.Calculate(x);

            int usefullMinSpectr = Math.Max(0,
                                            (int)(minFreq * spectr.Length / sampleRate));
            int usefullMaxSpectr = Math.Min(spectr.Length,
                                            (int)(maxFreq * spectr.Length / sampleRate) + 1);

            var maxMagnitude = float.NegativeInfinity;
            var maxIndex     = -1;

            for (int i = usefullMinSpectr; i < usefullMaxSpectr; i++)
            {
                if (spectr[i] > maxMagnitude)
                {
                    maxMagnitude = spectr[i];
                    maxIndex     = i;
                }
            }

            if (maxMagnitude < 0.000_1f)
            {
                return(0);
            }
            return(maxIndex * sampleRate / (double)spectr.Length);
        }
Example #2
0
        /// <summary>
        /// Finds fundamental frequency: calculates spectrogram, finds peaks, analyzes
        /// and refines frequency by diff sample values.
        /// </summary>
        /// <param name="x">The sounds samples data</param>
        /// <param name="sampleRate">The sound sample rate</param>
        /// <param name="minFreq">The min useful frequency</param>
        /// <param name="maxFreq">The max useful frequency</param>
        /// <returns>Found frequency, 0 - otherwise</returns>
        public static double FindFundamentalFrequency(float[] x, int sampleRate, double minFreq, double maxFreq)
        {
            float[] spectr = FftAlgorithm.Calculate(x);

            int usefullMinSpectr = Math.Max(0,
                                            (int)(minFreq * spectr.Length / sampleRate));
            int usefullMaxSpectr = Math.Min(spectr.Length,
                                            (int)(maxFreq * spectr.Length / sampleRate) + 1);

            // find peaks in the FFT frequency bins
            const int PeaksCount = 3;

            int[] peakIndices;
            peakIndices = FindPeaks(spectr, usefullMinSpectr, usefullMaxSpectr - usefullMinSpectr,
                                    PeaksCount);

            if (Array.IndexOf(peakIndices, usefullMinSpectr) >= 0)
            {
                // lowest usefull frequency bin shows active
                // looks like is no detectable sound, return 0
                return(0);
            }

            // select fragment to check peak values: data offset
            const int verifyFragmentOffset = 0;
            // ... and half length of data
            int verifyFragmentLength = (int)(sampleRate / minFreq);

            // trying all peaks to find one with smaller difference value
            double minPeakValue       = Double.PositiveInfinity;
            int    minPeakIndex       = 0;
            int    minOptimalInterval = 0;

            for (int i = 0; i < peakIndices.Length; i++)
            {
                int    index = peakIndices[i];
                int    binIntervalStart = spectr.Length / (index + 1), binIntervalEnd = spectr.Length / index;
                int    interval;
                double peakValue;
                // scan bins frequencies/intervals
                ScanSignalIntervals(x, verifyFragmentOffset, verifyFragmentLength,
                                    binIntervalStart, binIntervalEnd, out interval, out peakValue);

                if (peakValue < minPeakValue)
                {
                    minPeakValue       = peakValue;
                    minPeakIndex       = index;
                    minOptimalInterval = interval;
                }
            }

            if (minPeakValue < 0.000_001 || minOptimalInterval < double.Epsilon)
            {
                return(0);
            }
            return((double)sampleRate / minOptimalInterval);
        }