public static void ConvertEventsToIndices( IAnalyser2 analyser, EventBase[] events, ref SummaryIndexBase[] indices, TimeSpan durationOfTheOriginalAudioFile, double scoreThreshold) { if (events == null && indices == null) { Log.Warn("No events or summary indices were produced, events cannot be made into indices"); } else if (events == null && indices != null) { // no-op, no events to convert, but indices already calculated Log.Debug("No events received, indices already given, no further action"); } else if (events != null && indices == null) { Log.InfoFormat("Converting Events to {0} minute Indices", IndexUnitTime.TotalMinutes); indices = analyser.ConvertEventsToSummaryIndices( events, IndexUnitTime, durationOfTheOriginalAudioFile, scoreThreshold); } else if (events != null && indices != null) { // no-op both values already present, just ensure they match Log.Info("Both events and indices already given, no event conversion done"); } }
/// <summary> /// A WRAPPER AROUND THE analyser.Analyze(analysisSettings) METHOD /// To be called as an executable with command line arguments. /// </summary> public static void Execute(Arguments arguments) { Contract.Requires(arguments != null); var(analysisSettings, segmentSettings) = arguments.ToAnalysisSettings(); TimeSpan offsetStart = TimeSpan.FromSeconds(arguments.Start ?? 0); TimeSpan duration = TimeSpan.FromSeconds(arguments.Duration ?? 0); int resampleRate = ConfigDictionary.GetInt(AnalysisKeys.ResampleRate, analysisSettings.ConfigDict); // EXTRACT THE REQUIRED RECORDING SEGMENT FileInfo tempF = segmentSettings.SegmentAudioFile; if (tempF.Exists) { tempF.Delete(); } if (duration == TimeSpan.Zero) { // Process entire file AudioFilePreparer.PrepareFile(arguments.Source, tempF, new AudioUtilityRequest { TargetSampleRate = resampleRate }, analysisSettings.AnalysisTempDirectoryFallback); ////var fiSegment = AudioFilePreparer.PrepareFile(diOutputDir, fiSourceFile, , Human2.RESAMPLE_RATE); } else { AudioFilePreparer.PrepareFile(arguments.Source, tempF, new AudioUtilityRequest { TargetSampleRate = resampleRate, OffsetStart = offsetStart, OffsetEnd = offsetStart.Add(duration) }, analysisSettings.AnalysisTempDirectoryFallback); ////var fiSegmentOfSourceFile = AudioFilePreparer.PrepareFile(diOutputDir, new FileInfo(recordingPath), MediaTypes.MediaTypeWav, TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(3), RESAMPLE_RATE); } //DO THE ANALYSIS // ############################################################################################################################################# // BROKEN! throw new NotImplementedException("Broken in code updates"); IAnalyser2 analyser = null; //new Rain_OBSOLETE(); AnalysisResult2 result = analyser.Analyze <FileInfo>(analysisSettings, null /*broken */); /*DataTable dt = result.Data; * //############################################################################################################################################# * * // ADD IN ADDITIONAL INFO TO RESULTS TABLE * if (dt != null) * { * int iter = 0; // dummy - iteration number would ordinarily be available at this point. * int startMinute = (int)offsetStart.TotalMinutes; * foreach (DataRow row in dt.Rows) * { * row[InitialiseIndexProperties.KEYRankOrder] = iter; * row[InitialiseIndexProperties.KEYStartMinute] = startMinute; * row[InitialiseIndexProperties.KEYSegmentDuration] = result.AudioDuration.TotalSeconds; * } * * CsvTools.DataTable2CSV(dt, segmentSettings.SegmentSummaryIndicesFile.FullName); * //DataTableTools.WriteTable2Console(dt); * }*/ }
/// <summary> /// Gets a named output directory. For example, if <paramref name="baseDir"/> is "C:\Temp" and /// <paramref name="analyzer"/> is the indices analysis, the result will be "C:\Temp\Towsey.Acoustic". /// </summary> /// <param name="baseDir">The base output directory (either normal output or a temp directory).</param> /// <param name="analyzer">The <see cref="IAnalyser2"/> to extract the identifier from.</param> /// <param name="subFolders">An optional list of sub folders to append to the path.</param> /// <returns>A combined directory made up of all the path fragments.</returns> public static DirectoryInfo GetNamedDirectory( DirectoryInfo baseDir, IAnalyser2 analyzer, params string[] subFolders) { Contract.Requires(analyzer.NotNull(), "analyzer must be not null"); Contract.Requires(!string.IsNullOrWhiteSpace(analyzer.Identifier), "analysisIdentifier must be set."); return(baseDir.Combine(subFolders.Prepend(analyzer.Identifier))); }
public static DirectoryInfo SaveSpectralIndices(IAnalyser2 analyser2, string fileName, DirectoryInfo outputDirectory, IEnumerable <SpectralIndexBase> spectra) { if (spectra == null) { Log.Debug("No spectral indices returned... file not written"); return(null); } analyser2.WriteSpectrumIndicesFiles(outputDirectory, fileName, spectra); return(outputDirectory); }
/// <summary> /// 2. Analyses long audio recording (mp3 or wav) as per passed config file. Outputs an events.csv file AND an /// indices.csv file /// Signed off: Michael Towsey 4th December 2012 /// </summary> public static void Execute(Arguments arguments) { if (arguments == null) { throw new NoDeveloperMethodException(); } LoggedConsole.WriteLine("# PROCESS LONG RECORDING"); LoggedConsole.WriteLine("# DATE AND TIME: " + DateTime.Now); // 1. set up the necessary files var sourceAudio = arguments.Source; var configFile = arguments.Config.ToFileInfo(); var outputDirectory = arguments.Output; var tempFilesDirectory = arguments.TempDir; // if a temp dir is not given, use output dir as temp dir if (tempFilesDirectory == null) { Log.Warn("No temporary directory provided, using output directory"); tempFilesDirectory = outputDirectory; } // try an automatically find the config file if (configFile == null) { throw new FileNotFoundException("No config file argument provided"); } else if (!configFile.Exists) { Log.Warn($"Config file {configFile.FullName} not found... attempting to resolve config file"); // we use .ToString() here to get the original input string - Using fullname always produces an absolute path wrt to pwd... we don't want to prematurely make asusmptions: // e.g. We require a missing absolute path to fail... that wouldn't work with .Name // e.g. We require a relative path to try and resolve, using .FullName would fail the first absolute check inside ResolveConfigFile configFile = ConfigFile.Resolve(configFile.ToString(), Directory.GetCurrentDirectory().ToDirectoryInfo()); } if (arguments.StartOffset.HasValue ^ arguments.EndOffset.HasValue) { throw new InvalidStartOrEndException("If StartOffset or EndOffset is specified, then both must be specified"); } if (arguments.StartOffset.HasValue && arguments.EndOffset.HasValue && arguments.EndOffset.Value <= arguments.StartOffset.Value) { throw new InvalidStartOrEndException("Start offset must be less than end offset."); } LoggedConsole.WriteLine("# Recording file: " + sourceAudio.FullName); LoggedConsole.WriteLine("# Configuration file: " + configFile); LoggedConsole.WriteLine("# Output folder: " + outputDirectory); LoggedConsole.WriteLine("# Temp File Directory: " + tempFilesDirectory); // optionally copy logs / config to make results easier to understand // TODO: remove, see https://github.com/QutEcoacoustics/audio-analysis/issues/133 if (arguments.WhenExitCopyConfig || arguments.WhenExitCopyLog) { AppDomain.CurrentDomain.ProcessExit += (sender, args) => { Cleanup(arguments, configFile); }; } // 2. initialize the analyzer // we're changing the way resolving config files works. Ideally, we'd like to use statically typed config files // but we can't do that unless we know which type we have to load first! Currently analyzer to load is in // the config file so we can't know which analyzer we can use. Thus we will change to using the file name, // or an argument to resolve the analyzer to load. // Get analysis name: IAnalyser2 analyzer = FindAndCheckAnalyzer <IAnalyser2>(arguments.AnalysisIdentifier, configFile.Name); // 2. get the analysis config AnalyzerConfig configuration = analyzer.ParseConfig(configFile); SaveBehavior saveIntermediateWavFiles = configuration.SaveIntermediateWavFiles; bool saveIntermediateDataFiles = configuration.SaveIntermediateCsvFiles; SaveBehavior saveSonogramsImages = configuration.SaveSonogramImages; bool filenameDate = configuration.RequireDateInFilename; if (configuration[AnalysisKeys.AnalysisName].IsNotWhitespace()) { Log.Warn("Your config file has `AnalysisName` set - this property is deprecated and ignored"); } // AT 2018-02: changed logic so default index properties loaded if not provided FileInfo indicesPropertiesConfig = IndexProperties.Find(configuration, configFile); if (indicesPropertiesConfig == null || !indicesPropertiesConfig.Exists) { Log.Warn("IndexProperties config can not be found! Loading a default"); indicesPropertiesConfig = ConfigFile.Default <Dictionary <string, IndexProperties> >(); } LoggedConsole.WriteLine("# IndexProperties Cfg: " + indicesPropertiesConfig.FullName); // min score for an acceptable event Log.Info("Minimum event threshold has been set to " + configuration.EventThreshold); FileSegment.FileDateBehavior defaultBehavior = FileSegment.FileDateBehavior.Try; if (filenameDate) { if (!FileDateHelpers.FileNameContainsDateTime(sourceAudio.Name)) { throw new InvalidFileDateException( "When RequireDateInFilename option is set, the filename of the source audio file must contain " + "a valid AND UNAMBIGUOUS date. Such a date was not able to be parsed."); } defaultBehavior = FileSegment.FileDateBehavior.Required; } // 3. initilize AnalysisCoordinator class that will do the analysis var analysisCoordinator = new AnalysisCoordinator( new LocalSourcePreparer(), saveIntermediateWavFiles, false, arguments.Parallel); // 4. get the segment of audio to be analysed // if tiling output, specify that FileSegment needs to be able to read the date var fileSegment = new FileSegment(sourceAudio, arguments.AlignToMinute, null, defaultBehavior); var bothOffsetsProvided = arguments.StartOffset.HasValue && arguments.EndOffset.HasValue; if (bothOffsetsProvided) { fileSegment.SegmentStartOffset = TimeSpan.FromSeconds(arguments.StartOffset.Value); fileSegment.SegmentEndOffset = TimeSpan.FromSeconds(arguments.EndOffset.Value); } else { Log.Debug("Neither start nor end segment offsets provided. Therefore both were ignored."); } // 6. initialize the analysis settings object var analysisSettings = analyzer.DefaultSettings; analysisSettings.ConfigFile = configFile; analysisSettings.Configuration = configuration; analysisSettings.AnalysisOutputDirectory = outputDirectory; analysisSettings.AnalysisTempDirectory = tempFilesDirectory; analysisSettings.AnalysisDataSaveBehavior = saveIntermediateDataFiles; analysisSettings.AnalysisImageSaveBehavior = saveSonogramsImages; analysisSettings.AnalysisChannelSelection = arguments.Channels; analysisSettings.AnalysisMixDownToMono = arguments.MixDownToMono; var segmentDuration = configuration.SegmentDuration?.Seconds(); if (!segmentDuration.HasValue) { segmentDuration = analysisSettings.AnalysisMaxSegmentDuration ?? TimeSpan.FromMinutes(1); Log.Warn( $"Can't read `{nameof(AnalyzerConfig.SegmentDuration)}` from config file. " + $"Default value of {segmentDuration} used)"); } analysisSettings.AnalysisMaxSegmentDuration = segmentDuration.Value; var segmentOverlap = configuration.SegmentOverlap?.Seconds(); if (!segmentOverlap.HasValue) { segmentOverlap = analysisSettings.SegmentOverlapDuration; Log.Warn( $"Can't read `{nameof(AnalyzerConfig.SegmentOverlap)}` from config file. " + $"Default value of {segmentOverlap} used)"); } analysisSettings.SegmentOverlapDuration = segmentOverlap.Value; // set target sample rate var resampleRate = configuration.ResampleRate; if (!resampleRate.HasValue) { resampleRate = analysisSettings.AnalysisTargetSampleRate ?? AppConfigHelper.DefaultTargetSampleRate; Log.Warn( $"Can't read {nameof(configuration.ResampleRate)} from config file. " + $"Default value of {resampleRate} used)"); } analysisSettings.AnalysisTargetSampleRate = resampleRate; Log.Info( $"{nameof(configuration.SegmentDuration)}={segmentDuration}, " + $"{nameof(configuration.SegmentOverlap)}={segmentOverlap}, " + $"{nameof(configuration.ResampleRate)}={resampleRate}"); // 7. ####################################### DO THE ANALYSIS ################################### LoggedConsole.WriteLine("START ANALYSIS ..."); var analyserResults = analysisCoordinator.Run(fileSegment, analyzer, analysisSettings); // ############################################################################################## // 8. PROCESS THE RESULTS LoggedConsole.WriteLine(string.Empty); LoggedConsole.WriteLine("START PROCESSING RESULTS ..."); if (analyserResults == null) { LoggedConsole.WriteErrorLine("###################################################\n"); LoggedConsole.WriteErrorLine("The Analysis Run Coordinator has returned a null result."); LoggedConsole.WriteErrorLine("###################################################\n"); throw new AnalysisOptionDevilException(); } // Merge and correct main result types EventBase[] mergedEventResults = ResultsTools.MergeResults(analyserResults, ar => ar.Events, ResultsTools.CorrectEvent); SummaryIndexBase[] mergedIndicesResults = ResultsTools.MergeResults(analyserResults, ar => ar.SummaryIndices, ResultsTools.CorrectSummaryIndex); SpectralIndexBase[] mergedSpectralIndexResults = ResultsTools.MergeResults(analyserResults, ar => ar.SpectralIndices, ResultsTools.CorrectSpectrumIndex); // not an exceptional state, do not throw exception if (mergedEventResults != null && mergedEventResults.Length == 0) { LoggedConsole.WriteWarnLine("The analysis produced no EVENTS (mergedResults had zero count)"); } if (mergedIndicesResults != null && mergedIndicesResults.Length == 0) { LoggedConsole.WriteWarnLine("The analysis produced no Summary INDICES (mergedResults had zero count)"); } if (mergedSpectralIndexResults != null && mergedSpectralIndexResults.Length == 0) { LoggedConsole.WriteWarnLine("The analysis produced no Spectral INDICES (merged results had zero count)"); } // 9. CREATE SUMMARY INDICES IF NECESSARY (FROM EVENTS) #if DEBUG // get the duration of the original source audio file - need this to convert Events datatable to Indices Datatable var audioUtility = new MasterAudioUtility(tempFilesDirectory); var mimeType = MediaTypes.GetMediaType(sourceAudio.Extension); var sourceInfo = audioUtility.Info(sourceAudio); // updated by reference all the way down in LocalSourcePreparer Debug.Assert(fileSegment.TargetFileDuration == sourceInfo.Duration); #endif var duration = fileSegment.TargetFileDuration.Value; ResultsTools.ConvertEventsToIndices( analyzer, mergedEventResults, ref mergedIndicesResults, duration, configuration.EventThreshold); int eventsCount = mergedEventResults?.Length ?? 0; int numberOfRowsOfIndices = mergedIndicesResults?.Length ?? 0; // 10. Allow analysers to post-process // TODO: remove results directory if possible var instanceOutputDirectory = AnalysisCoordinator.GetNamedDirectory(analysisSettings.AnalysisOutputDirectory, analyzer); // 11. IMPORTANT - this is where IAnalyser2's post processor gets called. // Produces all spectrograms and images of SPECTRAL INDICES. // Long duration spectrograms are drawn IFF analysis type is Towsey.Acoustic analyzer.SummariseResults(analysisSettings, fileSegment, mergedEventResults, mergedIndicesResults, mergedSpectralIndexResults, analyserResults); // 12. SAVE THE RESULTS string fileNameBase = Path.GetFileNameWithoutExtension(sourceAudio.Name); var eventsFile = ResultsTools.SaveEvents(analyzer, fileNameBase, instanceOutputDirectory, mergedEventResults); var indicesFile = ResultsTools.SaveSummaryIndices(analyzer, fileNameBase, instanceOutputDirectory, mergedIndicesResults); var spectraFile = ResultsTools.SaveSpectralIndices(analyzer, fileNameBase, instanceOutputDirectory, mergedSpectralIndexResults); // 13. THIS IS WHERE SUMMARY INDICES ARE PROCESSED // Convert summary indices to black and white tracks image if (mergedIndicesResults == null) { Log.Info("No summary indices produced"); } else { if (indicesPropertiesConfig == null || !indicesPropertiesConfig.Exists) { throw new InvalidOperationException("Cannot process indices without an index configuration file, the file could not be found!"); } // this arbitrary amount of data. if (mergedIndicesResults.Length > 5000) { Log.Warn("Summary Indices Image not able to be drawn - there are too many indices to render"); } else { var basename = Path.GetFileNameWithoutExtension(fileNameBase); string imageTitle = $"SOURCE:{basename}, {Meta.OrganizationTag}; "; // Draw Tracks-Image of Summary indices // set time scale resolution for drawing of summary index tracks TimeSpan timeScale = TimeSpan.FromSeconds(0.1); Bitmap tracksImage = IndexDisplay.DrawImageOfSummaryIndices( IndexProperties.GetIndexProperties(indicesPropertiesConfig), indicesFile, imageTitle, timeScale, fileSegment.TargetFileStartDate); var imagePath = FilenameHelpers.AnalysisResultPath(instanceOutputDirectory, basename, "SummaryIndices", ImageFileExt); tracksImage.Save(imagePath); } } // 14. wrap up, write stats LoggedConsole.WriteLine("INDICES CSV file(s) = " + (indicesFile?.Name ?? "<<No indices result, no file!>>")); LoggedConsole.WriteLine("\tNumber of rows (i.e. minutes) in CSV file of indices = " + numberOfRowsOfIndices); LoggedConsole.WriteLine(string.Empty); if (eventsFile == null) { LoggedConsole.WriteLine("An Events CSV file was NOT returned."); } else { LoggedConsole.WriteLine("EVENTS CSV file(s) = " + eventsFile.Name); LoggedConsole.WriteLine("\tNumber of events = " + eventsCount); } Log.Success($"Analysis Complete.\nSource={sourceAudio.Name}\nOutput={instanceOutputDirectory.FullName}"); }
/// <summary> /// Analyze one or more file segments using the same analysis and settings. /// Note each segment could be sourced from separate original audio files! /// If using a remote source preparer the segments could even be downloaded from a remote source!. /// </summary> /// <param name="segments"> /// The file Segments. /// </param> /// <param name="analysis"> /// The analysis. /// </param> /// <param name="settings"> /// The settings. /// </param> /// <returns> /// The analysis results. /// </returns> public AnalysisResult2[] Run <TSource>( ISegment <TSource>[] segments, IAnalyser2 analysis, AnalysisSettings settings) { Contract.Requires(settings != null, "Settings must not be null."); Contract.Requires(analysis != null, "Analysis must not be null."); Contract.Requires(segments != null, "File Segments must not be null."); // do not allow the program to continue // if there are no possible segments to process because the original file // is too short. var tooShort = segments .FirstOrDefault(segment => segment.SourceMetadata.Duration < settings.AnalysisMinSegmentDuration); if (tooShort != null) { Log.Fatal("Provided audio recording is too short too analyze!"); throw new AudioRecordingTooShortException( "{0} is too short to analyze with current analysisSettings.AnalysisMinSegmentDuration ({1})" .Format2(tooShort.Source, settings.AnalysisMinSegmentDuration)); } // ensure output directory exists Contract.Requires( settings.AnalysisOutputDirectory.TryCreate(), $"Attempt to create AnalysisOutputDirectory failed: {settings.AnalysisOutputDirectory}"); // try and create temp directory (returns true if already exists) if (!settings.IsAnalysisTempDirectoryValid) { // ensure a temp directory is always set Log.Warn( "No temporary directory provided, using random directory: " + settings.AnalysisTempDirectoryFallback); } // calculate the sub-segments of the given file segments that match what the analysis expects. var analysisSegments = PrepareAnalysisSegments(this.SourcePreparer, segments, settings); // Execute a pre analyzer hook Log.Info("Executing BeforeAnalyze"); analysis.BeforeAnalyze(settings); Log.Debug("Completed BeforeAnalyze"); AnalysisResult2[] results; // clone analysis settings for parallelism concerns: // - as each iteration modifies settings. This causes hard to track down bugs // clones are made for sequential runs to to ensure consistency var settingsForThisItem = (AnalysisSettings)settings.Clone(); Log.Info($"Analysis started in {(this.IsParallel ? "parallel" : "sequence")}."); var stopwatch = new Stopwatch(); stopwatch.Start(); // Analyze the sub-segments in parallel or sequentially (IsParallel property), // Create and delete directories and/or files as indicated by properties // DeleteFinished and UniqueDirectoryPerSegment if (this.IsParallel) { results = this.RunParallel(analysisSegments, analysis, settingsForThisItem); Array.Sort(results); } else { // sequential results = this.RunSequential(analysisSegments, analysis, settingsForThisItem); } stopwatch.Stop(); Log.Info($"Analysis complete, took {stopwatch.Elapsed}."); // TODO: execute SummariseResults hook here eventually // delete temp directories // only delete directory if we are using one that was created specifically for this analysis settings.AnalysisTempDirectoryFallback.TryDelete(true, $"Item {settings.InstanceId}"); return(results); }
/// <summary> /// Analyze one file segment using the analysis and settings. /// </summary> /// <param name="segment"> /// The file Segment. /// </param> /// <param name="analysis"> /// The analysis. /// </param> /// <param name="settings"> /// The settings. /// </param> /// <returns> /// The analysis results. /// </returns> public AnalysisResult2[] Run <TSource>(ISegment <TSource> segment, IAnalyser2 analysis, AnalysisSettings settings) { return(this.Run(new[] { segment }, analysis, settings)); }
/// <summary> /// This entrypoint should be used for testing short files (less than 2 minutes) /// </summary> public static void Execute(Arguments arguments) { MainEntry.WarnIfDevleoperEntryUsed("EventRecognizer entry does not do any audio maniuplation."); Log.Info("Running event recognizer"); var sourceAudio = arguments.Source; var configFile = arguments.Config.ToFileInfo(); var outputDirectory = arguments.Output; if (configFile == null) { throw new FileNotFoundException("No config file argument provided"); } else if (!configFile.Exists) { Log.Warn($"Config file {configFile.FullName} not found... attempting to resolve config file"); configFile = ConfigFile.Resolve(configFile.Name, Directory.GetCurrentDirectory().ToDirectoryInfo()); } LoggedConsole.WriteLine("# Recording file: " + sourceAudio.FullName); LoggedConsole.WriteLine("# Configuration file: " + configFile); LoggedConsole.WriteLine("# Output folder: " + outputDirectory); // find an appropriate event IAnalyzer IAnalyser2 recognizer = AnalyseLongRecording.FindAndCheckAnalyser <IEventRecognizer>( arguments.AnalysisIdentifier, configFile.Name); Log.Info("Attempting to run recognizer: " + recognizer.Identifier); Log.Info("Reading configuration file"); Config configuration = ConfigFile.Deserialize <RecognizerBase.RecognizerConfig>(configFile); // get default settings AnalysisSettings analysisSettings = recognizer.DefaultSettings; // convert arguments to analysis settings analysisSettings = arguments.ToAnalysisSettings( analysisSettings, outputIntermediate: true, resultSubDirectory: recognizer.Identifier, configuration: configuration); // Enable this if you want the Config file ResampleRate parameter to work. // Generally however the ResampleRate should remain at 22050Hz for all recognizers. //analysisSettings.AnalysisTargetSampleRate = (int) configuration[AnalysisKeys.ResampleRate]; // get transform input audio file - if needed Log.Info("Querying source audio file"); var audioUtilityRequest = new AudioUtilityRequest() { TargetSampleRate = analysisSettings.AnalysisTargetSampleRate, }; var preparedFile = AudioFilePreparer.PrepareFile( outputDirectory, sourceAudio, MediaTypes.MediaTypeWav, audioUtilityRequest, outputDirectory); var source = preparedFile.SourceInfo.ToSegment(); var prepared = preparedFile.TargetInfo.ToSegment(FileSegment.FileDateBehavior.None); var segmentSettings = new SegmentSettings <FileInfo>( analysisSettings, source, (analysisSettings.AnalysisOutputDirectory, analysisSettings.AnalysisTempDirectory), prepared); if (preparedFile.TargetInfo.SampleRate.Value != analysisSettings.AnalysisTargetSampleRate) { Log.Warn("Input audio sample rate does not match target sample rate"); } // Execute a pre analyzer hook recognizer.BeforeAnalyze(analysisSettings); // execute actual analysis - output data will be written Log.Info("Running recognizer: " + recognizer.Identifier); AnalysisResult2 results = recognizer.Analyze(analysisSettings, segmentSettings); // run summarize code - output data can be written Log.Info("Running recognizer summary: " + recognizer.Identifier); recognizer.SummariseResults( analysisSettings, source, results.Events, results.SummaryIndices, results.SpectralIndices, new[] { results }); //Log.Info("Recognizer run, saving extra results"); // TODO: Michael, output anything else as you wish. Log.Debug("Clean up temporary files"); if (source.Source.FullName != prepared.Source.FullName) { prepared.Source.Delete(); } int eventCount = results?.Events?.Length ?? 0; Log.Info($"Number of detected events: {eventCount}"); Log.Success(recognizer.Identifier + " recognizer has completed"); }
/// <summary> /// /// </summary> /// <param name="fiAudio"></param> /// <param name="fiConfig"></param> /// <param name="fiImage"></param> /// <returns></returns> public static Image GetImageFromAudioSegment(FileInfo fiAudio, FileInfo fiConfig, FileInfo fiImage, IAnalyser2 analyser) { var config = new ConfigDictionary(fiConfig.FullName); //read in config file bool doAnnotate = config.GetBoolean(AnalysisKeys.AnnotateSonogram); //bool doNoiseReduction = config.GetBoolean(Keys.NOISE_DO_REDUCTION); //double bgNoiseThreshold = config.GetDouble(Keys.NOISE_BG_REDUCTION); var diOutputDir = new DirectoryInfo(Path.GetDirectoryName(fiImage.FullName)); //Image image = null; if (doAnnotate) { if (analyser == null) { string analyisName = config.GetString(AnalysisKeys.AnalysisName); LoggedConsole.WriteLine("\nWARNING: Could not construct annotated image because analysis name not recognized:"); LoggedConsole.WriteLine("\t " + analyisName); return(null); } throw new NotSupportedException("Code intentionally broken because it is out of date and not used"); /* * Image image = null; * var settings = new AnalysisSettings * { * ConfigDict = config.GetDictionary(), * SegmentAudioFile = fiAudio, * ConfigFile = fiConfig, * SegmentImageFile = fiImage, * SegmentOutputDirectory = diOutputDir * }; * * // want to pass SampleRate of the original file. * settings.SampleRateOfOriginalAudioFile = int.Parse(settings.ConfigDict[AnalysisKeys.ResampleRate]); * * analyser.BeforeAnalyze(settings); * * var results = analyser.Analyze(settings, new SegmentSettings<FileInfo>(se)); * * image = results.ImageFile == null ? null : Image.FromFile(results.ImageFile.FullName); * * analyser = null; * return image;*/ } else { analyser = null; var configDict = config.GetDictionary(); BaseSonogram sonogram = Audio2DecibelSonogram(fiAudio, configDict); var mti = Sonogram2MultiTrackImage(sonogram, configDict); var image = mti.GetImage(); if (image != null) { if (fiImage.Exists) { fiImage.Delete(); } image.Save(fiImage.FullName, ImageFormat.Png); } return(image); } }
public static FileInfo SaveSummaryIndices(IAnalyser2 analyser2, string fileName, DirectoryInfo outputDirectory, IEnumerable <SummaryIndexBase> indices) { return(SaveResults(outputDirectory, fileName, analyser2.Identifier + "." + FilenameHelpers.StandardIndicesSuffix, analyser2.WriteSummaryIndicesFile, indices)); }
public static FileInfo SaveEvents(IAnalyser2 analyser2, string fileName, DirectoryInfo outputDirectory, IEnumerable <EventBase> events) { return(SaveResults(outputDirectory, fileName, analyser2.Identifier + "." + FilenameHelpers.StandardEventsSuffix, analyser2.WriteEventsFile, events)); }