|
|
|
@@ -0,0 +1,60 @@ |
|
|
|
package stereo |
|
|
|
|
|
|
|
import ( |
|
|
|
"math" |
|
|
|
"testing" |
|
|
|
|
|
|
|
"github.com/jan/fm-rds-tx/internal/audio" |
|
|
|
) |
|
|
|
|
|
|
|
func TestSSBAndVSBDelayMonoToMatchDiffPath(t *testing.T) { |
|
|
|
const sampleRate = 228000 |
|
|
|
const wantDelay = (ssbHilbertTaps - 1) / 2 |
|
|
|
|
|
|
|
for _, mode := range []Mode{ModeSSB, ModeVSB} { |
|
|
|
enc := NewStereoEncoder(sampleRate) |
|
|
|
enc.SetMode(mode, sampleRate) |
|
|
|
|
|
|
|
for i := 0; i < wantDelay; i++ { |
|
|
|
c := enc.Encode(audio.NewFrame(1, 1)) |
|
|
|
if math.Abs(c.Mono) > 1e-12 { |
|
|
|
t.Fatalf("mode %s: mono leaked before delay filled at sample %d: got %.9f want 0", mode, i, c.Mono) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
c := enc.Encode(audio.NewFrame(1, 1)) |
|
|
|
if math.Abs(c.Mono-1) > 1e-12 { |
|
|
|
t.Fatalf("mode %s: mono did not emerge after expected delay: got %.9f want 1", mode, c.Mono) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func TestDSBMonoRemainsUndelayed(t *testing.T) { |
|
|
|
enc := NewStereoEncoder(228000) |
|
|
|
enc.SetMode(ModeDSB, 228000) |
|
|
|
c := enc.Encode(audio.NewFrame(1, 1)) |
|
|
|
if math.Abs(c.Mono-1) > 1e-12 { |
|
|
|
t.Fatalf("DSB mono should be immediate: got %.9f want 1", c.Mono) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func TestResetClearsMonoDelayState(t *testing.T) { |
|
|
|
const sampleRate = 228000 |
|
|
|
const wantDelay = (ssbHilbertTaps - 1) / 2 |
|
|
|
|
|
|
|
enc := NewStereoEncoder(sampleRate) |
|
|
|
enc.SetMode(ModeSSB, sampleRate) |
|
|
|
|
|
|
|
for i := 0; i < wantDelay+4; i++ { |
|
|
|
_ = enc.Encode(audio.NewFrame(1, 1)) |
|
|
|
} |
|
|
|
|
|
|
|
enc.Reset() |
|
|
|
|
|
|
|
for i := 0; i < wantDelay; i++ { |
|
|
|
c := enc.Encode(audio.NewFrame(1, 1)) |
|
|
|
if math.Abs(c.Mono) > 1e-12 { |
|
|
|
t.Fatalf("reset did not clear mono delay at sample %d: got %.9f want 0", i, c.Mono) |
|
|
|
} |
|
|
|
} |
|
|
|
} |