Skip to content

Commit

Permalink
Improve unintelligibility algorithm (#140)
Browse files Browse the repository at this point in the history
The amplitude for noise (as opposed to silence) is no longer
a fixed value, but is now relative to the maximum amplitude.
This should provide a better protection against the natural
high/low tide variation of amplitude.

Signed-off-by: Dave Thaler <[email protected]>
  • Loading branch information
dthaler authored Sep 30, 2024
1 parent 036b51c commit 89eceb2
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 34 deletions.
26 changes: 16 additions & 10 deletions OrcanodeMonitor/Core/FfmpegCoreAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ public class FfmpegCoreAnalyzer
// We consider anything below this average amplitude as silence.
const double MaxSilenceAmplitude = 20.0;

// We consider anything above this frequency amplitude as signal.
const double MinSignalAmplitude = 200.0;
// Minimum ratio of amplitude outside the hum range to amplitude
// within the hum range. So far the max in a known-unintelligible
// sample is 10% and the min in a known-good sample is 50%. So for
// now we use 20%.
const double MinSignalRatio = 0.20;

// Microphone audio hum typically falls within the 50 Hz to 60 Hz
// range. This hum is often caused by electrical interference from
// power lines and other electronic devices.
const double MinHumFrequency = 50.0; // Hz
const double MaxHumFrequency = 60.0; // Hz

private static bool IsHumFrequency(double frequency) => (frequency >= MinHumFrequency && frequency <= MaxHumFrequency);

private static OrcanodeOnlineStatus AnalyzeFrequencies(float[] data, int sampleRate)
{
int n = data.Length;
Expand All @@ -41,27 +46,28 @@ private static OrcanodeOnlineStatus AnalyzeFrequencies(float[] data, int sampleR
return OrcanodeOnlineStatus.Unintelligible;
}

// Look for signal in frequencies other than the audio hum range.
double halfOfMax = amplitudes.Max() / 2.0;
var majorOtherIndices = new Dictionary<double, double>();
// Find the maximum amplitude outside the audio hum range.
double maxNonHumAmplitude = 0;
for (int i = 0; i < amplitudes.Length; i++)
{
if (amplitudes[i] > MinSignalAmplitude)
double frequency = (((double)i) * sampleRate) / n;
double amplitude = amplitudes[i];
if (!IsHumFrequency(frequency))
{
double frequency = (((double)i) * sampleRate) / n;
if (frequency < MinHumFrequency || frequency > MaxHumFrequency)
if (maxNonHumAmplitude < amplitude)
{
majorOtherIndices[frequency] = amplitudes[i];
maxNonHumAmplitude = amplitude;
}
}
}

if (majorOtherIndices.Count == 0)
if (maxNonHumAmplitude / max < MinSignalRatio)
{
// Essentially just silence outside the hum range, no signal.
return OrcanodeOnlineStatus.Unintelligible;
}

// Signal outside the hum range.
return OrcanodeOnlineStatus.Online;
}

Expand Down
24 changes: 0 additions & 24 deletions OrcanodeMonitor/Core/WelfordVariance.cs

This file was deleted.

1 change: 1 addition & 0 deletions Test/UnintelligibilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public async Task TestUnintelligibleSample()
[TestMethod]
public async Task TestNormalSample()
{
await TestSampleAsync("normal\\live3504.ts", OrcanodeOnlineStatus.Online);
await TestSampleAsync("normal\\live2649.ts", OrcanodeOnlineStatus.Online);
await TestSampleAsync("normal\\live2289.ts", OrcanodeOnlineStatus.Online);
await TestSampleAsync("normal\\live385.ts", OrcanodeOnlineStatus.Online);
Expand Down
Binary file added Test/samples/normal/live3504.ts
Binary file not shown.

0 comments on commit 89eceb2

Please sign in to comment.