private Lazy <IndexCalculateResult[]> GetLazyIndices <T>( AudioRecording recording, AnalysisSettings analysisSettings, SegmentSettings <T> segmentSettings, AcousticIndices.AcousticIndicesConfig acousticConfiguration) { // Convert the Config config to IndexCalculateConfig class and merge in the unnecesary parameters. IndexCalculateResult[] Callback() { IndexCalculateResult[] subsegmentResults = AcousticIndices.CalculateIndicesInSubsegments( recording, segmentSettings.SegmentStartOffset, segmentSettings.AnalysisIdealSegmentDuration, acousticConfiguration.IndexCalculationDuration.Seconds(), acousticConfiguration.IndexProperties, segmentSettings.Segment.SourceMetadata.SampleRate, acousticConfiguration); return(subsegmentResults); } return(new Lazy <IndexCalculateResult[]>(Callback, LazyThreadSafetyMode.ExecutionAndPublication)); }
public override AnalysisResult2 Analyze <T>(AnalysisSettings analysisSettings, SegmentSettings <T> segmentSettings) { var configuration = (StandardizedFeatureExtractionConfig)analysisSettings.Configuration; var audioFile = segmentSettings.SegmentAudioFile; var recording = new AudioRecording(audioFile.FullName); // Configurations non-specific for bands TimeSpan indexCalculationDuration = configuration.IndexCalculationDurationTimeSpan; TimeSpan bgNoiseNeighbourhood = configuration.BgNoiseBuffer; // Bands List <StandardizedFeatureExtractionConfig.BandsProperties> bandsList = configuration.Bands; // Check if there are identical bands CheckForIdenticalBands(bandsList); // Estimate total number of subsegments double segmentDurationSeconds = segmentSettings.AnalysisIdealSegmentDuration.TotalSeconds; double subsegmentDuration = indexCalculationDuration.TotalSeconds; int subsegmentCount = (int)Math.Round(segmentDurationSeconds / subsegmentDuration); int totalSubsegmentCount = subsegmentCount * bandsList.Count; // Store results of all subsegments var analysisResults = new AnalysisResult2(analysisSettings, segmentSettings, recording.Duration); analysisResults.AnalysisIdentifier = this.Identifier; var trackScores = new List <Plot>(totalSubsegmentCount); var tracks = new List <SpectralTrack>(totalSubsegmentCount); analysisResults.SummaryIndices = new SummaryIndexBase[totalSubsegmentCount]; analysisResults.SpectralIndices = new SpectralIndexBase[totalSubsegmentCount]; // Create list to store images, one for each band. They are later combined into one image. var list = new List <Image <Rgb24> >(); string imagePath = segmentSettings.SegmentImageFile.FullName; int maxImageWidth = 0; int bandCount = 0; foreach (var band in bandsList) { Log.DebugFormat("Starting band {0}/{1}", bandCount + 1, bandsList.Count); // Calculate spectral indices // get a fresh copy of the ICC config var config = (IndexCalculateConfig)((ICloneable)configuration).Clone(); // Add values specific for band from custom configuration file to config config.MinBandWidth = band.Bandwidth.Min; config.MaxBandWidth = band.Bandwidth.Max; config.FrameLength = band.FftWindow; if (band.MelScale != 0) { config.FrequencyScale = FreqScaleType.Mel; config.MelScale = band.MelScale; } else { config.FrequencyScale = FreqScaleType.Linear; } // Calculate indices for each subsegment and for each band IndexCalculateResult[] subsegmentResults = AcousticIndices.CalculateIndicesInSubsegments( recording, segmentSettings.SegmentStartOffset, segmentSettings.AnalysisIdealSegmentDuration, indexCalculationDuration, config.IndexProperties, segmentSettings.Segment.SourceMetadata.SampleRate, config); int columnsAmplitudeSpectrogram = subsegmentResults[0].AmplitudeSpectrogram.GetLength(1); double[,] amplitudeSpectrogramSegment = new double[0, columnsAmplitudeSpectrogram]; for (int i = 0; i < subsegmentResults.Length; i++) { var indexCalculateResult = subsegmentResults[i]; indexCalculateResult.SummaryIndexValues.FileName = segmentSettings.Segment.SourceMetadata.Identifier; indexCalculateResult.SpectralIndexValues.FileName = segmentSettings.Segment.SourceMetadata.Identifier; analysisResults.SummaryIndices[bandCount + (i * bandsList.Count)] = indexCalculateResult.SummaryIndexValues; analysisResults.SpectralIndices[bandCount + (i * bandsList.Count)] = indexCalculateResult.SpectralIndexValues; trackScores.AddRange(indexCalculateResult.TrackScores); if (indexCalculateResult.Tracks != null) { tracks.AddRange(indexCalculateResult.Tracks); } if (analysisSettings.AnalysisImageSaveBehavior.ShouldSave()) { // Add amplitude spectrograms of each subsegment together to get amplitude spectrogram of one segment double[,] amplitudeSpectrogramSubsegment = indexCalculateResult.AmplitudeSpectrogram; amplitudeSpectrogramSegment = MatrixTools.ConcatenateMatrixRows( amplitudeSpectrogramSegment, amplitudeSpectrogramSubsegment); } } if (analysisSettings.AnalysisImageSaveBehavior.ShouldSave()) { // Create image of amplitude spectrogram var image = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(amplitudeSpectrogramSegment)); // Label information string minBandWidth = band.Bandwidth.Min.ToString(); string maxBandWidth = band.Bandwidth.Max.ToString(); string fftWindow = band.FftWindow.ToString(); string mel; string melScale; if (band.MelScale != 0) { mel = "Mel"; melScale = band.MelScale.ToString(); } else { mel = "Standard"; melScale = 0.ToString(); } // Create label string segmentSeparator = "_"; string[] segments = { minBandWidth, maxBandWidth, fftWindow, mel, melScale }; string labelText = segments.Aggregate(string.Empty, (aggregate, item) => aggregate + segmentSeparator + item); var stringFont = Drawing.Arial14; int width = 250; int height = image.Height; var label = new Image <Rgb24>(width, height); label.Mutate(g1 => { g1.Clear(Color.Gray); g1.DrawText(labelText, stringFont, Color.Black, new PointF(4, 30)); g1.DrawLine(new Pen(Color.Black, 1), 0, 0, width, 0); //draw upper boundary g1.DrawLine(new Pen(Color.Black, 1), 0, 1, width, 1); //draw upper boundary }); var labelledImage = ImageTools.CombineImagesInLine(label, image); // Add labeled image to list list.Add(labelledImage); // Update maximal width of image if (image.Width > maxImageWidth) { maxImageWidth = image.Width; } } bandCount += 1; Log.InfoFormat("Completed band {0}/{1}", bandCount, bandsList.Count); } if (analysisSettings.AnalysisDataSaveBehavior) { this.WriteSummaryIndicesFile(segmentSettings.SegmentSummaryIndicesFile, analysisResults.SummaryIndices); analysisResults.SummaryIndicesFile = segmentSettings.SegmentSummaryIndicesFile; analysisResults.SpectraIndicesFiles = this.WriteSpectrumIndicesFiles( segmentSettings.SegmentSpectrumIndicesDirectory, Path.GetFileNameWithoutExtension(segmentSettings.SegmentAudioFile.Name), analysisResults.SpectralIndices); } if (analysisSettings.AnalysisImageSaveBehavior.ShouldSave()) { var finalImage = ImageTools.CombineImagesVertically(list, maxImageWidth); finalImage.Save(imagePath); analysisResults.ImageFile = new FileInfo(imagePath); LoggedConsole.WriteLine("See {0} for spectrogram pictures", imagePath); } return(analysisResults); }