137 lines
3.1 KiB
Go
137 lines
3.1 KiB
Go
package player
|
|
|
|
import (
|
|
"math"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestSpeedStreamerPassthroughAt1x(t *testing.T) {
|
|
src := &fakeStreamer{val: [2]float64{0.5, -0.5}, count: 1024}
|
|
var speed atomic.Uint64
|
|
speed.Store(math.Float64bits(1.0))
|
|
|
|
ss := newSpeedStreamer(src, &speed)
|
|
|
|
samples := make([][2]float64, 128)
|
|
n, ok := ss.Stream(samples)
|
|
|
|
if n != 128 || !ok {
|
|
t.Fatalf("Stream() = (%d, %v), want (128, true)", n, ok)
|
|
}
|
|
|
|
for i := range n {
|
|
if math.Abs(samples[i][0]-0.5) > 1e-9 {
|
|
t.Errorf("samples[%d][0] = %f, want 0.5", i, samples[i][0])
|
|
break
|
|
}
|
|
if math.Abs(samples[i][1]-(-0.5)) > 1e-9 {
|
|
t.Errorf("samples[%d][1] = %f, want -0.5", i, samples[i][1])
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSpeedStreamerPassthroughAtZero(t *testing.T) {
|
|
src := &fakeStreamer{val: [2]float64{0.3, 0.3}, count: 64}
|
|
var speed atomic.Uint64
|
|
speed.Store(math.Float64bits(0.0))
|
|
|
|
ss := newSpeedStreamer(src, &speed)
|
|
|
|
samples := make([][2]float64, 32)
|
|
n, ok := ss.Stream(samples)
|
|
|
|
if n != 32 || !ok {
|
|
t.Fatalf("Stream() = (%d, %v), want (32, true)", n, ok)
|
|
}
|
|
}
|
|
|
|
func TestSpeedStreamer2xProducesOutput(t *testing.T) {
|
|
src := &sineStreamer{freq: 440, sr: 44100, count: 8192}
|
|
var speed atomic.Uint64
|
|
speed.Store(math.Float64bits(2.0))
|
|
|
|
ss := newSpeedStreamer(src, &speed)
|
|
|
|
samples := make([][2]float64, 4096)
|
|
n, ok := ss.Stream(samples)
|
|
|
|
if n == 0 {
|
|
t.Fatal("Stream() at 2x speed returned 0 samples")
|
|
}
|
|
if !ok {
|
|
t.Fatal("Stream() at 2x speed returned ok=false")
|
|
}
|
|
}
|
|
|
|
func TestSpeedStreamerHalfSpeedProducesOutput(t *testing.T) {
|
|
src := &sineStreamer{freq: 440, sr: 44100, count: 8192}
|
|
var speed atomic.Uint64
|
|
speed.Store(math.Float64bits(0.5))
|
|
|
|
ss := newSpeedStreamer(src, &speed)
|
|
|
|
samples := make([][2]float64, 4096)
|
|
n, ok := ss.Stream(samples)
|
|
|
|
if n == 0 {
|
|
t.Fatal("Stream() at 0.5x speed returned 0 samples")
|
|
}
|
|
if !ok {
|
|
t.Fatal("Stream() at 0.5x speed returned ok=false")
|
|
}
|
|
}
|
|
|
|
func TestSpeedStreamerErr(t *testing.T) {
|
|
src := &fakeStreamer{}
|
|
var speed atomic.Uint64
|
|
|
|
ss := newSpeedStreamer(src, &speed)
|
|
if err := ss.Err(); err != nil {
|
|
t.Errorf("Err() = %v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func TestTsAlphaTable(t *testing.T) {
|
|
// Verify crossfade alpha table is properly initialized
|
|
if tsAlpha[0] != 0.0 {
|
|
t.Errorf("tsAlpha[0] = %f, want 0.0", tsAlpha[0])
|
|
}
|
|
lastIdx := len(tsAlpha) - 1
|
|
expectedLast := float64(lastIdx) / float64(tsOvlp)
|
|
if math.Abs(tsAlpha[lastIdx]-expectedLast) > 1e-9 {
|
|
t.Errorf("tsAlpha[%d] = %f, want %f", lastIdx, tsAlpha[lastIdx], expectedLast)
|
|
}
|
|
|
|
// Should be monotonically increasing
|
|
for i := 1; i < len(tsAlpha); i++ {
|
|
if tsAlpha[i] <= tsAlpha[i-1] {
|
|
t.Fatalf("tsAlpha[%d] (%f) <= tsAlpha[%d] (%f)", i, tsAlpha[i], i-1, tsAlpha[i-1])
|
|
}
|
|
}
|
|
}
|
|
|
|
// sineStreamer generates a sine wave for testing WSOLA
|
|
type sineStreamer struct {
|
|
freq float64
|
|
sr float64
|
|
pos int
|
|
count int
|
|
}
|
|
|
|
func (s *sineStreamer) Stream(samples [][2]float64) (int, bool) {
|
|
n := min(len(samples), s.count-s.pos)
|
|
if n <= 0 {
|
|
return 0, false
|
|
}
|
|
for i := range n {
|
|
val := math.Sin(2 * math.Pi * s.freq * float64(s.pos+i) / s.sr)
|
|
samples[i] = [2]float64{val, val}
|
|
}
|
|
s.pos += n
|
|
return n, true
|
|
}
|
|
|
|
func (s *sineStreamer) Err() error { return nil }
|