Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

64 строки
1.5KB

  1. package recorder
  2. import (
  3. "bytes"
  4. "errors"
  5. "math"
  6. "time"
  7. "sdr-visual-suite/internal/demod"
  8. "sdr-visual-suite/internal/dsp"
  9. )
  10. // DemodLive demodulates a recent window and returns WAV bytes.
  11. func (m *Manager) DemodLive(centerHz float64, bw float64, mode string, seconds int) ([]byte, int, error) {
  12. if m == nil || m.ring == nil {
  13. return nil, 0, errors.New("recorder not ready")
  14. }
  15. if seconds <= 0 {
  16. seconds = 2
  17. }
  18. end := time.Now()
  19. start := end.Add(-time.Duration(seconds) * time.Second)
  20. segment := m.ring.Slice(start, end)
  21. if len(segment) == 0 {
  22. return nil, 0, errors.New("no iq in ring")
  23. }
  24. name := mode
  25. if name == "" {
  26. name = "NFM"
  27. }
  28. switch name {
  29. case "AM", "NFM", "WFM", "WFM_STEREO", "USB", "LSB", "CW":
  30. default:
  31. name = "NFM"
  32. }
  33. d := demod.Get(name)
  34. if d == nil {
  35. return nil, 0, errors.New("demodulator not found")
  36. }
  37. offset := centerHz - m.centerHz
  38. shifted := dsp.FreqShift(segment, m.sampleRate, offset)
  39. if bw <= 0 {
  40. bw = 12000
  41. }
  42. cutoff := bw / 2
  43. if cutoff < 200 {
  44. cutoff = 200
  45. }
  46. taps := dsp.LowpassFIR(cutoff, m.sampleRate, 101)
  47. filtered := dsp.ApplyFIR(shifted, taps)
  48. decim := int(math.Round(float64(m.sampleRate) / float64(d.OutputSampleRate())))
  49. if decim < 1 {
  50. decim = 1
  51. }
  52. dec := dsp.Decimate(filtered, decim)
  53. inputRate := m.sampleRate / decim
  54. audio := d.Demod(dec, inputRate)
  55. buf := &bytes.Buffer{}
  56. if err := writeWAVTo(buf, audio, inputRate, d.Channels()); err != nil {
  57. return nil, 0, err
  58. }
  59. return buf.Bytes(), inputRate, nil
  60. }