Wideband autonomous SDR analysis engine forked from sdr-visual-suite
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

67 wiersze
1.4KB

  1. package dsp
  2. import "math"
  3. // LowpassFIR returns windowed-sinc lowpass taps (Hann).
  4. func LowpassFIR(cutoffHz float64, sampleRate int, taps int) []float64 {
  5. if taps%2 == 0 {
  6. taps++
  7. }
  8. out := make([]float64, taps)
  9. fc := cutoffHz / float64(sampleRate)
  10. if fc <= 0 {
  11. return out
  12. }
  13. m := float64(taps-1) / 2.0
  14. for n := 0; n < taps; n++ {
  15. x := float64(n) - m
  16. var sinc float64
  17. if x == 0 {
  18. sinc = 2 * fc
  19. } else {
  20. sinc = math.Sin(2*math.Pi*fc*x) / (math.Pi * x)
  21. }
  22. w := 0.5 * (1 - math.Cos(2*math.Pi*float64(n)/float64(taps-1)))
  23. out[n] = float64(sinc) * w
  24. }
  25. return out
  26. }
  27. // ApplyFIR applies real FIR taps to complex IQ.
  28. func ApplyFIR(iq []complex64, taps []float64) []complex64 {
  29. if len(iq) == 0 || len(taps) == 0 {
  30. return nil
  31. }
  32. out := make([]complex64, len(iq))
  33. n := len(taps)
  34. for i := 0; i < len(iq); i++ {
  35. var accR, accI float64
  36. for k := 0; k < n; k++ {
  37. idx := i - k
  38. if idx < 0 {
  39. break
  40. }
  41. v := iq[idx]
  42. w := taps[k]
  43. accR += float64(real(v)) * w
  44. accI += float64(imag(v)) * w
  45. }
  46. out[i] = complex(float32(accR), float32(accI))
  47. }
  48. return out
  49. }
  50. // Decimate keeps every nth sample.
  51. func Decimate(iq []complex64, factor int) []complex64 {
  52. if factor <= 1 {
  53. out := make([]complex64, len(iq))
  54. copy(out, iq)
  55. return out
  56. }
  57. out := make([]complex64, 0, len(iq)/factor+1)
  58. for i := 0; i < len(iq); i += factor {
  59. out = append(out, iq[i])
  60. }
  61. return out
  62. }