Пример #1
0
        Analysis(FileInfo fiSegmentOfSourceFile, Dictionary <string, string> config)
        {
            int    minHzMale    = ConfigDictionary.GetInt(LSKiwi1.key_MIN_HZ_MALE, config);
            int    maxHzMale    = ConfigDictionary.GetInt(LSKiwi1.key_MAX_HZ_MALE, config);
            int    minHzFemale  = ConfigDictionary.GetInt(LSKiwi1.key_MIN_HZ_FEMALE, config);
            int    maxHzFemale  = ConfigDictionary.GetInt(LSKiwi1.key_MAX_HZ_FEMALE, config);
            int    frameLength  = ConfigDictionary.GetInt(LSKiwi1.key_FRAME_LENGTH, config);
            double frameOverlap = ConfigDictionary.GetDouble(LSKiwi1.key_FRAME_OVERLAP, config);
            //double dctDuration = ConfigDictionary.GetDouble(LSKiwi1.key_DCT_DURATION, config);
            //double dctThreshold = ConfigDictionary.GetDouble(LSKiwi1.key_DCT_THRESHOLD, config);
            double minPeriod      = ConfigDictionary.GetDouble(LSKiwi1.key_MIN_PERIODICITY, config);
            double maxPeriod      = ConfigDictionary.GetDouble(LSKiwi1.key_MAX_PERIODICITY, config);
            double eventThreshold = ConfigDictionary.GetDouble(Keys.EVENT_THRESHOLD, config);
            double minDuration    = ConfigDictionary.GetDouble(LSKiwi1.key_MIN_DURATION, config); //minimum event duration to qualify as species call
            double maxDuration    = ConfigDictionary.GetDouble(LSKiwi1.key_MAX_DURATION, config); //maximum event duration to qualify as species call

            AudioRecording recording = new AudioRecording(fiSegmentOfSourceFile.FullName);

            if (recording == null)
            {
                Console.WriteLine("AudioRecording == null. Analysis not possible.");
                return(null);
            }
            TimeSpan tsRecordingtDuration = recording.Duration();

            //i: MAKE SONOGRAM
            SonogramConfig sonoConfig = new SonogramConfig(); //default values config

            sonoConfig.SourceFName        = recording.FileName;
            sonoConfig.WindowSize         = frameLength;
            sonoConfig.WindowOverlap      = frameOverlap;
            sonoConfig.NoiseReductionType = NoiseReductionType.STANDARD; //MUST DO NOISE REMOVAL
            BaseSonogram sonogram = new SpectralSonogram(sonoConfig, recording.GetWavReader());

            //DETECT MALE KIWI
            var resultsMale      = DetectKiwi(sonogram, minHzMale, maxHzMale, /*dctDuration, dctThreshold,*/ minPeriod, maxPeriod, eventThreshold, minDuration, maxDuration);
            var scoresM          = resultsMale.Item1;
            var hitsM            = resultsMale.Item2;
            var predictedEventsM = resultsMale.Item3;

            foreach (AcousticEvent ev in predictedEventsM)
            {
                ev.Name = "LSK(m)";
            }
            //DETECT FEMALE KIWI
            var resultsFemale    = DetectKiwi(sonogram, minHzFemale, maxHzFemale, /* dctDuration, dctThreshold,*/ minPeriod, maxPeriod, eventThreshold, minDuration, maxDuration);
            var scoresF          = resultsFemale.Item1;
            var hitsF            = resultsFemale.Item2;
            var predictedEventsF = resultsFemale.Item3;

            foreach (AcousticEvent ev in predictedEventsF)
            {
                ev.Name = "LSK(f)";
            }

            //combine the male and female results
            hitsM = MatrixTools.AddMatrices(hitsM, hitsF);
            foreach (AcousticEvent ev in predictedEventsF)
            {
                predictedEventsM.Add(ev);
            }
            foreach (double[] array in scoresF)
            {
                scoresM.Add(array);
            }

            return(System.Tuple.Create(sonogram, hitsM, scoresM, predictedEventsM, tsRecordingtDuration));
        } //Analysis()
        /// <summary>
        /// Do your analysis. This method is called once per segment (typically one-minute segments).
        /// </summary>
        /// <param name="recording"></param>
        /// <param name="configuration"></param>
        /// <param name="segmentStartOffset"></param>
        /// <param name="getSpectralIndexes"></param>
        /// <param name="outputDirectory"></param>
        /// <param name="imageWidth"></param>
        /// <returns></returns>
        public override RecognizerResults Recognize(AudioRecording recording, dynamic configuration, TimeSpan segmentStartOffset, Lazy <IndexCalculateResult[]> getSpectralIndexes, DirectoryInfo outputDirectory, int?imageWidth)
        {
            string speciesName            = (string)configuration[AnalysisKeys.SpeciesName] ?? "<no species>";
            string abbreviatedSpeciesName = (string)configuration[AnalysisKeys.AbbreviatedSpeciesName] ?? "<no.sp>";

            int minHz = (int)configuration[AnalysisKeys.MinHz];
            int maxHz = (int)configuration[AnalysisKeys.MaxHz];

            // BETTER TO CALCULATE THIS. IGNORE USER!
            // double frameOverlap = Double.Parse(configDict[Keys.FRAME_OVERLAP]);

            // duration of DCT in seconds
            double dctDuration = (double)configuration[AnalysisKeys.DctDuration];

            // minimum acceptable value of a DCT coefficient
            double dctThreshold = (double)configuration[AnalysisKeys.DctThreshold];

            // ignore oscillations below this threshold freq
            int minOscilFreq = (int)configuration[AnalysisKeys.MinOscilFreq];

            // ignore oscillations above this threshold freq
            int maxOscilFreq = (int)configuration[AnalysisKeys.MaxOscilFreq];

            // min duration of event in seconds
            double minDuration = (double)configuration[AnalysisKeys.MinDuration];

            // max duration of event in seconds
            double maxDuration = (double)configuration[AnalysisKeys.MaxDuration];

            // min score for an acceptable event
            double eventThreshold = (double)configuration[AnalysisKeys.EventThreshold];

            if (recording.WavReader.SampleRate != 22050)
            {
                throw new InvalidOperationException("Requires a 22050Hz file");
            }

            // The default was 512 for Canetoad.
            // Set longer Framesize for calls having longer pulse periodicity.
            const int FrameSize     = 128;
            double    windowOverlap = Oscillations2012.CalculateRequiredFrameOverlap(
                recording.SampleRate,
                FrameSize,
                maxOscilFreq);
            //windowOverlap = 0.75; // previous default

            // i: MAKE SONOGRAM
            var sonoConfig = new SonogramConfig
            {
                SourceFName   = recording.BaseName,
                WindowSize    = FrameSize,
                WindowOverlap = windowOverlap,
                //NoiseReductionType = NoiseReductionType.NONE,
                NoiseReductionType      = NoiseReductionType.STANDARD,
                NoiseReductionParameter = 0.1
            };

            // sonoConfig.NoiseReductionType = SNR.Key2NoiseReductionType("STANDARD");
            TimeSpan     recordingDuration = recording.Duration();
            int          sr           = recording.SampleRate;
            double       freqBinWidth = sr / (double)sonoConfig.WindowSize;
            BaseSonogram sonogram     = new SpectrogramStandard(sonoConfig, recording.WavReader);
            int          rowCount     = sonogram.Data.GetLength(0);
            int          colCount     = sonogram.Data.GetLength(1);

            // double[,] subMatrix = MatrixTools.Submatrix(sonogram.Data, 0, minBin, (rowCount - 1), maxbin);

            // ######################################################################
            // ii: DO THE ANALYSIS AND RECOVER SCORES OR WHATEVER
            // This window is used to smooth the score array before extracting events.
            // A short window (e.g. 3) preserves sharper score edges to define events but also keeps noise.
            int scoreSmoothingWindow = 13;

            double[]             scores; // predefinition of score array
            List <AcousticEvent> acousticEvents;

            double[,] hits;
            Oscillations2012.Execute(
                (SpectrogramStandard)sonogram,
                minHz,
                maxHz,
                dctDuration,
                minOscilFreq,
                maxOscilFreq,
                dctThreshold,
                eventThreshold,
                minDuration,
                maxDuration,
                scoreSmoothingWindow,
                out scores,
                out acousticEvents,
                out hits);

            acousticEvents.ForEach(ae =>
            {
                ae.SpeciesName     = speciesName;
                ae.SegmentDuration = recordingDuration;
                ae.Name            = abbreviatedSpeciesName;
            });

            var plot  = new Plot(this.DisplayName, scores, eventThreshold);
            var plots = new List <Plot> {
                plot
            };


            this.WriteDebugImages(recording, outputDirectory, sonogram, acousticEvents, plots, hits);

            return(new RecognizerResults()
            {
                Sonogram = sonogram,
                Hits = hits,
                Plots = plots,
                Events = acousticEvents
            });
        }