コード例 #1
0
        /// <summary>
        /// returns oscillations using the DCT.
        /// </summary>
        public static void GetOscillationUsingDct(double[] array, double framesPerSecond, double[,] cosines, out double oscilFreq, out double period, out double intenisty)
        {
            var modifiedArray = DataTools.SubtractMean(array);
            var dctCoeff      = MFCCStuff.DCT(modifiedArray, cosines);

            // convert to absolute values because not interested in negative values due to phase.
            for (int i = 0; i < dctCoeff.Length; i++)
            {
                dctCoeff[i] = Math.Abs(dctCoeff[i]);
            }

            // remove low freq oscillations from consideration
            int thresholdIndex = dctCoeff.Length / 5;

            for (int i = 0; i < thresholdIndex; i++)
            {
                dctCoeff[i] = 0.0;
            }

            dctCoeff = DataTools.normalise2UnitLength(dctCoeff);

            //dct = DataTools.NormaliseMatrixValues(dctCoeff); //another option to NormaliseMatrixValues
            int indexOfMaxValue = DataTools.GetMaxIndex(dctCoeff);

            //recalculate DCT duration in seconds
            double dctDuration = dctCoeff.Length / framesPerSecond;

            oscilFreq = indexOfMaxValue / dctDuration * 0.5;                             //Times 0.5 because index = Pi and not 2Pi
            period    = 2 * dctCoeff.Length / (double)indexOfMaxValue / framesPerSecond; //convert maxID to period in seconds
            intenisty = dctCoeff[indexOfMaxValue];
        }
コード例 #2
0
        public static double[] DoDct(double[] vector, double[,] cosines, int lowerDctBound)
        {
            //var dctArray = DataTools.Vector2Zscores(dctArray);
            var dctArray  = DataTools.SubtractMean(vector);
            int dctLength = dctArray.Length;

            double[] dctCoeff = MFCCStuff.DCT(dctArray, cosines);

            // convert to absolute values because not interested in negative values due to phase.
            for (int i = 0; i < dctLength; i++)
            {
                dctCoeff[i] = Math.Abs(dctCoeff[i]);
            }

            // remove lower coefficients from consideration because they dominate
            for (int i = 0; i < lowerDctBound; i++)
            {
                dctCoeff[i] = 0.0;
            }

            dctCoeff = DataTools.normalise2UnitLength(dctCoeff);
            return(dctCoeff);
        }
コード例 #3
0
        /// <summary>
        /// THIS METHOD NO LONGER IN USE.
        /// NOT USEFUL FOR ANIMAL CALLS.
        /// Tried this but it is suitable only when there is guarantee of numerous spectral tracks as in the vowels of human speech.
        /// It yields SPURIOUS RESULTS where there is only one whistle track.
        /// </summary>
        public static double[,] DetectHarmonicsUsingDCT(double[,] matrix, int minBin, int maxBin, int hzWidth, bool normaliseDCT, int minPeriod, int maxPeriod, double dctThreshold)
        {
            int dctLength = maxBin - minBin + 1;                   //DCT spans N freq bins

            int minIndex = (int)(hzWidth / (double)maxPeriod * 2); //Times 0.5 because index = Pi and not 2Pi
            int maxIndex = (int)(hzWidth / (double)minPeriod * 2); //Times 0.5 because index = Pi and not 2Pi

            //double period = hzWidth / (double)indexOfMaxValue * 2; //Times 2 because index = Pi and not 2Pi
            if (maxIndex > dctLength)
            {
                maxIndex = dctLength; //safety check in case of future changes to code.
            }

            int rows = matrix.GetLength(0);
            int cols = matrix.GetLength(1);

            double[,] hits = new double[rows, cols];

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients

            for (int r = 0; r < rows - dctLength; r++)
            {
                //for (int c = minBin; c <= minBin; c++)//traverse columns - skip DC column
                //{
                var array = new double[dctLength];

                //accumulate J rows of values
                for (int i = 0; i < dctLength; i++)
                {
                    for (int j = 0; j < 5; j++)
                    {
                        array[i] += matrix[r + j, minBin + i];
                    }
                }

                array = DataTools.SubtractMean(array);

                //     DataTools.writeBarGraph(array);

                double[] dct = MFCCStuff.DCT(array, cosines);
                for (int i = 0; i < dctLength; i++)
                {
                    dct[i] = Math.Abs(dct[i]); //convert to absolute values
                }

                for (int i = 0; i < 5; i++)
                {
                    dct[i] = 0.0;  //remove low freq values from consideration
                }

                if (normaliseDCT)
                {
                    dct = DataTools.normalise2UnitLength(dct);
                }

                int indexOfMaxValue = DataTools.GetMaxIndex(dct);

                //DataTools.writeBarGraph(dct);

                double period = hzWidth / (double)indexOfMaxValue * 2; //Times 2 because index = Pi and not 2Pi

                //mark DCT location with harmonic freq, only if harmonic freq is in correct range and amplitude
                if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dct[indexOfMaxValue] > dctThreshold)
                {
                    for (int i = 0; i < dctLength; i++)
                    {
                        hits[r, minBin + i] = period;
                    }

                    for (int i = 0; i < dctLength; i++)
                    {
                        hits[r + 1, minBin + i] = period; //alternate row
                    }
                }

                //c += 5; //skip columns
                //}
                r++; //do alternate row
            }

            return(hits);
        }
