Files
voice-cat/dotnet/src/VoiceCat.Dsp/EnergyVadProcessor.cs
T

49 lines
1.5 KiB
C#
Raw Normal View History

namespace VoiceCat.Dsp;
public sealed class EnergyVadProcessor
{
private readonly TimeProvider timeProvider;
private long lastVoiceTimestamp;
private bool hasVoice;
private float threshold;
public float Threshold
{
get => Volatile.Read(ref threshold);
set
{
if (!float.IsFinite(value) || value is < 0 or > 1) throw new ArgumentOutOfRangeException(nameof(value));
Volatile.Write(ref threshold, value);
}
}
public TimeSpan HangTime { get; }
public EnergyVadProcessor(float threshold = 0.02f, TimeSpan? hangTime = null, TimeProvider? timeProvider = null)
{
Threshold = threshold;
HangTime = hangTime ?? TimeSpan.FromMilliseconds(300);
if (HangTime < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(hangTime));
this.timeProvider = timeProvider ?? TimeProvider.System;
}
public bool Process(ReadOnlySpan<short> pcm)
{
long now = timeProvider.GetTimestamp();
if (!pcm.IsEmpty)
{
double sum = 0;
foreach (short sample in pcm)
{
double normalized = sample / 32768.0;
sum += normalized * normalized;
}
if (Math.Sqrt(sum / pcm.Length) >= Threshold)
{
lastVoiceTimestamp = now;
hasVoice = true;
}
}
return hasVoice && timeProvider.GetElapsedTime(lastVoiceTimestamp, now) < HangTime;
}
}