Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

159 líneas
3.6KB

  1. package rds
  2. import (
  3. "math"
  4. "strings"
  5. "testing"
  6. )
  7. func TestCRC10KnownVector(t *testing.T) {
  8. // Verify the CRC polynomial produces 10-bit outputs
  9. c := crc10(0x1234)
  10. if c > 0x3FF {
  11. t.Fatalf("CRC exceeds 10 bits: %x", c)
  12. }
  13. }
  14. func TestEncodeBlockProduces26Bits(t *testing.T) {
  15. block := encodeBlock(0x1234, 'A')
  16. // Must fit in 26 bits
  17. if block>>26 != 0 {
  18. t.Fatalf("block exceeds 26 bits: %x", block)
  19. }
  20. // Data portion should be the original word
  21. data := uint16(block >> 10)
  22. if data != 0x1234 {
  23. t.Fatalf("data mismatch: got %x want %x", data, 0x1234)
  24. }
  25. }
  26. func TestBuildGroup0ABlockCount(t *testing.T) {
  27. g := buildGroup0A(0x1234, 0, false, false, 0, "TESTFM")
  28. // Block A must be PI
  29. if g[0] != 0x1234 {
  30. t.Fatalf("block A not PI: %x", g[0])
  31. }
  32. // Block D should contain first two PS chars 'T','E'
  33. ch0 := byte(g[3] >> 8)
  34. ch1 := byte(g[3] & 0xFF)
  35. if ch0 != 'T' || ch1 != 'E' {
  36. t.Fatalf("unexpected PS chars: %c %c", ch0, ch1)
  37. }
  38. }
  39. func TestBuildGroup2ABlockCount(t *testing.T) {
  40. g := buildGroup2A(0x1234, 0, false, false, 0, "Hello World")
  41. if g[0] != 0x1234 {
  42. t.Fatalf("block A not PI: %x", g[0])
  43. }
  44. // Group type field in block B should have type 2 in bits 15..12
  45. groupType := (g[1] >> 12) & 0x0F
  46. if groupType != 2 {
  47. t.Fatalf("unexpected group type: %d", groupType)
  48. }
  49. }
  50. func TestEncoderGenerate(t *testing.T) {
  51. cfg := DefaultConfig()
  52. cfg.SampleRate = 228000
  53. enc, err := NewEncoder(cfg)
  54. if err != nil {
  55. t.Fatalf("unexpected error: %v", err)
  56. }
  57. samples := enc.Generate(1024)
  58. if len(samples) != 1024 {
  59. t.Fatalf("expected 1024 samples, got %d", len(samples))
  60. }
  61. var maxAbs float64
  62. var energy float64
  63. for _, s := range samples {
  64. a := math.Abs(s)
  65. energy += s * s
  66. if a > maxAbs {
  67. maxAbs = a
  68. }
  69. }
  70. if energy == 0 {
  71. t.Fatal("expected non-zero energy in RDS output")
  72. }
  73. if maxAbs > defaultAmplitude*1.01 {
  74. t.Fatalf("samples exceed configured amplitude: %.6f", maxAbs)
  75. }
  76. }
  77. func TestEncoderReset(t *testing.T) {
  78. cfg := DefaultConfig()
  79. cfg.SampleRate = 228000
  80. enc, err := NewEncoder(cfg)
  81. if err != nil {
  82. t.Fatalf("unexpected error: %v", err)
  83. }
  84. sampleA := enc.Generate(1)[0]
  85. enc.Generate(100)
  86. enc.Reset()
  87. sampleB := enc.Generate(1)[0]
  88. if math.Abs(sampleA-sampleB) > 1e-9 {
  89. t.Fatalf("expected reset to replay initial sample: %v vs %v", sampleA, sampleB)
  90. }
  91. }
  92. func TestGroupSchedulerCycles(t *testing.T) {
  93. cfg := DefaultConfig()
  94. cfg.PS = "TESTPS"
  95. cfg.RT = "short"
  96. gs := newGroupScheduler(cfg)
  97. // Should get 4 PS groups then RT groups then cycle
  98. for i := 0; i < 40; i++ {
  99. _ = gs.NextGroup()
  100. }
  101. // No panic = success
  102. }
  103. func TestNormalizePS(t *testing.T) {
  104. got := normalizePS("radiox")
  105. if got != "RADIOX " {
  106. t.Fatalf("unexpected PS: %q", got)
  107. }
  108. }
  109. func TestNormalizeRT(t *testing.T) {
  110. long := strings.Repeat("a", 80)
  111. got := normalizeRT(long)
  112. if len(got) != 64 {
  113. t.Fatalf("unexpected RT length: %d", len(got))
  114. }
  115. }
  116. func TestDifferentialEncoder(t *testing.T) {
  117. d := diffEncoder{}
  118. // Input: 0 -> out = 0^0 = 0, prev=0
  119. // Input: 1 -> out = 0^1 = 1, prev=1
  120. // Input: 0 -> out = 1^0 = 1, prev=1
  121. // Input: 1 -> out = 1^1 = 0, prev=0
  122. expected := []uint8{0, 1, 1, 0}
  123. input := []uint8{0, 1, 0, 1}
  124. for i, in := range input {
  125. got := d.encode(in)
  126. if got != expected[i] {
  127. t.Fatalf("step %d: input=%d expected=%d got=%d", i, in, expected[i], got)
  128. }
  129. }
  130. }
  131. func TestRTSegmentCount(t *testing.T) {
  132. if n := rtSegmentCount("Hi"); n != 1 {
  133. t.Fatalf("expected 1, got %d", n)
  134. }
  135. if n := rtSegmentCount("Hello World!"); n != 3 {
  136. t.Fatalf("expected 3, got %d", n)
  137. }
  138. if n := rtSegmentCount(strings.Repeat("x", 64)); n != 16 {
  139. t.Fatalf("expected 16, got %d", n)
  140. }
  141. }