Skip to content

Commit

Permalink
Update unintelligibility algorithm (#250)
Browse files Browse the repository at this point in the history
* Update unintelligibility algorithm

Signed-off-by: Dave Thaler <[email protected]>

* Address coderabbit feedback

Signed-off-by: Dave Thaler <[email protected]>

---------

Signed-off-by: Dave Thaler <[email protected]>
  • Loading branch information
dthaler authored Jan 9, 2025
1 parent 114c7fa commit dfefd20
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 8 deletions.
60 changes: 55 additions & 5 deletions OrcanodeMonitor/Core/FfmpegCoreAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ public static double MinNoiseMagnitude

// Minimum ratio of magnitude outside the hum range to magnitude
// within the hum range. So far the max in a known-unintelligible
// sample is 21% and the min in a known-good sample is 29%.
const double _defaultMinSignalPercent = 25;
// sample is 53% and the min in a known-good sample is 208%.
const double _defaultMinSignalPercent = 150;
private static double MinSignalRatio
{
get
Expand Down Expand Up @@ -159,6 +159,50 @@ public double GetMaxNonHumMagnitude()
return maxNonHumMagnitude;
}

/// <summary>
/// Find the total magnitude outside the audio hum range.
/// </summary>
/// <returns>Magnitude</returns>
public double GetTotalNonHumMagnitude()
{
double totalNonHumMagnitude = 0;
foreach (var pair in FrequencyMagnitudes)
{
double frequency = pair.Key;
double magnitude = pair.Value;
if (!IsHumFrequency(frequency))
{
if (magnitude > MinNoiseMagnitude)
{
totalNonHumMagnitude += magnitude;
}
}
}
return totalNonHumMagnitude;
}

/// <summary>
/// Find the total magnitude of the audio hum range.
/// </summary>
/// <returns>Magnitude</returns>
public double GetTotalHumMagnitude()
{
double totalHumMagnitude = 0;
foreach (var pair in FrequencyMagnitudes)
{
double frequency = pair.Key;
double magnitude = pair.Value;
if (IsHumFrequency(frequency))
{
if (magnitude > MinNoiseMagnitude)
{
totalHumMagnitude += magnitude;
}
}
}
return totalHumMagnitude;
}

private OrcanodeOnlineStatus GetStatus(OrcanodeOnlineStatus oldStatus)
{
double max = MaxMagnitude;
Expand All @@ -174,10 +218,16 @@ private OrcanodeOnlineStatus GetStatus(OrcanodeOnlineStatus oldStatus)
return oldStatus;
}

// Find the maximum magnitude outside the audio hum range.
double maxNonHumMagnitude = GetMaxNonHumMagnitude();
// Find the total magnitude outside the audio hum range.
if (GetMaxNonHumMagnitude() < MinNoiseMagnitude)
{
// Just silence outside the hum range, no signal.
return OrcanodeOnlineStatus.Unintelligible;
}

if (maxNonHumMagnitude < MinNoiseMagnitude || maxNonHumMagnitude / max < MinSignalRatio)
double totalNonHumMagnitude = GetTotalNonHumMagnitude();
double totalHumMagnitude = GetTotalHumMagnitude();
if (totalNonHumMagnitude / totalHumMagnitude < MinSignalRatio)
{
// Essentially just silence outside the hum range, no signal.
return OrcanodeOnlineStatus.Unintelligible;
Expand Down
4 changes: 3 additions & 1 deletion OrcanodeMonitor/Pages/SpectralDensity.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@
<div>
<h2>Statistics</h2>
Max magnitude: @Model.MaxMagnitude<br />
Max magnitude outside hum range (50-60Hz): @Model.MaxNonHumMagnitude<br />
Max magnitude outside hum range: @Model.MaxNonHumMagnitude<br />
Total magnitude outside hum range: @Model.TotalNonHumMagnitude<br />
Total magnitude of hum range: @Model.TotalHumMagnitude<br />
Signal ratio: @Model.SignalRatio%<br />
Status: @Model.Status<br />
<!-- Audio Button and Element -->
Expand Down
8 changes: 7 additions & 1 deletion OrcanodeMonitor/Pages/SpectralDensity.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ public class SpectralDensityModel : PageModel
public List<double> MaxBucketMagnitude => _maxBucketMagnitude;
public string AudioUrl => _event?.Url ?? "Unknown";
public int MaxMagnitude { get; private set; }
public int TotalNonHumMagnitude => (int)Math.Round(_totalNonHumMagnitude);
public int TotalHumMagnitude => (int)Math.Round(_totalHumMagnitude);
private double _totalHumMagnitude;
private double _totalNonHumMagnitude;
public int MaxNonHumMagnitude { get; private set; }
public int SignalRatio { get; private set; }
public string Status { get; private set; }
Expand Down Expand Up @@ -81,8 +85,10 @@ private void UpdateFrequencyInfo(FrequencyInfo frequencyInfo)
double maxNonHumMagnitude = frequencyInfo.GetMaxNonHumMagnitude();
MaxMagnitude = (int)Math.Round(maxMagnitude);
MaxNonHumMagnitude = (int)Math.Round(maxNonHumMagnitude);
SignalRatio = (int)Math.Round(100 * maxNonHumMagnitude / maxMagnitude);
Status = Orcanode.GetStatusString(frequencyInfo.Status);
_totalHumMagnitude = frequencyInfo.GetTotalHumMagnitude();
_totalNonHumMagnitude = frequencyInfo.GetTotalNonHumMagnitude();
SignalRatio = (int)Math.Round(100 * _totalNonHumMagnitude / _totalHumMagnitude);
}

private async Task UpdateNodeFrequencyDataAsync()
Expand Down
1 change: 1 addition & 0 deletions Test/UnintelligibilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public async Task TestUnintelligibleSample()
[TestMethod]
public async Task TestNormalSample()
{
await TestSampleAsync("normal\\live4118.ts", OrcanodeOnlineStatus.Online);
await TestSampleAsync("normal\\live3368.ts", OrcanodeOnlineStatus.Online);

await TestSampleAsync("normal\\live3504.ts", OrcanodeOnlineStatus.Online);
Expand Down
Binary file added Test/samples/normal/live4118.ts
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/Design.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ The following state will be stored per orcanode:

**MEZMO_LOG_SECONDS**: The number of seconds of Mezmo logs to check for activity. Default: 60

**ORCASOUND_MIN_INTELLIGIBLE_SIGNAL_PERCENT**: The minimum percentage of max amplitude across all frequencies of amplitude outside the 50-60 Hz range needed to determine that an audio stream is intelligible. Default: 30
**ORCASOUND_MIN_INTELLIGIBLE_SIGNAL_PERCENT**: The minimum percentage of total magnitude across all frequencies outside the hum range vs magnitude in hum range (multiples of 60 Hz), needed to determine that an audio stream is intelligible. Default: 150

**ORCASOUND_MAX_SILENCE_AMPLITUDE**: The maximum amplitude at which an stream stream might still be considered unintelligible due to silence. Default: 20

Expand Down

0 comments on commit dfefd20

Please sign in to comment.