Wideband autonomous SDR analysis engine forked from sdr-visual-suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.4KB

  1. package dsp
  2. import "math"
  3. type DCBlocker struct {
  4. r float64
  5. prevX complex64
  6. prevY complex64
  7. }
  8. func NewDCBlocker(r float64) *DCBlocker {
  9. if r <= 0 || r >= 1 {
  10. r = 0.995
  11. }
  12. return &DCBlocker{r: r}
  13. }
  14. func (d *DCBlocker) Reset() {
  15. d.prevX = 0
  16. d.prevY = 0
  17. }
  18. func (d *DCBlocker) Apply(iq []complex64) {
  19. if d == nil {
  20. return
  21. }
  22. for i := 0; i < len(iq); i++ {
  23. x := iq[i]
  24. y := complex(
  25. float32(float64(real(x)-real(d.prevX))+d.r*float64(real(d.prevY))),
  26. float32(float64(imag(x)-imag(d.prevX))+d.r*float64(imag(d.prevY))),
  27. )
  28. d.prevX = x
  29. d.prevY = y
  30. iq[i] = y
  31. }
  32. }
  33. func IQBalance(iq []complex64) {
  34. if len(iq) == 0 {
  35. return
  36. }
  37. var sumI, sumQ float64
  38. for _, v := range iq {
  39. sumI += float64(real(v))
  40. sumQ += float64(imag(v))
  41. }
  42. meanI := sumI / float64(len(iq))
  43. meanQ := sumQ / float64(len(iq))
  44. var varI, varQ, cov float64
  45. for _, v := range iq {
  46. i := float64(real(v)) - meanI
  47. q := float64(imag(v)) - meanQ
  48. varI += i * i
  49. varQ += q * q
  50. cov += i * q
  51. }
  52. n := float64(len(iq))
  53. varI /= n
  54. varQ /= n
  55. cov /= n
  56. if varI <= 0 || varQ <= 0 {
  57. return
  58. }
  59. gain := math.Sqrt(varI / varQ)
  60. phi := 0.5 * math.Atan2(2*cov, varI-varQ)
  61. cosP := math.Cos(phi)
  62. sinP := math.Sin(phi)
  63. for i := 0; i < len(iq); i++ {
  64. re := float64(real(iq[i])) - meanI
  65. im := (float64(imag(iq[i])) - meanQ) * gain
  66. i2 := re*cosP - im*sinP
  67. q2 := re*sinP + im*cosP
  68. iq[i] = complex(float32(i2+meanI), float32(q2+meanQ))
  69. }
  70. }