Exemple #1
0
        } //Analysis()

        /// <summary>
        /// returns some indices relevant to rain and cicadas from a short (10seconds) chunk of audio
        /// </summary>
        /// <param name="signal">signal envelope of a 10s chunk of audio</param>
        /// <param name="spectrogram">spectrogram of a 10s chunk of audio</param>
        /// <param name="lowFreqBound"></param>
        /// <param name="midFreqBound"></param>
        /// <param name="binWidth"></param>
        /// <returns></returns>
        public static RainStruct Get10SecondIndices(double[] signal, double[,] spectrogram, int lowFreqBound, int midFreqBound,
                                                    TimeSpan frameDuration, double binWidth)
        {
            // i: FRAME ENERGIES -
            double StandardDeviationCount = 0.1;
            var    results3 = SNR.SubtractBackgroundNoiseFromWaveform_dB(SNR.Signal2Decibels(signal), StandardDeviationCount); //use Lamel et al.
            var    dBarray  = SNR.TruncateNegativeValues2Zero(results3.NoiseReducedSignal);

            bool[] activeFrames = new bool[dBarray.Length]; //record frames with activity >= threshold dB above background and count
            for (int i = 0; i < dBarray.Length; i++)
            {
                if (dBarray[i] >= ActivityAndCover.DefaultActivityThresholdDb)
                {
                    activeFrames[i] = true;
                }
            }

            //int activeFrameCount = dBarray.Count((x) => (x >= AcousticIndices.DEFAULT_activityThreshold_dB));
            int activeFrameCount = DataTools.CountTrues(activeFrames);

            double spikeThreshold = 0.05;
            double spikeIndex     = CalculateSpikeIndex(signal, spikeThreshold);

            //Console.WriteLine("spikeIndex=" + spikeIndex);
            //DataTools.writeBarGraph(signal);

            RainStruct rainIndices;                                                                    // struct in which to store all indices

            rainIndices.activity        = activeFrameCount / (double)dBarray.Length;                   //fraction of frames having acoustic activity
            rainIndices.bgNoise         = results3.NoiseMode;                                          //bg noise in dB
            rainIndices.snr             = results3.Snr;                                                //snr
            rainIndices.avSig_dB        = 20 * Math.Log10(signal.Average());                           //10 times log of amplitude squared
            rainIndices.temporalEntropy = DataTools.EntropyNormalised(DataTools.SquareValues(signal)); //ENTROPY of ENERGY ENVELOPE
            rainIndices.spikes          = spikeIndex;

            // ii: calculate the bin id of boundary between mid and low frequency spectrum
            int lowBinBound        = (int)Math.Ceiling(lowFreqBound / binWidth);
            var midbandSpectrogram = MatrixTools.Submatrix(spectrogram, 0, lowBinBound, spectrogram.GetLength(0) - 1, spectrogram.GetLength(1) - 1);

            // iii: ENTROPY OF AVERAGE SPECTRUM and VARIANCE SPECTRUM - at this point the spectrogram is still an amplitude spectrogram
            var tuple = SpectrogramTools.CalculateAvgSpectrumAndVarianceSpectrumFromAmplitudeSpectrogram(midbandSpectrogram);

            rainIndices.spectralEntropy = DataTools.EntropyNormalised(tuple.Item1); //ENTROPY of spectral averages
            if (double.IsNaN(rainIndices.spectralEntropy))
            {
                rainIndices.spectralEntropy = 1.0;
            }

            // iv: CALCULATE Acoustic Complexity Index on the AMPLITUDE SPECTRUM
            var aciArray = AcousticComplexityIndex.CalculateAci(midbandSpectrogram);

            rainIndices.ACI = aciArray.Average();

            //v: remove background noise from the spectrogram
            double spectralBgThreshold = 0.015;      // SPECTRAL AMPLITUDE THRESHOLD for smoothing background

            //double[] modalValues = SNR.CalculateModalValues(spectrogram); //calculate modal value for each freq bin.
            //modalValues = DataTools.filterMovingAverage(modalValues, 7);  //smooth the modal profile
            //spectrogram = SNR.SubtractBgNoiseFromSpectrogramAndTruncate(spectrogram, modalValues);
            //spectrogram = SNR.RemoveNeighbourhoodBackgroundNoise(spectrogram, spectralBgThreshold);

            //vi: SPECTROGRAM ANALYSIS - SPECTRAL COVER. NOTE: spectrogram is still a noise reduced amplitude spectrogram
            SpectralActivity sa = ActivityAndCover.CalculateSpectralEvents(spectrogram, spectralBgThreshold, frameDuration, lowFreqBound, midFreqBound, binWidth);

            rainIndices.lowFreqCover = sa.LowFreqBandCover;
            rainIndices.midFreqCover = sa.MidFreqBandCover;
            rainIndices.hiFreqCover  = sa.HighFreqBandCover;

            //double[] coverSpectrum = sa.coverSpectrum;
            //double[] eventSpectrum = sa.eventSpectrum;

            return(rainIndices);
        }
