diff --git a/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs b/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
index dfcd0fd55..2dd981037 100644
--- a/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
+++ b/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
@@ -47,6 +47,117 @@ public override void Draw(IImageProcessingContext graphics, EventRenderingOption
this.DrawEventLabel(graphics, options);
}
+ ///
+ /// Converts the Oscillation Detector score array to a list of Oscillation Events.
+ ///
+ /// min threshold.
+ /// max threshold.
+ /// lower freq bound of the acoustic event.
+ /// upper freq bound of the acoustic event.
+ /// the minimum oscillations per second.
+ /// the maximum oscillations per second.
+ /// the array of OD scores.
+ /// threshold.
+ /// time offset.
+ public static List ConvertOscillationScores2Events(
+ SpectrogramStandard spectrogram,
+ double minDurationThreshold,
+ double maxDurationThreshold,
+ int minHz,
+ int maxHz,
+ double? minOscilFrequency,
+ double? maxOscilFrequency,
+ double[] oscilScores,
+ double scoreThreshold,
+ TimeSpan segmentStartOffset)
+ {
+ // The name of source file
+ string fileName = spectrogram.Configuration.SourceFName;
+ double framesPerSec = spectrogram.FramesPerSecond;
+ double freqBinWidth = spectrogram.FBinWidth;
+ int count = oscilScores.Length;
+
+ // get the bin bounds of the frequency band of interest.
+ int minBin = (int)(minHz / freqBinWidth);
+ int maxBin = (int)(maxHz / freqBinWidth);
+
+ // get the oeriodicity bounds for the frequency band of interest.
+ double? minPeriodicity = 1 / maxOscilFrequency;
+ double? maxPeriodicity = 1 / minOscilFrequency;
+
+ var events = new List();
+ bool isHit = false;
+ double frameOffset = 1 / framesPerSec;
+ int startFrame = 0;
+
+ //pass over all frames
+ for (int i = 0; i < count; i++)
+ {
+ if (isHit == false && oscilScores[i] >= scoreThreshold)
+ {
+ //start of an event
+ isHit = true;
+ startFrame = i;
+ }
+ else //check for the end of an event
+ if (isHit && (oscilScores[i] < scoreThreshold || i == count - 1))
+ {
+ isHit = false;
+ double duration = (i - startFrame + 1) * frameOffset;
+ if (duration < minDurationThreshold || duration > maxDurationThreshold)
+ {
+ //skip events with duration outside the required bounds
+ continue;
+ }
+
+ // This is end of an event, so initialise it
+ // First trim the event because oscillation events spill over the edges of the true event due to use of the DCT.
+ (int trueStartFrame, int trueEndFrame, double framePeriodicity) = OscillationEvent.TrimEvent(spectrogram, startFrame, minBin, i, maxBin);
+ double trueStartTime = trueStartFrame * frameOffset;
+ double trueEndTime = trueEndFrame * frameOffset;
+ int trueFrameLength = trueEndFrame - trueStartFrame + 1;
+
+ // Determine if the periodicity is within the required bounds.
+ var periodicity = framePeriodicity * frameOffset;
+ if (periodicity < minPeriodicity || periodicity > maxPeriodicity)
+ {
+ //skip events with periodicity outside the required bounds
+ continue;
+ }
+
+ //obtain average score.
+ double sum = 0.0;
+ for (int n = trueStartFrame; n <= trueEndFrame; n++)
+ {
+ sum += oscilScores[n];
+ }
+
+ double score = sum / trueFrameLength;
+
+ var ev = new OscillationEvent()
+ {
+ Name = "Oscillation",
+ SegmentStartSeconds = segmentStartOffset.TotalSeconds,
+ ResultStartSeconds = segmentStartOffset.TotalSeconds + trueStartTime,
+ EventStartSeconds = segmentStartOffset.TotalSeconds + trueStartTime,
+ EventEndSeconds = segmentStartOffset.TotalSeconds + trueEndTime,
+ LowFrequencyHertz = minHz,
+ HighFrequencyHertz = maxHz,
+ Periodicity = framePeriodicity * frameOffset,
+ Score = score,
+ FileName = fileName,
+ };
+
+ //##########################################################################################
+ //ev.Score2 = av / (i - startFrame + 1);
+ //ev.Intensity = (int)ev.Score2; // store this info for later inclusion in csv file as Event Intensity
+ events.Add(ev);
+ }
+ }
+
+ return events;
+ }
+
///
/// Extracts an event from a spectrogram given its bounds.
/// Then trims the event because oscillation events do not typically start where the DCT places them.