Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

70 řádky
1.6KB

  1. package recorder
  2. import (
  3. "bytes"
  4. "errors"
  5. "log"
  6. "time"
  7. "sdr-visual-suite/internal/demod"
  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. switch name {
  28. case "AM", "NFM", "WFM", "WFM_STEREO", "USB", "LSB", "CW":
  29. default:
  30. name = "NFM"
  31. }
  32. d := demod.Get(name)
  33. if d == nil {
  34. return nil, 0, errors.New("demodulator not found")
  35. }
  36. offset := centerHz - m.centerHz
  37. if bw <= 0 {
  38. bw = 12000
  39. }
  40. var audio []float32
  41. var inputRate int
  42. gpu := m.gpuEngine()
  43. if gpu != nil {
  44. gpuMode, useGPU := gpuModeFor(name)
  45. if useGPU {
  46. if gpuAudio, gpuRate, ok := tryGPUAudio(gpu, name, segment, offset, bw, gpuMode); ok {
  47. audio = gpuAudio
  48. inputRate = gpuRate
  49. }
  50. }
  51. }
  52. if audio == nil {
  53. if name == "WFM_STEREO" {
  54. log.Printf("gpudemod: WFM_STEREO live path using CPU stereo/RDS post-process")
  55. } else {
  56. log.Printf("gpudemod: CPU live demod fallback used (%s)", name)
  57. }
  58. audio, inputRate = demodAudioCPU(d, segment, m.sampleRate, offset, bw)
  59. }
  60. buf := &bytes.Buffer{}
  61. if err := writeWAVTo(buf, audio, inputRate, d.Channels()); err != nil {
  62. return nil, 0, err
  63. }
  64. return buf.Bytes(), inputRate, nil
  65. }