diff --git a/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs b/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
index a70a05f46..dfcd0fd55 100644
--- a/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
+++ b/src/AudioAnalysisTools/Events/Types/OscillationEvent.cs
@@ -6,6 +6,7 @@ namespace AudioAnalysisTools
{
using System;
using System.Collections.Generic;
+ using System.Linq;
using AudioAnalysisTools.Events;
using AudioAnalysisTools.Events.Drawing;
using AudioAnalysisTools.StandardSpectrograms;
@@ -26,6 +27,11 @@ public OscillationEvent()
///
public double Periodicity { get; set; }
+ ///
+ /// Gets the oascillation rate. This is calculated from the Periodicity. Cannot be set directly.
+ ///
+ public double OscillationRate => 1 / this.Periodicity;
+
///
/// Draws a border around this oscillation event.
///
@@ -44,18 +50,21 @@ public override void Draw(IImageProcessingContext graphics, EventRenderingOption
///
/// 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.
- /// It a;sp returns the periodicity of the oscillation event.
+ /// It also returns the periodicity of the oscillation event.
///
public static (int EventStart, int EventEnd, double FramePeriod) TrimEvent(SpectrogramStandard spectrogram, int startFrame, int minBin, int endFrame, int maxBin)
{
- //obtain the oscillation event's periodicity.
//extract the relevant portion of the spectrogram.
var eventMatrix = MatrixTools.Submatrix(spectrogram.Data, startFrame, minBin, endFrame, maxBin);
+
+ // Caclulate a normalised vector of timeframe average amplitudes.
var frameAverages = MatrixTools.GetRowAverages(eventMatrix);
+ var meanValue = frameAverages.Average();
+ frameAverages = DataTools.SubtractValueAndTruncateToZero(frameAverages, meanValue);
frameAverages = DataTools.normalise(frameAverages);
- double threshold = 0.25;
+ double threshold = 0.33;
- // find the true start frame
+ // find a potentially more accurate start frame
int startFrameOffset = 0;
for (int frame = 1; frame < frameAverages.Length; frame++)
{
@@ -66,8 +75,9 @@ public static (int EventStart, int EventEnd, double FramePeriod) TrimEvent(Spect
}
}
+ // find a potentially more accurate end frame
int endFrameOffset = 0;
- for (int frame = frameAverages.Length - 1; frame >= 0; frame--)
+ for (int frame = frameAverages.Length - 1; frame > 0; frame--)
{
endFrameOffset++;
if (frameAverages[frame - 1] >= threshold && frameAverages[frame] < threshold)
@@ -76,10 +86,21 @@ public static (int EventStart, int EventEnd, double FramePeriod) TrimEvent(Spect
}
}
- int trueStartFrame = startFrame + startFrameOffset;
- int trueEndFrame = endFrame - endFrameOffset;
+ int revisedStartFrame = startFrame + startFrameOffset;
+ int revisedEndFrame = endFrame - endFrameOffset;
+
+ // the above algorithm may produce faulty result for some situations.
+ // This is a sanity check.
+ int revisedEventLength = revisedEndFrame - revisedStartFrame + 1;
+ if (revisedEventLength < frameAverages.Length * 0.75)
+ {
+ // if revised event length is too short, return to original start and end values
+ revisedStartFrame = startFrame;
+ revisedEndFrame = endFrame;
+ }
- // determine the number of times the frame values step from below to above threshold.
+ // Now obtain the oscillation event's periodicity.
+ // Determine the number of times the frame values step from below to above threshold.
// also the frame index in which the steps happen.
int stepCount = 0;
var peakOnsets = new List();
@@ -96,7 +117,7 @@ public static (int EventStart, int EventEnd, double FramePeriod) TrimEvent(Spect
int framePeriods = peakOnsets[peakOnsets.Count - 1] - peakOnsets[0];
double framePeriod = framePeriods / (double)(stepCount - 1);
- return (trueStartFrame, trueEndFrame, framePeriod);
+ return (revisedStartFrame, revisedEndFrame, framePeriod);
}
}
}
\ No newline at end of file