🎉 live server seems to be working now
This commit is contained in:
260
third_party/sendspin-go/internal/server/resampler_test.go
vendored
Normal file
260
third_party/sendspin-go/internal/server/resampler_test.go
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
// ABOUTME: Tests for audio resampler
|
||||
// ABOUTME: Tests linear interpolation resampling between sample rates
|
||||
package server
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewResampler(t *testing.T) {
|
||||
r := NewResampler(44100, 48000, 2)
|
||||
|
||||
if r == nil {
|
||||
t.Fatal("expected resampler to be created")
|
||||
}
|
||||
|
||||
if r.inputRate != 44100 {
|
||||
t.Errorf("expected inputRate 44100, got %d", r.inputRate)
|
||||
}
|
||||
|
||||
if r.outputRate != 48000 {
|
||||
t.Errorf("expected outputRate 48000, got %d", r.outputRate)
|
||||
}
|
||||
|
||||
if r.channels != 2 {
|
||||
t.Errorf("expected channels 2, got %d", r.channels)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleUpsampling(t *testing.T) {
|
||||
// 44100 -> 48000 (upsampling by factor of ~1.088)
|
||||
r := NewResampler(44100, 48000, 2)
|
||||
|
||||
// Input: 100 stereo samples (200 int16 values)
|
||||
input := make([]int32, 200)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 100) // Ramp signal
|
||||
}
|
||||
|
||||
// Calculate expected output size
|
||||
expectedSize := int(float64(len(input)) * float64(48000) / float64(44100))
|
||||
output := make([]int32, expectedSize)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
// Should have produced output
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
|
||||
// Should have produced approximately the expected amount
|
||||
// Allow some tolerance due to rounding
|
||||
if n < expectedSize-10 || n > expectedSize+10 {
|
||||
t.Errorf("expected ~%d samples, got %d", expectedSize, n)
|
||||
}
|
||||
|
||||
// Output should have interpolated values (not exact copies)
|
||||
allZero := true
|
||||
for i := 0; i < n; i++ {
|
||||
if output[i] != 0 {
|
||||
allZero = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allZero {
|
||||
t.Error("output contains only zeros")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleDownsampling(t *testing.T) {
|
||||
// 48000 -> 44100 (downsampling by factor of ~0.91875)
|
||||
r := NewResampler(48000, 44100, 2)
|
||||
|
||||
// Input: 100 stereo samples
|
||||
input := make([]int32, 200)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 100)
|
||||
}
|
||||
|
||||
expectedSize := int(float64(len(input)) * float64(44100) / float64(48000))
|
||||
output := make([]int32, expectedSize)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
|
||||
if n < expectedSize-10 || n > expectedSize+10 {
|
||||
t.Errorf("expected ~%d samples, got %d", expectedSize, n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleSameRate(t *testing.T) {
|
||||
// No resampling needed (48000 -> 48000)
|
||||
r := NewResampler(48000, 48000, 2)
|
||||
|
||||
input := make([]int32, 200)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 100)
|
||||
}
|
||||
|
||||
output := make([]int32, len(input)+10) // Extra space for rounding
|
||||
n := r.Resample(input, output)
|
||||
|
||||
// Should produce approximately the same number of samples
|
||||
// Allow small tolerance for floating point rounding
|
||||
if n < len(input)-5 || n > len(input)+5 {
|
||||
t.Errorf("expected ~%d samples, got %d", len(input), n)
|
||||
}
|
||||
|
||||
// Values should be similar (allow for interpolation artifacts)
|
||||
for i := 0; i < n && i < len(input); i++ {
|
||||
diff := abs(int(output[i]) - int(input[i]))
|
||||
if diff > 200 { // Allow some rounding errors
|
||||
t.Errorf("sample %d: expected ~%d, got %d (diff %d)", i, input[i], output[i], diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleStereo(t *testing.T) {
|
||||
// Test that stereo channels are handled correctly
|
||||
r := NewResampler(44100, 48000, 2)
|
||||
|
||||
// Create input with different L/R patterns
|
||||
input := make([]int32, 20) // 10 stereo samples
|
||||
for i := 0; i < 10; i++ {
|
||||
input[i*2] = 1000 // Left channel
|
||||
input[i*2+1] = -1000 // Right channel
|
||||
}
|
||||
|
||||
output := make([]int32, 30) // Space for upsampled output
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
|
||||
// Check that L/R pattern is preserved (approximately)
|
||||
leftPositive := 0
|
||||
rightNegative := 0
|
||||
for i := 0; i < n/2; i++ {
|
||||
if output[i*2] > 0 {
|
||||
leftPositive++
|
||||
}
|
||||
if output[i*2+1] < 0 {
|
||||
rightNegative++
|
||||
}
|
||||
}
|
||||
|
||||
// Most samples should maintain the pattern
|
||||
if leftPositive < n/4 {
|
||||
t.Error("left channel pattern not preserved")
|
||||
}
|
||||
if rightNegative < n/4 {
|
||||
t.Error("right channel pattern not preserved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleMono(t *testing.T) {
|
||||
// Test mono resampling
|
||||
r := NewResampler(44100, 48000, 1)
|
||||
|
||||
input := make([]int32, 100)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 50)
|
||||
}
|
||||
|
||||
expectedSize := int(float64(len(input)) * float64(48000) / float64(44100))
|
||||
output := make([]int32, expectedSize)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleLargeRatioUp(t *testing.T) {
|
||||
// Test large upsampling ratio (44.1k -> 192k)
|
||||
r := NewResampler(44100, 192000, 2)
|
||||
|
||||
input := make([]int32, 200)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 10)
|
||||
}
|
||||
|
||||
expectedSize := int(float64(len(input)) * float64(192000) / float64(44100))
|
||||
output := make([]int32, expectedSize)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
|
||||
// Should have significantly more samples
|
||||
if n < len(input)*3 {
|
||||
t.Errorf("expected at least 3x upsampling, got %d from %d", n, len(input))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleLargeRatioDown(t *testing.T) {
|
||||
// Test large downsampling ratio (192k -> 48k)
|
||||
r := NewResampler(192000, 48000, 2)
|
||||
|
||||
input := make([]int32, 200)
|
||||
for i := range input {
|
||||
input[i] = int32(i * 10)
|
||||
}
|
||||
|
||||
expectedSize := int(float64(len(input)) * float64(48000) / float64(192000))
|
||||
output := make([]int32, expectedSize)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output")
|
||||
}
|
||||
|
||||
// Should have significantly fewer samples
|
||||
if n > len(input)/2 {
|
||||
t.Errorf("expected at most 1/2 samples after downsampling, got %d from %d", n, len(input))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleEmptyInput(t *testing.T) {
|
||||
r := NewResampler(44100, 48000, 2)
|
||||
|
||||
input := []int32{}
|
||||
output := make([]int32, 100)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
if n != 0 {
|
||||
t.Errorf("expected 0 samples from empty input, got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResampleSmallBuffer(t *testing.T) {
|
||||
r := NewResampler(44100, 48000, 2)
|
||||
|
||||
// Small input
|
||||
input := []int32{100, -100, 200, -200}
|
||||
output := make([]int32, 10)
|
||||
|
||||
n := r.Resample(input, output)
|
||||
|
||||
// Should produce some output
|
||||
if n == 0 {
|
||||
t.Fatal("resampler produced no output from small buffer")
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function
|
||||
func abs(x int) int {
|
||||
if x < 0 {
|
||||
return -x
|
||||
}
|
||||
return x
|
||||
}
|
||||
Reference in New Issue
Block a user