Wideband autonomous SDR analysis engine forked from sdr-visual-suite
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

90 Zeilen
2.3KB

  1. package gpudemod
  2. import (
  3. "math"
  4. "math/cmplx"
  5. "testing"
  6. )
  7. func makeDeterministicIQ(n int) []complex64 {
  8. out := make([]complex64, n)
  9. for i := 0; i < n; i++ {
  10. a := 0.017 * float64(i)
  11. b := 0.031 * float64(i)
  12. out[i] = complex64(complex(math.Cos(a)+0.2*math.Cos(b), math.Sin(a)+0.15*math.Sin(b)))
  13. }
  14. return out
  15. }
  16. func makeLowpassTaps(n int) []float32 {
  17. out := make([]float32, n)
  18. for i := range out {
  19. out[i] = 1.0 / float32(n)
  20. }
  21. return out
  22. }
  23. func requireComplexSlicesClose(t *testing.T, a []complex64, b []complex64, tol float64) {
  24. t.Helper()
  25. if len(a) != len(b) {
  26. t.Fatalf("length mismatch: %d vs %d", len(a), len(b))
  27. }
  28. for i := range a {
  29. if cmplx.Abs(complex128(a[i]-b[i])) > tol {
  30. t.Fatalf("slice mismatch at %d: %v vs %v (tol=%f)", i, a[i], b[i], tol)
  31. }
  32. }
  33. }
  34. func TestCPUOracleMonolithicVsChunked(t *testing.T) {
  35. iq := makeDeterministicIQ(200000)
  36. mk := func() *CPUOracleState {
  37. return &CPUOracleState{
  38. SignalID: 1,
  39. ConfigHash: 123,
  40. NCOPhase: 0,
  41. Decim: 20,
  42. PhaseCount: 0,
  43. NumTaps: 65,
  44. ShiftedHistory: make([]complex64, 0, 64),
  45. BaseTaps: makeLowpassTaps(65),
  46. }
  47. }
  48. phaseInc := 0.017
  49. monoState := mk()
  50. mono := CPUOracleExtract(iq, monoState, phaseInc)
  51. chunked := RunChunkedCPUOracle(iq, []int{4096, 5000, 8192, 27307}, mk, phaseInc)
  52. requireComplexSlicesClose(t, mono, chunked, 1e-5)
  53. }
  54. func TestExactIntegerDecimation(t *testing.T) {
  55. if d, err := ExactIntegerDecimation(4000000, 200000); err != nil || d != 20 {
  56. t.Fatalf("unexpected exact decim result: d=%d err=%v", d, err)
  57. }
  58. if _, err := ExactIntegerDecimation(4000000, 192000); err == nil {
  59. t.Fatalf("expected non-integer decimation error")
  60. }
  61. }
  62. func TestCPUOracleDirectVsPolyphase(t *testing.T) {
  63. iq := makeDeterministicIQ(50000)
  64. mk := func() *CPUOracleState {
  65. taps := makeLowpassTaps(65)
  66. return &CPUOracleState{
  67. SignalID: 1,
  68. ConfigHash: 123,
  69. NCOPhase: 0,
  70. Decim: 20,
  71. PhaseCount: 0,
  72. NumTaps: 65,
  73. ShiftedHistory: make([]complex64, 0, 64),
  74. BaseTaps: taps,
  75. PolyphaseTaps: BuildPolyphaseTapsPhaseMajor(taps, 20),
  76. }
  77. }
  78. phaseInc := 0.017
  79. direct := CPUOracleExtract(iq, mk(), phaseInc)
  80. poly := CPUOracleExtractPolyphase(iq, mk(), phaseInc)
  81. requireComplexSlicesClose(t, direct, poly, 1e-5)
  82. }