Esempio n. 1
0
 /// <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);
        }