コード例 #4
0
        /// <summary>
        /// Currently this method is called by only one species recognizer - LitoriaCaerulea.
        /// </summary>
        /// <param name="ipArray">an array of decibel values.</param>
        /// <param name="framesPerSecond">the frame rate.</param>
        /// <param name="decibelThreshold">Ignore frames below this threshold.</param>
        /// <param name="dctDuration">Duration in seconds of the required DCT.</param>
        /// <param name="minOscFreq">minimum oscillation frequency.</param>
        /// <param name="maxOscFreq">maximum oscillation frequency.</param>
        /// <param name="dctThreshold">Threshold for the maximum DCT coefficient.</param>
        /// <param name="dctScores">an array of dct scores.</param>
        /// <param name="oscFreq">an array of oscillation frequencies.</param>
        public static void DetectOscillations(
            double[] ipArray,
            double framesPerSecond,
            double decibelThreshold,
            double dctDuration,
            double minOscFreq,
            double maxOscFreq,
            double dctThreshold,
            out double[] dctScores,
            out double[] oscFreq)
        {
            int dctLength = (int)Math.Round(framesPerSecond * dctDuration);
            int minIndex  = (int)(minOscFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
            int maxIndex  = (int)(maxOscFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi

            if (maxIndex > dctLength)
            {
                LoggedConsole.WriteWarnLine("MaxIndex > DCT length. Therefore set maxIndex = DCT length.");
                maxIndex = dctLength;
            }

            int length = ipArray.Length;

            dctScores = new double[length];
            oscFreq   = new double[length];

            //set up the cosine coefficients
            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength);

            //following two lines write bmp image of cosine matrix values for checking.
            //string bmpPath = @"C:\SensorNetworks\Output\cosines.png";
            //ImageTools.DrawMatrix(cosines, bmpPath, true);

            for (int r = 1; r < length - dctLength; r++)
            {
                // only stop if current location is a peak
                if (ipArray[r] < ipArray[r - 1] || ipArray[r] < ipArray[r + 1])
                {
                    continue;
                }

                // only stop if current location is a peak
                if (ipArray[r] < decibelThreshold)
                {
                    continue;
                }

                // extract array and ready for DCT
                var dctArray = DataTools.Subarray(ipArray, r, dctLength);

                dctArray = DataTools.SubtractMean(dctArray);
                double[] dctCoefficient = MFCCStuff.DCT(dctArray, cosines);

                // convert to absolute values because not interested in negative values due to phase.
                for (int i = 0; i < dctLength; i++)
                {
                    dctCoefficient[i] = Math.Abs(dctCoefficient[i]);
                }

                // remove low freq oscillations from consideration
                int thresholdIndex = minIndex / 4;
                for (int i = 0; i < thresholdIndex; i++)
                {
                    dctCoefficient[i] = 0.0;
                }

                dctCoefficient = DataTools.normalise2UnitLength(dctCoefficient);

                int indexOfMaxValue = DataTools.GetMaxIndex(dctCoefficient);

                //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
                if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dctCoefficient[indexOfMaxValue] > dctThreshold)
                {
                    for (int i = 0; i < dctLength; i++)
                    {
                        if (dctScores[r + i] < dctCoefficient[indexOfMaxValue])
                        {
                            dctScores[r + i] = dctCoefficient[indexOfMaxValue];
                            oscFreq[r + i]   = indexOfMaxValue / dctDuration / 2;
                        }
                    }
                }
            }
        }
