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 }); }