public static void Execute(Arguments arguments) { MainEntry.WarnIfDeveloperEntryUsed(); TowseyLibrary.Log.Verbosity = 1; string date = "# DATE AND TIME: " + DateTime.Now; LoggedConsole.WriteLine("# Running acoustic event detection."); LoggedConsole.WriteLine(date); FileInfo recodingFile = arguments.Source; var recodingBaseName = recodingFile.BaseName(); DirectoryInfo outputDir = arguments.Output.Combine(EcosoundsAedIdentifier); outputDir.Create(); Log.Info("# Output folder =" + outputDir); Log.Info("# Recording file: " + recodingFile.Name); // READ PARAMETER VALUES FROM INI FILE AedConfiguration configruation = ConfigFile.Deserialize <AedConfiguration>(arguments.Config); var aedConfig = GetAedParametersFromConfigFileOrDefaults(configruation); var results = Detect(recodingFile, aedConfig, TimeSpan.Zero); // print image // save image of sonograms var outputImagePath = outputDir.CombineFile(recodingBaseName + ".Sonogram.png"); Image image = DrawSonogram(results.Item3, results.Item1); image.Save(outputImagePath.FullName, ImageFormat.Png); Log.Info("Image saved to: " + outputImagePath.FullName); // output csv var outputCsvPath = outputDir.CombineFile(recodingBaseName + ".Events.csv"); WriteEventsFileStatic(outputCsvPath, results.Item1); Log.Info("CSV file saved to: " + outputCsvPath.FullName); TowseyLibrary.Log.WriteLine("Finished"); }
public static void Execute(Arguments arguments) { MainEntry.WarnIfDeveloperEntryUsed(); if (arguments == null) { throw new NoDeveloperMethodException(); } // READ PARAMETER VALUES FROM INI FILE var config = ConfigFile.Deserialize(arguments.Config); var aedConfig = Aed.GetAedParametersFromConfigFileOrDefaults(config); var input = arguments.Source; Tuple <BaseSonogram, List <AcousticEvent> > result = Detect(input, aedConfig, Default.eprNormalisedMinScore, TimeSpan.Zero); List <AcousticEvent> eprEvents = result.Item2; eprEvents.Sort((ae1, ae2) => ae1.TimeStart.CompareTo(ae2.TimeStart)); LoggedConsole.WriteLine(); foreach (AcousticEvent ae in eprEvents) { LoggedConsole.WriteLine(ae.TimeStart + "," + ae.EventDurationSeconds + "," + ae.LowFrequencyHertz + "," + ae.HighFrequencyHertz); } LoggedConsole.WriteLine(); string outputFolder = arguments.Config.ToFileInfo().DirectoryName; string wavFilePath = input.FullName; BaseSonogram sonogram = result.Item1; string imagePath = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(wavFilePath) + ".png"); var image = Aed.DrawSonogram(sonogram, eprEvents); image.Save(imagePath); //ProcessingTypes.SaveAeCsv(eprEvents, outputFolder, wavFilePath); Log.Info("Finished"); }
public static void Execute(Arguments arguments) { MainEntry.WarnIfDeveloperEntryUsed(); string title = "# EVENT PATTERN RECOGNITION."; string date = "# DATE AND TIME: " + DateTime.Now; Log.WriteLine(title); Log.WriteLine(date); Log.Verbosity = 1; string targetName = arguments.Target; // prefix of name of created files var input = arguments.Source; string recordingFileName = input.Name; string recordingDirectory = input.DirectoryName; DirectoryInfo outputDir = arguments.Config.ToFileInfo().Directory; FileInfo targetPath = outputDir.CombineFile(targetName + "_target.txt"); FileInfo targetNoNoisePath = outputDir.CombineFile(targetName + "_targetNoNoise.txt"); FileInfo noisePath = outputDir.CombineFile(targetName + "_noise.txt"); FileInfo targetImagePath = outputDir.CombineFile(targetName + "_target.png"); FileInfo paramsPath = outputDir.CombineFile(targetName + "_params.txt"); Log.WriteIfVerbose("# Output folder =" + outputDir); //i: GET RECORDING AudioRecording recording = new AudioRecording(input.FullName); //if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); THIS METHOD CALL IS OBSOLETE int sr = recording.SampleRate; //ii: READ PARAMETER VALUES FROM INI FILE var config = new ConfigDictionary(arguments.Config); Dictionary <string, string> dict = config.GetTable(); // framing parameters //double frameOverlap = FeltTemplates_Use.FeltFrameOverlap; // default = 0.5 double frameOverlap = double.Parse(dict["FRAME_OVERLAP"]); //frequency band int minHz = int.Parse(dict["MIN_HZ"]); int maxHz = int.Parse(dict["MAX_HZ"]); // oscillation OD parameters double dctDuration = double.Parse(dict[OscillationRecogniser.key_DCT_DURATION]); // 2.0; // seconds double dctThreshold = double.Parse(dict[OscillationRecogniser.key_DCT_THRESHOLD]); // 0.5; int minOscilFreq = int.Parse(dict[OscillationRecogniser.key_MIN_OSCIL_FREQ]); // 4; int maxOscilFreq = int.Parse(dict[OscillationRecogniser.key_MAX_OSCIL_FREQ]); // 5; bool normaliseDCT = false; // iii initialize the sonogram config class. SonogramConfig sonoConfig = new SonogramConfig(); //default values config sonoConfig.SourceFName = recording.BaseName; //sonoConfig.WindowSize = windowSize; sonoConfig.WindowOverlap = frameOverlap; // iv: generate the sonogram BaseSonogram sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader); Log.WriteLine("Frames: Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f2}%, Offset={3:f1}ms, Frames/s={4:f1}", sonogram.Configuration.WindowSize, sonogram.FrameCount, sonogram.FrameDuration * 1000, sonogram.FrameStep * 1000, sonogram.FramesPerSecond, frameOverlap); int binCount = (int)(maxHz / sonogram.FBinWidth) - (int)(minHz / sonogram.FBinWidth) + 1; Log.WriteIfVerbose("Freq band: {0} Hz - {1} Hz. (Freq bin count = {2})", minHz, maxHz, binCount); // v: extract the subband energy array Log.WriteLine("# Start extracting target event."); double[] dBArray = SNR.DecibelsInSubband(sonogram.Data, minHz, maxHz, sonogram.FBinWidth); for (int i = 0; i < sonogram.FrameCount; i++) { dBArray[i] /= binCount; // get average dB energy } double Q = 0.0; double SD = 0.0; throw new NotImplementedException("Mike changed the API here, I don't know how to fix it."); dBArray = new[] { 0.0 }; // SNR.NoiseSubtractMode(dBArray, out Q, out SD); double maxDB = 6.0; double dBThreshold = 2 * SD / maxDB; //set dB threshold to 2xSD above background noise dBArray = SNR.NormaliseDecibelArray_ZeroOne(dBArray, maxDB); dBArray = DataTools.filterMovingAverage(dBArray, 7); //Log.WriteLine("Q ={0}", Q); //Log.WriteLine("SD={0}", SD); //Log.WriteLine("Th={0}", dBThreshold); //normalised threshhold // ############################################################################################################################################# // vi: look for oscillation at required OR for ground parrots. double[] odScores = Oscillations2010.DetectOscillationsInScoreArray(dBArray, dctDuration, sonogram.FramesPerSecond, dctThreshold, normaliseDCT, minOscilFreq, maxOscilFreq); //odScores = SNR.NoiseSubtractMode(odScores, out Q, out SD); double maxOD = 1.0; odScores = SNR.NormaliseDecibelArray_ZeroOne(odScores, maxOD); odScores = DataTools.filterMovingAverage(odScores, 5); //odScores = DataTools.NormaliseMatrixValues(odScores); //NormaliseMatrixValues 0 - 1 //double odThreshold = (10 * SD) / maxOD; //set od threshold to 2xSD above background noise //double odThreshold = dctThreshold; double odThreshold = 0.4; Log.WriteLine("Max={0}", odScores.Max()); //Log.WriteLine("Q ={0}", Q); //Log.WriteLine("SD ={0}", SD); Log.WriteLine("Th ={0}", dctThreshold); //normalised threshhold // ############################################################################################################################################# // vii: LOOK FOR GROUND PARROTS USING TEMPLATE var template = GroundParrotRecogniser.ReadGroundParrotTemplateAsList(sonogram); double[] gpScores = DetectEPR(template, sonogram, odScores, odThreshold); gpScores = DataTools.normalise(gpScores); //NormaliseMatrixValues 0 - 1 // ############################################################################################################################################# // iv: SAVE extracted event as matrix of dB intensity values //FileTools.WriteMatrix2File(template, targetPath); // write template values to file PRIOR to noise removal. //FileTools.WriteMatrix2File(templateMinusNoise, targetNoNoisePath); // write template values to file AFTER to noise removal. //FileTools.WriteArray2File(noiseSubband, noisePath); // v: SAVE image of extracted event in the original sonogram string sonogramImagePath = outputDir + Path.GetFileNameWithoutExtension(recordingFileName) + ".png"; //DrawSonogram(sonogram, sonogramImagePath, dBArray, dBThreshold / maxDB, odScores, dctThreshold, gpScores, template); }
private int Execute(Arguments arguments) { var errors = new List <string>(); var warnings = new List <string>(); Log.Info("Checking required executables and libraries can be found and loaded"); // this is an important call used in analyze long recordings. // This call effectively check is we can load types and if files are present (I think) try { AnalysisCoordinator.GetAnalyzers <IAnalyser2>(typeof(MainEntry).Assembly); } catch (ReflectionTypeLoadException rtlex) { errors.Add(ExceptionLookup.FormatReflectionTypeLoadException(rtlex, true)); } // master audio utility checks for available executables try { var utility = new MasterAudioUtility(); } catch (Exception ex) { errors.Add(ex.Message); } if (AppConfigHelper.WvunpackExe == null) { warnings.Add("Cannot find wvunpack - we'll be unable to process any wavpack files."); } if (!new SoxAudioUtility(new FileInfo(AppConfigHelper.SoxExe)).SupportsMp3) { warnings.Add(SoxAudioUtility.Mp3NotSupportedOnOSX); } if (MainEntry.CheckForDataAnnotations() is string message) { errors.Add(message); } Type type = Type.GetType("Mono.Runtime"); if (type != null) { errors.Add($"We no longer use Mono with ${Meta.Name}. DO NOT prefix the {Meta.Name} prefix with `mono`."); } foreach (var warning in warnings) { Log.Warn(warning); } // don't have much more to check at the current time if (errors.Count == 0) { Log.Success("Valid environment"); return(ExceptionLookup.Ok); } else { foreach (var error in errors) { Log.Error(error); } // not using exception lookup on purpose - it's static constructor loads more types return(ExceptionLookup.UnhandledExceptionErrorCode); } }
public static void Execute(Arguments arguments) { MainEntry.WarnIfDevleoperEntryUsed(); string date = "# DATE AND TIME: " + DateTime.Now; Log.WriteLine("# SEGMENTING A RECORDING"); Log.WriteLine(date); Log.Verbosity = 1; FileInfo recordingPath = arguments.Source; FileInfo iniPath = arguments.Config.ToFileInfo(); DirectoryInfo outputDir = arguments.Output; string opFName = "segment-output.txt"; FileInfo opPath = outputDir.CombineFile(opFName); Log.WriteIfVerbose("# Output folder =" + outputDir); //READ PARAMETER VALUES FROM INI FILE var config = new ConfigDictionary(iniPath); Dictionary <string, string> dict = config.GetTable(); Dictionary <string, string> .KeyCollection keys = dict.Keys; int minHz = int.Parse(dict[key_MIN_HZ]); int maxHz = int.Parse(dict[key_MAX_HZ]); double frameOverlap = double.Parse(dict[key_FRAME_OVERLAP]); double smoothWindow = double.Parse(dict[key_SMOOTH_WINDOW]); //smoothing window (seconds) before segmentation double thresholdSD = double.Parse(dict[key_THRESHOLD]); //segmentation threshold in noise SD double minDuration = double.Parse(dict[key_MIN_DURATION]); //min duration of segment & width of smoothing window in seconds double maxDuration = double.Parse(dict[key_MAX_DURATION]); //max duration of segment in seconds int DRAW_SONOGRAMS = int.Parse(dict[key_DRAW_SONOGRAMS]); //options to draw sonogram Log.WriteIfVerbose("# Freq band: {0} Hz - {1} Hz.)", minHz, maxHz); Log.WriteIfVerbose("# Smoothing Window: {0}s.", smoothWindow); Log.WriteIfVerbose("# Duration bounds: " + minDuration + " - " + maxDuration + " seconds"); //############################################################################################################################################# var results = Execute_Segmentation(recordingPath, minHz, maxHz, frameOverlap, smoothWindow, thresholdSD, minDuration, maxDuration); Log.WriteLine("# Finished detecting segments."); //############################################################################################################################################# var sonogram = results.Item1; var predictedEvents = results.Item2; //contain the segments detected var Q = results.Item3; var oneSD_dB = results.Item4; var dBThreshold = results.Item5; var intensity = results.Item6; Log.WriteLine("# Signal: Duration={0}, Sample Rate={1}", sonogram.Duration, sonogram.SampleRate); Log.WriteLine("# Frames: Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f0}%, Offset={3:f1}ms, Frames/s={4:f1}", sonogram.Configuration.WindowSize, sonogram.FrameCount, sonogram.FrameDuration * 1000, sonogram.FrameStep * 1000, sonogram.FramesPerSecond, frameOverlap); int binCount = (int)(maxHz / sonogram.FBinWidth) - (int)(minHz / sonogram.FBinWidth) + 1; Log.WriteLine("# FreqBand: {0} Hz - {1} Hz. (Freq bin count = {2})", minHz, maxHz, binCount); Log.WriteLine("# Intensity array - noise removal: Q={0:f1}dB. 1SD={1:f3}dB. Threshold={2:f3}dB.", Q, oneSD_dB, dBThreshold); Log.WriteLine("# Events: Count={0}", predictedEvents.Count()); int pcHIF = 100; if (intensity != null) { int hifCount = intensity.Count(p => p > dBThreshold); //count of high intensity frames pcHIF = 100 * hifCount / sonogram.FrameCount; } //write event count to results file. double sigDuration = sonogram.Duration.TotalSeconds; string fname = recordingPath.Name; int count = predictedEvents.Count; //string str = String.Format("#RecordingName\tDuration(sec)\t#Ev\tCompT(ms)\t%hiFrames\n{0}\t{1}\t{2}\t{3}\t{4}\n", fname, sigDuration, count, analysisDuration.TotalMilliseconds, pcHIF); //StringBuilder sb = new StringBuilder(str); //StringBuilder sb = new StringBuilder(); string str = string.Format("{0}\t{1}\t{2}\t{3}", fname, sigDuration, count, pcHIF); StringBuilder sb = AcousticEvent.WriteEvents(predictedEvents, str); FileTools.WriteTextFile(opPath.FullName, sb.ToString()); //draw images of sonograms string imagePath = outputDir + Path.GetFileNameWithoutExtension(recordingPath.Name) + ".png"; double min, max; DataTools.MinMax(intensity, out min, out max); double threshold_norm = dBThreshold / max; //min = 0.0; intensity = DataTools.normalise(intensity); if (DRAW_SONOGRAMS == 2) { DrawSonogram(sonogram, imagePath, predictedEvents, threshold_norm, intensity); } else if (DRAW_SONOGRAMS == 1 && predictedEvents.Count > 0) { DrawSonogram(sonogram, imagePath, predictedEvents, threshold_norm, intensity); } Log.WriteLine("# Finished recording:- " + recordingPath.Name); }
private int Execute(Arguments arguments) { var errors = new List <string>(); Log.Info("Checking required executables and libraries can be found and loaded"); // this is an important call used in analyze long recordings. // This call effectively check is we can load types and if files are present (I think) try { AnalysisCoordinator.GetAnalyzers <IAnalyser2>(typeof(MainEntry).Assembly); } catch (ReflectionTypeLoadException rtlex) { errors.Add(ExceptionLookup.FormatReflectionTypeLoadException(rtlex, true)); } // master audio utility checks for available executables try { var utility = new MasterAudioUtility(); } catch (Exception ex) { errors.Add(ex.Message); } if (MainEntry.CheckForDataAnnotations() is string message) { errors.Add(message); } if (AppConfigHelper.IsMono) { Type type = Type.GetType("Mono.Runtime"); if (type != null) { MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); if (displayName?.Invoke(null, null) is string name) { var version = Regex.Match(name, @".*(\d+\.\d+\.\d+\.\d+).*").Groups[1].Value; Console.WriteLine(version); if (new Version(version) > new Version(5, 5)) { Log.Success($"Your mono version {name} is greater than our required Mono version 5.5"); } else { errors.Add($"Mono version is {name}, we require at least Mono 5.5"); } } else { errors.Add("Could not get Mono display name"); } } } // don't have much more to check at the current time if (errors.Count == 0) { Log.Success("Valid environment"); return(ExceptionLookup.Ok); } else { foreach (var error in errors) { Log.Error(error); } // not using exception lookup on purpose - it's static constructor loads more types return(ExceptionLookup.UnhandledExceptionErrorCode); } }