コード例 #5
0
        } // end method ConvertODScores2Events()

        /*
         *      public static double PeakEntropy(double[] array)
         *      {
         *          bool[] peaks = DataTools.GetPeaks(array);
         *          int peakCount = DataTools.CountTrues(peaks);
         *          //set up histogram of peak energies
         *          double[] histogram = new double[peakCount];
         *          int count = 0;
         *          for (int k = 0; k < array.Length; k++)
         *          {
         *              if (peaks[k])
         *              {
         *                  histogram[count] = array[k];
         *                  count++;
         *              }
         *          }
         *          histogram = DataTools.NormaliseMatrixValues(histogram);
         *          histogram = DataTools.Normalise2Probabilites(histogram);
         *          double normFactor = Math.Log(histogram.Length) / DataTools.ln2;  //normalize for length of the array
         *          double entropy = DataTools.Entropy(histogram) / normFactor;
         *          return entropy;
         *      }
         *
         */

        /// <summary>
        /// returns the periodicity in an array of values.
        /// </summary>
        public static double[] PeriodicityAnalysis(double[] array)
        {
            //DataTools.writeBarGraph(array);
            var A         = AutoAndCrossCorrelation.MyCrossCorrelation(array, array); // do 2/3rds of maximum possible lag
            int dctLength = A.Length;

            A = DataTools.SubtractMean(A);

            //DataTools.writeBarGraph(A);

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients
            double[] dct = MFCCStuff.DCT(A, cosines);

            for (int i = 0; i < dctLength; i++)
            {
                dct[i] = Math.Abs(dct[i]); //convert to absolute values
            }

            //DataTools.writeBarGraph(dct);
            for (int i = 0; i < 3; i++)
            {
                dct[i] = 0.0;   //remove low freq oscillations from consideration
            }

            dct = DataTools.normalise2UnitLength(dct);
            var peaks = DataTools.GetPeaks(dct);

            // remove non-peak values and low values
            for (int i = 0; i < dctLength; i++)
            {
                if (!peaks[i] || dct[i] < 0.2)
                {
                    dct[i] = 0.0;
                }
            }

            DataTools.writeBarGraph(dct);

            //get periodicity of highest three values
            int peakCount = 3;
            var period    = new double[peakCount];
            var maxIndex  = new double[peakCount];

            for (int i = 0; i < peakCount; i++)
            {
                int indexOfMaxValue = DataTools.GetMaxIndex(dct);
                maxIndex[i] = indexOfMaxValue;

                //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi
                if ((double)indexOfMaxValue == 0)
                {
                    period[i] = 0.0;
                }
                else
                {
                    period[i] = dctLength / (double)indexOfMaxValue * 2;
                }

                dct[indexOfMaxValue] = 0.0; // remove value for next iteration
            }

            LoggedConsole.WriteLine("Max indices = {0:f0},  {1:f0},  {2:f0}.", maxIndex[0], maxIndex[1], maxIndex[2]);
            return(period);
        }
