Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

57 рядки
1.3KB

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