104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
package noise
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestSuppressorDisabledBypassesSamples(t *testing.T) {
|
|
suppressor := NewSuppressor()
|
|
samples := []int16{100, -200, 300, -400, 500}
|
|
original := append([]int16(nil), samples...)
|
|
|
|
suppressor.ProcessSamples(samples)
|
|
|
|
for i := range samples {
|
|
if samples[i] != original[i] {
|
|
t.Fatalf("expected sample %d to remain unchanged, got %d want %d", i, samples[i], original[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSuppressorAttenuatesLowLevelNoise(t *testing.T) {
|
|
suppressor := NewSuppressor()
|
|
suppressor.SetEnabled(true)
|
|
suppressor.SetThreshold(0.08)
|
|
|
|
input := makeSineFrame(600, 700)
|
|
originalRMS := frameRMS(input)
|
|
processed := append([]int16(nil), input...)
|
|
suppressor.ProcessSamples(processed)
|
|
processedRMS := frameRMS(processed)
|
|
|
|
if processedRMS >= originalRMS*0.8 {
|
|
t.Fatalf("expected low-level noise attenuation, got RMS %.2f from %.2f", processedRMS, originalRMS)
|
|
}
|
|
}
|
|
|
|
func TestSuppressorPreservesSpeechLikeSignal(t *testing.T) {
|
|
suppressor := NewSuppressor()
|
|
suppressor.SetEnabled(true)
|
|
suppressor.SetThreshold(0.08)
|
|
|
|
voice := makeSineFrame(1000, 9000)
|
|
originalRMS := frameRMS(voice)
|
|
processed := append([]int16(nil), voice...)
|
|
suppressor.ProcessSamples(processed)
|
|
processedRMS := frameRMS(processed)
|
|
|
|
if processedRMS <= originalRMS*0.6 {
|
|
t.Fatalf("expected speech-like signal to be mostly preserved, got RMS %.2f from %.2f", processedRMS, originalRMS)
|
|
}
|
|
}
|
|
|
|
func TestHigherThresholdAppliesStrongerSuppression(t *testing.T) {
|
|
lowSuppressor := NewSuppressor()
|
|
lowSuppressor.SetEnabled(true)
|
|
lowSuppressor.SetThreshold(0.02)
|
|
|
|
highSuppressor := NewSuppressor()
|
|
highSuppressor.SetEnabled(true)
|
|
highSuppressor.SetThreshold(0.20)
|
|
|
|
noiseFrame := makeSineFrame(500, 700)
|
|
lowRMS := runFrameWarmup(lowSuppressor, noiseFrame, 8)
|
|
highRMS := runFrameWarmup(highSuppressor, noiseFrame, 8)
|
|
|
|
if highRMS >= lowRMS*0.8 {
|
|
t.Fatalf("expected stronger suppression at higher threshold, got low %.2f high %.2f", lowRMS, highRMS)
|
|
}
|
|
}
|
|
|
|
func runFrameWarmup(suppressor *Suppressor, frame []int16, repeats int) float64 {
|
|
var processed []int16
|
|
for i := 0; i < repeats; i++ {
|
|
processed = append([]int16(nil), frame...)
|
|
suppressor.ProcessSamples(processed)
|
|
}
|
|
return frameRMS(processed)
|
|
}
|
|
|
|
func makeSineFrame(frequency float64, amplitude float64) []int16 {
|
|
const sampleRate = 48000.0
|
|
const frameSize = 480
|
|
|
|
frame := make([]int16, frameSize)
|
|
for i := 0; i < frameSize; i++ {
|
|
value := math.Sin((2.0 * math.Pi * frequency * float64(i)) / sampleRate)
|
|
frame[i] = int16(value * amplitude)
|
|
}
|
|
return frame
|
|
}
|
|
|
|
func frameRMS(samples []int16) float64 {
|
|
if len(samples) == 0 {
|
|
return 0.0
|
|
}
|
|
var sumSquares float64
|
|
for _, sample := range samples {
|
|
normalized := float64(sample) / 32768.0
|
|
sumSquares += normalized * normalized
|
|
}
|
|
return math.Sqrt(sumSquares / float64(len(samples)))
|
|
}
|