Noise suppression tweaks.
This commit is contained in:
103
noise/suppression_test.go
Normal file
103
noise/suppression_test.go
Normal file
@@ -0,0 +1,103 @@
|
||||
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)))
|
||||
}
|
||||
Reference in New Issue
Block a user