Пример #1
0
        /// <summary>
        /// Implements the "Adaptive Level Equalisatsion" algorithm of Lamel et al, 1981 - with modifications for our signals.
        /// Units are assumed to be decibels.
        /// Returns the min and max frame dB AND the estimate MODAL or BACKGROUND noise for the signal array
        /// IF This modal noise is subtracted from each frame dB, the effect is to set set average background noise level = 0 dB.
        /// The algorithm is described in Lamel et al, 1981.
        /// USED TO SEGMENT A RECORDING INTO SILENCE AND VOCALISATION
        /// NOTE: noiseThreshold is passed as decibels. Original Lamel algorithm ONLY SEARCHES in range min to 10dB above min.
        ///
        /// This method debugged on 7 Aug 2018 using following command line arguments:
        /// audio2csv Y:\TheNatureConservency\Myanmar\20180517\site112\2018_02_14_Bar5\20180214_Bar5\20180214_101121_Bar5.wav Towsey.Acoustic.yml C:\Temp... -m True
        /// </summary>
        /// <param name="dBarray">signal in decibel values</param>
        /// <param name="minDb">minimum value in the passed array of decibel values</param>
        /// <param name="maxDb">maximum value in the passed array of decibel values</param>
        /// <param name="modeNoise">modal or background noise in decibels</param>
        /// <param name="sdNoise">estimated sd of the noies - assuming noise to be guassian</param>
        public static void CalculateNoiseUsingLamelsAlgorithm(
            double[] dBarray,
            out double minDb,
            out double maxDb,
            out double modeNoise,
            out double sdNoise)
        {
            // set constants
            double noiseThreshold_DB = 10.0; // dB
            var    binCount          = 100;  // number of bins for histogram is FIXED
            double histogramBinWidth = noiseThreshold_DB / binCount;

            //ignore first N and last N frames when calculating background noise level because
            // sometimes these frames have atypically low signal values
            int buffer = 20; //ignore first N and last N frames when calculating background noise level

            //HOWEVER do not ignore them for short recordings!
            int arrayLength = dBarray.Length;

            if (arrayLength < 1000)
            {
                buffer = 0; //ie recording is < approx 11 seconds long
            }

            double min = double.MaxValue;
            double max = -double.MaxValue;

            for (int i = buffer; i < arrayLength - buffer; i++)
            {
                if (dBarray[i] < min)
                {
                    min = dBarray[i];
                }
                else if (dBarray[i] > max)
                {
                    max = dBarray[i];
                }
            }

            if (min <= SNR.MinimumDbBoundForEnvironmentalNoise)
            {
                min = SNR.MinimumDbBoundForEnvironmentalNoise;
            }

            // return the outs!
            minDb = min;
            maxDb = max;

            var histo        = new int[binCount];
            var absThreshold = minDb + noiseThreshold_DB;

            for (var i = 0; i < arrayLength; i++)
            {
                if (dBarray[i] <= absThreshold)
                {
                    var id = (int)((dBarray[i] - minDb) / histogramBinWidth);
                    if (id >= binCount)
                    {
                        id = binCount - 1;
                    }
                    else if (id < 0)
                    {
                        id = 0;
                    }

                    histo[id]++;
                }
            }

            var smoothHisto = DataTools.filterMovingAverage(histo, 3);

            //DataTools.writeBarGraph(histo);

            // find peak of lowBins histogram
            SNR.GetModeAndOneStandardDeviation(smoothHisto, out var indexOfMode, out var indexOfOneSd);

            // return remaining outs!
            modeNoise = min + ((indexOfMode + 1) * histogramBinWidth);    // modal noise level
            sdNoise   = (indexOfMode - indexOfOneSd) * histogramBinWidth; // SD of the noise
        }