/// <summary> /// Initializes a new instance of the <see cref="AnalysisResult2"/> class. /// This is the standard result class for <c>IAnalyser2</c> results. /// </summary> /// <param name="settingsUsed"> /// Represents the settings used for the analysis. /// </param> /// <param name="segmentSettings">The settings for the segment that was analyzed.</param> /// <param name="durationAnalyzed"> /// Records the actual duration analyzed by the analysis. /// </param> public AnalysisResult2(AnalysisSettings settingsUsed, SegmentSettingsBase segmentSettings, TimeSpan durationAnalyzed) { this.SegmentSettings = segmentSettings; this.SettingsUsed = (AnalysisSettings)settingsUsed.Clone(); this.OutputFiles = new Dictionary <string, FileInfo>(); this.SegmentAudioDuration = durationAnalyzed; this.MiscellaneousResults = new Dictionary <string, object>(); this.SummaryIndices = new SummaryIndexBase[0]; this.SpectralIndices = new SpectralIndexBase[0]; this.Events = new EventBase[0]; }
/// <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); }