| @@ -7,6 +7,7 @@ import ( | |||||
| "time" | "time" | ||||
| "sdr-visual-suite/internal/demod" | "sdr-visual-suite/internal/demod" | ||||
| "sdr-visual-suite/internal/demod/gpudemod" | |||||
| "sdr-visual-suite/internal/dsp" | "sdr-visual-suite/internal/dsp" | ||||
| ) | ) | ||||
| @@ -38,23 +39,55 @@ func (m *Manager) DemodLive(centerHz float64, bw float64, mode string, seconds i | |||||
| return nil, 0, errors.New("demodulator not found") | return nil, 0, errors.New("demodulator not found") | ||||
| } | } | ||||
| offset := centerHz - m.centerHz | offset := centerHz - m.centerHz | ||||
| shifted := dsp.FreqShift(segment, m.sampleRate, offset) | |||||
| if bw <= 0 { | if bw <= 0 { | ||||
| bw = 12000 | bw = 12000 | ||||
| } | } | ||||
| cutoff := bw / 2 | |||||
| if cutoff < 200 { | |||||
| cutoff = 200 | |||||
| var audio []float32 | |||||
| var inputRate int | |||||
| if m.gpuDemod != nil { | |||||
| var gpuMode gpudemod.DemodType | |||||
| var useGPU bool | |||||
| switch name { | |||||
| case "NFM": | |||||
| gpuMode, useGPU = gpudemod.DemodNFM, true | |||||
| case "WFM": | |||||
| gpuMode, useGPU = gpudemod.DemodWFM, true | |||||
| case "AM": | |||||
| gpuMode, useGPU = gpudemod.DemodAM, true | |||||
| case "USB": | |||||
| gpuMode, useGPU = gpudemod.DemodUSB, true | |||||
| case "LSB": | |||||
| gpuMode, useGPU = gpudemod.DemodLSB, true | |||||
| case "CW": | |||||
| gpuMode, useGPU = gpudemod.DemodCW, true | |||||
| } | |||||
| if useGPU { | |||||
| if gpuAudio, gpuRate, err := m.gpuDemod.DemodFused(segment, offset, bw, gpuMode); err == nil { | |||||
| audio = gpuAudio | |||||
| inputRate = gpuRate | |||||
| } else if gpuAudio, gpuRate, err := m.gpuDemod.Demod(segment, offset, bw, gpuMode); err == nil { | |||||
| audio = gpuAudio | |||||
| inputRate = gpuRate | |||||
| } | |||||
| } | |||||
| } | } | ||||
| 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 | |||||
| if audio == nil { | |||||
| 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) | |||||
| } | } | ||||
| dec := dsp.Decimate(filtered, decim) | |||||
| inputRate := m.sampleRate / decim | |||||
| audio := d.Demod(dec, inputRate) | |||||
| buf := &bytes.Buffer{} | buf := &bytes.Buffer{} | ||||
| if err := writeWAVTo(buf, audio, inputRate, d.Channels()); err != nil { | if err := writeWAVTo(buf, audio, inputRate, d.Channels()); err != nil { | ||||
| return nil, 0, err | return nil, 0, err | ||||