Wideband autonomous SDR analysis engine forked from sdr-visual-suite
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

70 satır
1.5KB

  1. package classifier
  2. import (
  3. "math"
  4. )
  5. // ExtractTemporalFeatures computes simple time-domain features from IQ.
  6. func ExtractTemporalFeatures(iq []complex64) (envVar float64, zeroCross float64, instFreqStd float64, crest float64) {
  7. if len(iq) == 0 {
  8. return 0, 0, 0, 0
  9. }
  10. env := make([]float64, len(iq))
  11. var mean, rms float64
  12. for i, v := range iq {
  13. a := math.Hypot(float64(real(v)), float64(imag(v)))
  14. env[i] = a
  15. mean += a
  16. rms += a * a
  17. }
  18. mean /= float64(len(iq))
  19. rms = math.Sqrt(rms / float64(len(iq)))
  20. // env variance
  21. var sumVar float64
  22. for _, v := range env {
  23. d := v - mean
  24. sumVar += d * d
  25. }
  26. envVar = sumVar / float64(len(iq))
  27. if rms > 0 {
  28. crest = maxFloat(env) / rms
  29. }
  30. // zero-crossing on real part
  31. zc := 0
  32. for i := 1; i < len(iq); i++ {
  33. p := real(iq[i-1])
  34. c := real(iq[i])
  35. if (p >= 0 && c < 0) || (p < 0 && c >= 0) {
  36. zc++
  37. }
  38. }
  39. zeroCross = float64(zc) / float64(len(iq))
  40. // instantaneous frequency std
  41. if len(iq) > 1 {
  42. var sum, sumSq float64
  43. for i := 1; i < len(iq); i++ {
  44. p := iq[i-1]
  45. c := iq[i]
  46. num := float64(real(p))*float64(imag(c)) - float64(imag(p))*float64(real(c))
  47. den := float64(real(p))*float64(real(c)) + float64(imag(p))*float64(imag(c))
  48. v := math.Atan2(num, den)
  49. sum += v
  50. sumSq += v * v
  51. }
  52. n := float64(len(iq) - 1)
  53. mean := sum / n
  54. instFreqStd = math.Sqrt(sumSq/n - mean*mean)
  55. }
  56. return
  57. }
  58. func maxFloat(vals []float64) float64 {
  59. m := vals[0]
  60. for _, v := range vals {
  61. if v > m {
  62. m = v
  63. }
  64. }
  65. return m
  66. }