Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

99 rindas
3.0KB

  1. package rds
  2. import (
  3. "math"
  4. "strings"
  5. "testing"
  6. )
  7. func TestCRC10KnownVector(t *testing.T) {
  8. c := crc10(0x1234)
  9. if c > 0x3FF { t.Fatalf("CRC exceeds 10 bits: %x", c) }
  10. }
  11. func TestEncodeBlockProduces26Bits(t *testing.T) {
  12. block := encodeBlock(0x1234, 'A')
  13. if block>>26 != 0 { t.Fatalf("block exceeds 26 bits: %x", block) }
  14. if uint16(block>>10) != 0x1234 { t.Fatalf("data mismatch") }
  15. }
  16. func TestBuildGroup0A(t *testing.T) {
  17. g := buildGroup0A(0x1234, 0, false, false, 0, "TESTFM")
  18. if g[0] != 0x1234 { t.Fatalf("block A not PI: %x", g[0]) }
  19. if byte(g[3]>>8) != 'T' || byte(g[3]&0xFF) != 'E' { t.Fatal("wrong PS chars") }
  20. }
  21. func TestBuildGroup2A(t *testing.T) {
  22. g := buildGroup2A(0x1234, 0, false, false, 0, "Hello World")
  23. if g[0] != 0x1234 { t.Fatal("block A not PI") }
  24. if (g[1]>>12)&0x0F != 2 { t.Fatal("wrong group type") }
  25. }
  26. func TestBuildGroupUsesConfiguredPI(t *testing.T) {
  27. if buildGroup0A(0xBEEF, 0, false, false, 0, "TEST")[0] != 0xBEEF { t.Fatal("PI mismatch 0A") }
  28. if buildGroup2A(0xCAFE, 0, false, false, 0, "Hello")[0] != 0xCAFE { t.Fatal("PI mismatch 2A") }
  29. }
  30. func TestEncoderGenerate(t *testing.T) {
  31. cfg := DefaultConfig(); cfg.SampleRate = 228000
  32. enc, err := NewEncoder(cfg)
  33. if err != nil { t.Fatal(err) }
  34. samples := enc.Generate(1024)
  35. if len(samples) != 1024 { t.Fatal("wrong length") }
  36. var energy, maxAbs float64
  37. for _, s := range samples {
  38. energy += s * s
  39. if math.Abs(s) > maxAbs { maxAbs = math.Abs(s) }
  40. }
  41. if energy == 0 { t.Fatal("zero energy") }
  42. // Unity output: peak should be close to 1.0
  43. if maxAbs > 1.01 { t.Fatalf("exceeds unity: %.6f", maxAbs) }
  44. }
  45. func TestEncoderNextSample(t *testing.T) {
  46. cfg := DefaultConfig(); cfg.SampleRate = 228000
  47. enc, _ := NewEncoder(cfg)
  48. s := enc.NextSample()
  49. // Should not panic and should produce a value
  50. if math.IsNaN(s) { t.Fatal("NaN") }
  51. }
  52. func TestEncoderReset(t *testing.T) {
  53. cfg := DefaultConfig(); cfg.SampleRate = 228000
  54. enc, _ := NewEncoder(cfg)
  55. a := enc.NextSample()
  56. for i := 0; i < 100; i++ { enc.NextSample() }
  57. enc.Reset()
  58. b := enc.NextSample()
  59. if math.Abs(a-b) > 1e-9 { t.Fatalf("reset failed: %v vs %v", a, b) }
  60. }
  61. func TestGroupSchedulerCycles(t *testing.T) {
  62. cfg := DefaultConfig(); cfg.PS = "TESTPS"; cfg.RT = "short"
  63. gs := newGroupScheduler(cfg)
  64. for i := 0; i < 40; i++ { _ = gs.NextGroup() }
  65. }
  66. func TestNormalizePS(t *testing.T) {
  67. if normalizePS("radiox") != "RADIOX " { t.Fatal("wrong PS") }
  68. }
  69. func TestNormalizeRT(t *testing.T) {
  70. if len(normalizeRT(strings.Repeat("a", 80))) != 64 { t.Fatal("wrong RT length") }
  71. }
  72. func TestDifferentialEncoder(t *testing.T) {
  73. d := diffEncoder{}
  74. expected := []uint8{0, 1, 1, 0}
  75. input := []uint8{0, 1, 0, 1}
  76. for i, in := range input {
  77. if got := d.encode(in); got != expected[i] { t.Fatalf("step %d: got %d want %d", i, got, expected[i]) }
  78. }
  79. }
  80. func TestRTSegmentCount(t *testing.T) {
  81. if rtSegmentCount("Hi") != 1 { t.Fatal("expected 1") }
  82. if rtSegmentCount("Hello World!") != 3 { t.Fatal("expected 3") }
  83. if rtSegmentCount(strings.Repeat("x", 64)) != 16 { t.Fatal("expected 16") }
  84. }