Exemple #2
0
        /// <summary>
        /// Counts the number of spectral tracks or harmonics in the passed ferquency band.
        /// Also calculates the average amplitude of the peaks to each succeeding trough.
        /// </summary>
        /// <param name="values">Spectral values in the frequency band.</param>
        /// <param name="row">This argument is NOT used. Is included only for debugging purposes.</param>
        public static Tuple <double, int, bool[]> CountHarmonicTracks(double[] values, int expectedHarmonicCount)
        {
            int L = values.Length;
            int expectedPeriod = L / expectedHarmonicCount;
            int midPeriod      = expectedPeriod / 2;

            //double[] smooth = DataTools.filterMovingAverage(values, 3);
            double[] smooth    = values;
            bool[]   peaks     = DataTools.GetPeaks(smooth);
            int      peakCount = DataTools.CountTrues(peaks);

            //return if too far outside limits
            int lowerLimit = expectedHarmonicCount / 2;
            int upperLimit = expectedHarmonicCount * 2;

            if (peakCount <= lowerLimit)
            {
                return(Tuple.Create(0.0, 0, peaks));
            }
            else
            if (peakCount >= upperLimit)
            {
                return(Tuple.Create(0.0, peakCount, peaks));
            }

            // Store peak locations.
            var peakLocations = new List <int>();

            for (int i = 0; i < values.Length; i++)
            {
                if (peaks[i])
                {
                    peakLocations.Add(i);
                }
            }

            //// If have too many peaks (local maxima), remove the lowest of them
            //if (peakCount > (expectedHarmonicCount + 1))
            //{
            //    var peakValues = new double[peakCount];
            //    for (int i = 0; i < peakCount; i++) peakValues[i] = values[peakLocations[i]];
            //    IEnumerable<double> ordered = peakValues.OrderByDescending(d => d);
            //    double avValue = ordered.Take(expectedHarmonicCount).Average();
            //    double min = ordered.Last();
            //    double threshold = min + ((avValue - min) / 2);
            //    // apply threshold to remove low peaks
            //    for (int i = 0; i < L; i++)
            //    {
            //        if ((peaks[i]) && (values[i] < threshold)) peaks[i] = false;
            //    }

            //    // recalculate the number of peaks
            //    peakCount = -1;
            //    for (int i = 0; i < L; i++)
            //    {
            //        if (peaks[i])
            //        {
            //            peakCount++;
            //            peakLocations[peakCount] = i;
            //        }
            //    }
            //}

            //if (peakCount <= 1) return Tuple.Create(0.0, 0, peaks);

            double amplitude = 0.0;

            for (int i = 0; i < peakLocations.Count; i++)
            {
                int troughIndex = peakLocations[i] + midPeriod;
                if (troughIndex >= L)
                {
                    troughIndex = peakLocations[i] - midPeriod;
                }

                double delta = smooth[peakLocations[i]] - smooth[troughIndex];
                if (delta > 1.0)
                {
                    amplitude += delta; // dB threshold - required a minimum perceptible difference
                }
            }

            double avAmplitude = amplitude / peakCount;

            return(Tuple.Create(avAmplitude, peakCount, peaks));
        }