diff --git a/internal/recorder/cpu_audio.go b/internal/recorder/cpu_audio.go new file mode 100644 index 0000000..f8802fe --- /dev/null +++ b/internal/recorder/cpu_audio.go @@ -0,0 +1,25 @@ +package recorder + +import ( + "math" + + "sdr-visual-suite/internal/demod" + "sdr-visual-suite/internal/dsp" +) + +func demodAudioCPU(d demod.Demodulator, iq []complex64, sampleRate int, offset float64, bw float64) ([]float32, int) { + shifted := dsp.FreqShift(iq, sampleRate, offset) + cutoff := bw / 2 + if cutoff < 200 { + cutoff = 200 + } + taps := dsp.LowpassFIR(cutoff, sampleRate, 101) + filtered := dsp.ApplyFIR(shifted, taps) + decim := int(math.Round(float64(sampleRate) / float64(d.OutputSampleRate()))) + if decim < 1 { + decim = 1 + } + dec := dsp.Decimate(filtered, decim) + inputRate := sampleRate / decim + return d.Demod(dec, inputRate), inputRate +} diff --git a/internal/recorder/demod.go b/internal/recorder/demod.go index 6de889a..ffecb86 100644 --- a/internal/recorder/demod.go +++ b/internal/recorder/demod.go @@ -3,13 +3,11 @@ package recorder import ( "errors" "log" - "math" "path/filepath" "sdr-visual-suite/internal/classifier" "sdr-visual-suite/internal/demod" "sdr-visual-suite/internal/detector" - "sdr-visual-suite/internal/dsp" ) func (m *Manager) demodAndWrite(dir string, ev detector.Event, iq []complex64, files map[string]any) error { @@ -44,20 +42,7 @@ func (m *Manager) demodAndWrite(dir string, ev detector.Event, iq []complex64, f } else { log.Printf("gpudemod: CPU demod fallback used for event %d (%s)", ev.ID, name) } - shifted := dsp.FreqShift(iq, m.sampleRate, offset) - cutoff := bw / 2 - if cutoff < 200 { - cutoff = 200 - } - taps := dsp.LowpassFIR(cutoff, m.sampleRate, 101) - filtered := dsp.ApplyFIR(shifted, taps) - decim := int(math.Round(float64(m.sampleRate) / float64(d.OutputSampleRate()))) - if decim < 1 { - decim = 1 - } - dec := dsp.Decimate(filtered, decim) - inputRate = m.sampleRate / decim - audio = d.Demod(dec, inputRate) + audio, inputRate = demodAudioCPU(d, iq, m.sampleRate, offset, bw) } wav := filepath.Join(dir, "audio.wav") if err := writeWAV(wav, audio, inputRate, d.Channels()); err != nil { diff --git a/internal/recorder/demod_live.go b/internal/recorder/demod_live.go index e16d564..a2de3dc 100644 --- a/internal/recorder/demod_live.go +++ b/internal/recorder/demod_live.go @@ -4,11 +4,9 @@ import ( "bytes" "errors" "log" - "math" "time" "sdr-visual-suite/internal/demod" - "sdr-visual-suite/internal/dsp" ) // DemodLive demodulates a recent window and returns WAV bytes. @@ -61,20 +59,7 @@ func (m *Manager) DemodLive(centerHz float64, bw float64, mode string, seconds i } else { log.Printf("gpudemod: CPU live demod fallback used (%s)", name) } - shifted := dsp.FreqShift(segment, m.sampleRate, offset) - cutoff := bw / 2 - if cutoff < 200 { - cutoff = 200 - } - taps := dsp.LowpassFIR(cutoff, m.sampleRate, 101) - filtered := dsp.ApplyFIR(shifted, taps) - decim := int(math.Round(float64(m.sampleRate) / float64(d.OutputSampleRate()))) - if decim < 1 { - decim = 1 - } - dec := dsp.Decimate(filtered, decim) - inputRate = m.sampleRate / decim - audio = d.Demod(dec, inputRate) + audio, inputRate = demodAudioCPU(d, segment, m.sampleRate, offset, bw) } buf := &bytes.Buffer{} if err := writeWAVTo(buf, audio, inputRate, d.Channels()); err != nil {