コード例 #6
0
        /*
         *
         *      /// <summary>
         *      /// Detects oscillations in a given freq bin.
         *      /// there are several important parameters for tuning.
         *      /// a) DCTLength: Good values are 0.25 to 0.50 sec. Do not want too long because DCT requires stationarity.
         *      ///     Do not want too short because too small a range of oscillations
         *      /// b) DCTindex: Sets lower bound for oscillations of interest. Index refers to array of coeff returned by DCT.
         *      ///     Array has same length as the length of the DCT. Low freq oscillations occur more often by chance. Want to exclude them.
         *      /// c) MinAmplitude: minimum acceptable value of a DCT coefficient if hit is to be accepted.
         *      ///     The algorithm is sensitive to this value. A lower value results in more oscillation hits being returned.
         *      /// </summary>
         *      /// <param name="minBin">min freq bin of search band</param>
         *      /// <param name="maxBin">max freq bin of search band</param>
         *      /// <param name="dctLength">number of values</param>
         *      /// <param name="DCTindex">Sets lower bound for oscillations of interest.</param>
         *      /// <param name="minAmplitude">threshold - do not accept a DCT value if its amplitude is less than this threshold</param>
         *      public static Double[,] DetectOscillations(SpectrogramStandard sonogram, int minHz, int maxHz,
         *                                                 double dctDuration, int minOscilFreq, int maxOscilFreq, double minAmplitude)
         *      {
         *          int minBin = (int)(minHz / sonogram.FBinWidth);
         *          int maxBin = (int)(maxHz / sonogram.FBinWidth);
         *
         *          int dctLength = (int)Math.Round(sonogram.FramesPerSecond * dctDuration);
         *          int minIndex = (int)(minOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
         *          int maxIndex = (int)(maxOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
         *          if (maxIndex > dctLength) maxIndex = dctLength; //safety check in case of future changes to code.
         *
         *          int rows = sonogram.Data.GetLength(0);
         *          int cols = sonogram.Data.GetLength(1);
         *          Double[,] hits = new Double[rows, cols];
         *          Double[,] matrix = sonogram.Data;
         *          //matrix = ImageTools.WienerFilter(sonogram.Data, 3);// DO NOT USE - SMUDGES EVERYTHING
         *
         *
         *          double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients
         *          //following two lines write matrix of cos values for checking.
         *          //string fPath = @"C:\SensorNetworks\Sonograms\cosines.txt";
         *          //FileTools.WriteMatrix2File_Formatted(cosines, fPath, "F3");
         *
         *          //following two lines write bmp image of cos values for checking.
         *          //string fPath = @"C:\SensorNetworks\Output\cosines.bmp";
         *          //ImageTools.DrawMatrix(cosines, fPath);
         *
         *
         *
         *          // traverse columns - skip DC column
         *
         *
         *          for (int c = minBin; c <= maxBin; c++)                    {
         *              for (int r = 0; r < rows - dctLength; r++)
         *              {
         *                  var array = new double[dctLength];
         *                  //accumulate J columns of values
         *                  for (int i = 0; i < dctLength; i++)
         *                      for (int j = 0; j < 5; j++) array[i] += matrix[r + i, c + j];
         *
         *                  array = DataTools.SubtractMean(array);
         *                  //     DataTools.writeBarGraph(array);
         *
         *                  double[] dct = MFCCStuff.DCT(array, cosines);
         *                  for (int i = 0; i < dctLength; i++) dct[i] = Math.Abs(dct[i]);//convert to absolute values
         *                  dct[0] = 0.0; dct[1] = 0.0; dct[2] = 0.0; dct[3] = 0.0; dct[4] = 0.0;//remove low freq oscillations from consideration
         *                  dct = DataTools.normalise2UnitLength(dct);
         *                  //dct = DataTools.NormaliseMatrixValues(dct); //another option to NormaliseMatrixValues
         *                  int indexOfMaxValue = DataTools.GetMaxIndex(dct);
         *                  double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi
         *
         *                  //DataTools.MinMax(dct, out min, out max);
         *                  //      DataTools.writeBarGraph(dct);
         *
         *                  //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
         *                  if ((indexOfMaxValue >= minIndex) && (indexOfMaxValue <= maxIndex) && (dct[indexOfMaxValue] > minAmplitude))
         *                  {
         *                      for (int i = 0; i < dctLength; i++) hits[r + i, c] = oscilFreq;
         *                  }
         *                  r += 5; //skip rows
         *              }
         *              c++; //do alternate columns
         *          }
         *          return hits;
         *      }
         */

        public static double[] DetectOscillationsInScoreArray(double[] scoreArray, double dctDuration, double timeScale, double dctThreshold,
                                                              bool normaliseDCT, int minOscilFreq, int maxOscilFreq)
        {
            int dctLength = (int)Math.Round(timeScale * dctDuration);
            int minIndex  = (int)(minOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
            int maxIndex  = (int)(maxOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi

            if (maxIndex > dctLength)
            {
                maxIndex = dctLength; //safety check in case of future changes to code.
            }

            int length = scoreArray.Length;

            double[] hits = new double[length];

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients

            //following two lines write matrix of cos values for checking.
            //string fPath = @"C:\SensorNetworks\Sonograms\cosines.txt";
            //FileTools.WriteMatrix2File_Formatted(cosines, fPath, "F3");

            //following two lines write bmp image of cos values for checking.
            //string fPath = @"C:\SensorNetworks\Output\cosines.bmp";
            //ImageTools.DrawMatrix(cosines, fPath);

            for (int r = 0; r < length - dctLength; r++)
            {
                var array = new double[dctLength];

                //transfer values
                for (int i = 0; i < dctLength; i++)
                {
                    array[i] = scoreArray[r + i];
                }

                array = DataTools.SubtractMean(array);

                //     DataTools.writeBarGraph(array);

                double[] dct = MFCCStuff.DCT(array, cosines);
                for (int i = 0; i < dctLength; i++)
                {
                    dct[i] = Math.Abs(dct[i]); //convert to absolute values
                }

                for (int i = 0; i < 5; i++)
                {
                    dct[i] = 0.0;   //remove low freq oscillations from consideration
                }

                if (normaliseDCT)
                {
                    dct = DataTools.normalise2UnitLength(dct);
                }

                int    indexOfMaxValue = DataTools.GetMaxIndex(dct);
                double oscilFreq       = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

                //      DataTools.writeBarGraph(dct);
                //LoggedConsole.WriteLine("oscilFreq = " + oscilFreq);

                //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
                if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dct[indexOfMaxValue] > dctThreshold)
                {
                    hits[r]     = dct[indexOfMaxValue];
                    hits[r + 1] = dct[indexOfMaxValue]; // because skipping rows.

                    //for (int i = 0; i < dctLength; i++) if (hits[r + i] < dct[indexOfMaxValue]) hits[r + i] = dct[indexOfMaxValue];
                }

                r += 1; //skip rows
            }

            return(hits);
        }
コード例 #7
0
        /*
         *      /// <summary>
         *      /// FINDS OSCILLATIONS IN A SONOGRAM
         *      /// SAME METHOD AS ABOVE BUT .....
         *      /// 1) WITHOUT CALCULATING THE COMPUTATION TIME
         *      /// 2) WITHOUT DOING SEGMENTATION
         *      /// </summary>
         *      /// <param name="sonogram">sonogram derived from the recording</param>
         *      /// <param name="minHz">min bound freq band to search</param>
         *      /// <param name="maxHz">max bound freq band to search</param>
         *      /// <param name="dctDuration">duration of DCT in seconds</param>
         *      /// <param name="dctThreshold">minimum amplitude of DCT </param>
         *      /// <param name="minOscilFreq">ignore oscillation frequencies below this threshold</param>
         *      /// <param name="maxOscilFreq">ignore oscillation frequencies greater than this </param>
         *      /// <param name="scoreThreshold">used for FP/FN</param>
         *      /// <param name="minDuration">ignore hits whose duration is shorter than this</param>
         *      /// <param name="maxDuration">ignore hits whose duration is longer than this</param>
         *      /// <param name="scores">return an array of scores over the entire recording</param>
         *      /// <param name="events">return a list of acoustic events</param>
         *      /// <param name="hits">a matrix to be superimposed over the final sonogram which shows where the DCT coefficients exceeded the threshold</param>
         *      public static void Execute(SpectrogramStandard sonogram, int minHz, int maxHz,
         *                                 double dctDuration, double dctThreshold, bool normaliseDCT, double minOscilFreq, double maxOscilFreq,
         *                                 double scoreThreshold, double minDuration, double maxDuration,
         *                                 out double[] scores, out List<AcousticEvent> events, out Double[,] hits, out double[] oscFreq)
         *      {
         *          //convert the entire recording to an acoustic event - this is the legacy of previous experimentation!!!!!!!!!
         *          List<AcousticEvent> segmentEvents = new List<AcousticEvent>();
         *          var ae = new AcousticEvent(0.0, sonogram.Duration.TotalSeconds, minHz, maxHz);
         *          ae.SetTimeAndFreqScales(sonogram.FramesPerSecond, sonogram.FBinWidth);
         *          segmentEvents.Add(ae);
         *
         *          //DETECT OSCILLATIONS
         *          hits = DetectOscillationsInSonogram(sonogram, minHz, maxHz, dctDuration, dctThreshold, normaliseDCT, minOscilFreq, maxOscilFreq, segmentEvents);
         *          hits = RemoveIsolatedOscillations(hits);
         *
         *          //EXTRACT SCORES AND ACOUSTIC EVENTS
         *          scores = GetOscillationScores(hits, minHz, maxHz, sonogram.FBinWidth);//scores = fraction of BW bins in each row that have an oscilation hit.
         *          scores = DataTools.filterMovingAverage(scores, 3);
         *          oscFreq = GetOscillationFrequency(hits, minHz, maxHz, sonogram.FBinWidth);
         *          events = ConvertODScores2Events(scores, oscFreq, minHz, maxHz, sonogram.FramesPerSecond, sonogram.FBinWidth, sonogram.Configuration.FreqBinCount, scoreThreshold,
         *                                          minDuration, maxDuration, sonogram.Configuration.SourceFName);
         *      }
         *
         */

        /// <summary>
        /// Detects oscillations in a given freq bin.
        /// there are several important parameters for tuning.
        /// a) dctDuration: Good values are 0.25 to 0.50 sec. Do not want too long because DCT requires stationarity.
        ///     Do not want too short because too small a range of oscillations
        /// b) dctThreshold: minimum acceptable value of a DCT coefficient if hit is to be accepted.
        ///     The algorithm is sensitive to this value. A lower value results in more oscillation hits being returned.
        /// c) Min and Max Oscillaitons: Sets lower &amp; upper bound for oscillations of interest.
        ///     Array has same length as the length of the DCT. Low freq oscillations occur more often by chance. Want to exclude them.
        /// </summary>
        /// <param name="minHz">min freq bin of search band.</param>
        /// <param name="maxHz">max freq bin of search band.</param>
        public static double[,] DetectOscillationsInSonogram(SpectrogramStandard sonogram, int minHz, int maxHz, double dctDuration, double dctThreshold,
                                                             bool normaliseDCT, double minOscilFreq, double maxOscilFreq, List <AcousticEvent> events)
        {
            if (events == null)
            {
                return(null);
            }

            int minBin = (int)(minHz / sonogram.FBinWidth);
            int maxBin = (int)(maxHz / sonogram.FBinWidth);

            int dctLength = (int)Math.Round(sonogram.FramesPerSecond * dctDuration);
            int minIndex  = (int)(minOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
            int maxIndex  = (int)(maxOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi

            if (maxIndex > dctLength)
            {
                maxIndex = dctLength; //safety check in case of future changes to code.
            }

            int rows = sonogram.Data.GetLength(0);
            int cols = sonogram.Data.GetLength(1);

            double[,] hits = new double[rows, cols];

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients

            //following two lines write matrix of cos values for checking.
            //string fPath = @"C:\SensorNetworks\Sonograms\cosines.txt";
            //FileTools.WriteMatrix2File_Formatted(cosines, fPath, "F3");

            //following two lines write bmp image of cos values for checking.
            string fPath = @"C:\SensorNetworks\Output\cosines.bmp";

            ImageTools.DrawMatrix(cosines, fPath, true);

            foreach (AcousticEvent av in events)
            {
                int startRow = (int)Math.Round(av.TimeStart * sonogram.FramesPerSecond);
                int endRow   = (int)Math.Round(av.TimeEnd * sonogram.FramesPerSecond);
                if (endRow >= sonogram.FrameCount)
                {
                    endRow = sonogram.FrameCount - 1;
                }

                endRow -= dctLength;
                if (endRow <= startRow)
                {
                    endRow = startRow + 1;  //want minimum of one row
                }

                // traverse columns
                for (int c = minBin; c <= maxBin; c++)
                {
                    for (int r = startRow; r < endRow; r++)
                    {
                        var array = new double[dctLength];

                        //accumulate J columns of values
                        int N = 5; //average five rows
                        for (int i = 0; i < dctLength; i++)
                        {
                            for (int j = 0; j < N; j++)
                            {
                                array[i] += sonogram.Data[r + i, c + j];
                            }

                            array[i] /= N;
                        }

                        array = DataTools.SubtractMean(array);

                        //     DataTools.writeBarGraph(array);

                        //double entropy = PeakEntropy(array);
                        //if (entropy < 0.85)
                        //{
                        //    r += 6; //skip rows
                        //    continue;
                        //}

                        int      lowFreqBuffer = 5;
                        double[] dct           = MFCCStuff.DCT(array, cosines);
                        for (int i = 0; i < dctLength; i++)
                        {
                            dct[i] = Math.Abs(dct[i]); //convert to absolute values
                        }

                        for (int i = 0; i < lowFreqBuffer; i++)
                        {
                            dct[i] = 0.0;         //remove low freq oscillations from consideration
                        }

                        if (normaliseDCT)
                        {
                            dct = DataTools.normalise2UnitLength(dct);
                        }

                        int    indexOfMaxValue = DataTools.GetMaxIndex(dct);
                        double oscilFreq       = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

                        //DataTools.writeBarGraph(dct);
                        //LoggedConsole.WriteLine("oscilFreq ={0:f2}  (max index={1})  Amp={2:f2}", oscilFreq, indexOfMaxValue, dct[indexOfMaxValue]);

                        //calculate specificity i.e. what other oscillations are present.
                        //double offMaxAmplitude = 0.0;
                        //for (int i = lowFreqBuffer; i < dctLength; i++) offMaxAmplitude += dct[i];
                        //offMaxAmplitude -= (dct[indexOfMaxValue-1] + dct[indexOfMaxValue] + dct[indexOfMaxValue+1]);
                        //offMaxAmplitude /= (dctLength - lowFreqBuffer - 3); //get average
                        //double specificity = 2 * (0.5 - (offMaxAmplitude / dct[indexOfMaxValue]));
                        ////LoggedConsole.WriteLine("avOffAmp={0:f2}   specificity ={1:f2}", offMaxAmplitude, specificity);
                        //double threshold = dctThreshold + dctThreshold;

                        //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
                        if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dct[indexOfMaxValue] > dctThreshold)

                        //if ((indexOfMaxValue >= minIndex) && (indexOfMaxValue <= maxIndex) && ((dct[indexOfMaxValue] * specificity) > threshold))
                        {
                            for (int i = 0; i < dctLength; i++)
                            {
                                hits[r + i, c] = oscilFreq;
                            }

                            for (int i = 0; i < dctLength; i++)
                            {
                                hits[r + i, c + 1] = oscilFreq; //write alternate column - MUST DO THIS BECAUSE doing alternate columns
                            }
                        }

                        r += 6; //skip rows i.e. frames of the sonogram.
                    }

                    c++; //do alternate columns
                }
            } //foreach (AcousticEvent av in events)

            return(hits);
        }
コード例 #8
0
        public static double[] DetectOscillations(double[] ipArray, double framesPerSecond, double dctDuration, double minOscilFreq, double maxOscilFreq, double dctThreshold)
        {
            int dctLength = (int)Math.Round(framesPerSecond * dctDuration);
            int minIndex  = (int)(minOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
            int maxIndex  = (int)(maxOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi

            //double midOscilFreq = minOscilFreq + ((maxOscilFreq - minOscilFreq) / 2);

            if (maxIndex > dctLength)
            {
                return(null);       //safety check
            }

            int length    = ipArray.Length;
            var dctScores = new double[length];

            //var hits = new double[length];

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients

            //following two lines write bmp image of cosine matrix values for checking.
            //string bmpPath = @"C:\SensorNetworks\Output\cosines.png";
            //ImageTools.DrawMatrix(cosines, bmpPath, true);

            for (int r = 1; r < length - dctLength; r++)
            {
                // only stop if current location is a peak
                if (ipArray[r] < ipArray[r - 1] || ipArray[r] < ipArray[r + 1])
                {
                    continue;
                }

                // extract array and ready for DCT
                //for (int i = 0; i < dctLength; i++) dctArray[i] = ipArray[r + i];
                var dctArray = DataTools.Subarray(ipArray, r, dctLength);

                dctArray = DataTools.SubtractMean(dctArray);

                //dctArray = DataTools.Vector2Zscores(dctArray);

                double[] dctCoeff = MFCCStuff.DCT(dctArray, cosines);

                // convert to absolute values because not interested in negative values due to phase.
                for (int i = 0; i < dctLength; i++)
                {
                    dctCoeff[i] = Math.Abs(dctCoeff[i]);
                }

                // remove low freq oscillations from consideration
                int thresholdIndex = minIndex / 4;
                for (int i = 0; i < thresholdIndex; i++)
                {
                    dctCoeff[i] = 0.0;
                }

                dctCoeff = DataTools.normalise2UnitLength(dctCoeff);

                //dct = DataTools.NormaliseMatrixValues(dct); //another option to NormaliseMatrixValues
                int indexOfMaxValue = DataTools.GetMaxIndex(dctCoeff);

                //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

                // #### Tried this option for scoring oscillation hits but did not work well.
                // #### Requires very fine tuning of thresholds
                //dctCoeff = DataTools.Normalise2Probabilites(dctCoeff);
                //// sum area under curve where looking for oscillations
                //double sum = 0.0;
                //for (int i = minIndex; i <= maxIndex; i++)
                //    sum += dctCoeff[i];
                //if (sum > dctThreshold)
                //{
                //    for (int i = 0; i < dctLength; i++) hits[r + i, c] = midOscilFreq;
                //}

                // DEBUGGING
                // DataTools.MinMax(dctCoeff, out min, out max);
                //DataTools.writeBarGraph(dctArray);
                //DataTools.writeBarGraph(dctCoeff);

                //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
                if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dctCoeff[indexOfMaxValue] > dctThreshold)
                {
                    //for (int i = 0; i < dctLength; i++) dctScores[r + i] = midOscilFreq;
                    for (int i = 0; i < dctLength; i++)
                    {
                        if (dctScores[r + i] < dctCoeff[indexOfMaxValue])
                        {
                            dctScores[r + i] = dctCoeff[indexOfMaxValue];
                        }
                    }
                }
            }

            //return hits; //dctArray
            return(dctScores);
        }
コード例 #9
0
        /// <summary>
        /// Detects oscillations in a given freq bin.
        /// there are several important parameters for tuning.
        /// a) DCTLength: Good values are 0.25 to 0.50 sec. Do not want too long because DCT requires stationarity.
        ///     Do not want too short because too small a range of oscillations
        /// b) DCTindex: Sets lower bound for oscillations of interest. Index refers to array of coeff returned by DCT.
        ///     Array has same length as the length of the DCT. Low freq oscillations occur more often by chance. Want to exclude them.
        /// c) MinAmplitude: minimum acceptable value of a DCT coefficient if hit is to be accepted.
        ///     The algorithm is sensitive to this value. A lower value results in more oscillation hits being returned.
        /// </summary>
        /// <param name="sonogram"></param>
        /// <param name="minHz">min freq bin of search band</param>
        /// <param name="maxHz">max freq bin of search band</param>
        /// <param name="dctDuration">number of values</param>
        /// <param name="maxOscilFreq"></param>
        /// <param name="dctThreshold">threshold - do not accept a DCT coefficient if its value is less than this threshold</param>
        /// <param name="minOscilFreq"></param>
        /// <returns></returns>
        public static double[,] DetectOscillations(SpectrogramStandard sonogram, int minHz, int maxHz,
                                                   double dctDuration, int minOscilFreq, int maxOscilFreq, double dctThreshold)
        {
            int minBin = (int)(minHz / sonogram.FBinWidth);
            int maxBin = (int)(maxHz / sonogram.FBinWidth);

            int dctLength = (int)Math.Round(sonogram.FramesPerSecond * dctDuration);
            int minIndex  = (int)(minOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi
            int maxIndex  = (int)(maxOscilFreq * dctDuration * 2); //multiply by 2 because index = Pi and not 2Pi

            int midOscilFreq = minOscilFreq + ((maxOscilFreq - minOscilFreq) / 2);

            if (maxIndex > dctLength)
            {
                return(null);       //safety check
            }

            int rows = sonogram.Data.GetLength(0);
            int cols = sonogram.Data.GetLength(1);

            double[,] hits   = new double[rows, cols];
            double[,] matrix = sonogram.Data;

            double[,] cosines = MFCCStuff.Cosines(dctLength, dctLength); //set up the cosine coefficients

            //following two lines write matrix of cos values for checking.
            //string txtPath = @"C:\SensorNetworks\Output\cosines.txt";
            //FileTools.WriteMatrix2File_Formatted(cosines, txtPath, "F3");

            //following two lines write bmp image of cos values for checking.
            //string bmpPath = @"C:\SensorNetworks\Output\cosines.png";
            //ImageTools.DrawMatrix(cosines, bmpPath, true);

            for (int c = minBin; c <= maxBin; c++) //traverse columns - skip DC column
            {
                var dctArray = new double[dctLength];

                for (int r = 0; r < rows - dctLength; r++)
                {
                    // extract array and ready for DCT
                    for (int i = 0; i < dctLength; i++)
                    {
                        dctArray[i] = matrix[r + i, c];
                    }

                    dctArray = DataTools.SubtractMean(dctArray);

                    //dctArray = DataTools.Vector2Zscores(dctArray);

                    double[] dctCoeff = MFCCStuff.DCT(dctArray, cosines);

                    // convert to absolute values because not interested in negative values due to phase.
                    for (int i = 0; i < dctLength; i++)
                    {
                        dctCoeff[i] = Math.Abs(dctCoeff[i]);
                    }

                    // remove low freq oscillations from consideration
                    int thresholdIndex = minIndex / 4;
                    for (int i = 0; i < thresholdIndex; i++)
                    {
                        dctCoeff[i] = 0.0;
                    }

                    dctCoeff = DataTools.normalise2UnitLength(dctCoeff);

                    //dct = DataTools.NormaliseMatrixValues(dct); //another option to NormaliseMatrixValues
                    int indexOfMaxValue = DataTools.GetMaxIndex(dctCoeff);

                    //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

                    // #### Tried this option for scoring oscillation hits but did not work well.
                    // #### Requires very fine tuning of thresholds
                    //dctCoeff = DataTools.Normalise2Probabilites(dctCoeff);
                    //// sum area under curve where looking for oscillations
                    //double sum = 0.0;
                    //for (int i = minIndex; i <= maxIndex; i++)
                    //    sum += dctCoeff[i];
                    //if (sum > dctThreshold)
                    //{
                    //    for (int i = 0; i < dctLength; i++) hits[r + i, c] = midOscilFreq;
                    //}

                    // DEBUGGING
                    // DataTools.MinMax(dctCoeff, out min, out max);
                    //DataTools.writeBarGraph(dctArray);
                    //DataTools.writeBarGraph(dctCoeff);

                    //mark DCT location with oscillation freq, only if oscillation freq is in correct range and amplitude
                    if (indexOfMaxValue >= minIndex && indexOfMaxValue <= maxIndex && dctCoeff[indexOfMaxValue] > dctThreshold)
                    {
                        for (int i = 0; i < dctLength; i++)
                        {
                            hits[r + i, c] = midOscilFreq;
                        }
                    }

                    r += 5; //skip rows
                }

                c++; //do alternate columns
            }

            return(hits);
        }