diff --git a/cmd/sdrd/dsp_loop.go b/cmd/sdrd/dsp_loop.go index 8d5e9ad..eb3e809 100644 --- a/cmd/sdrd/dsp_loop.go +++ b/cmd/sdrd/dsp_loop.go @@ -177,8 +177,12 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det * thresholds := det.LastThresholds() noiseFloor := det.LastNoiseFloor() if len(iq) > 0 { + snips := extractSignalIQBatch(iq, cfg.SampleRate, cfg.CenterHz, signals) for i := range signals { - snip := extractSignalIQ(iq, cfg.SampleRate, cfg.CenterHz, signals[i].CenterHz, signals[i].BWHz) + var snip []complex64 + if i < len(snips) { + snip = snips[i] + } cls := classifier.Classify(classifier.SignalInput{FirstBin: signals[i].FirstBin, LastBin: signals[i].LastBin, SNRDb: signals[i].SNRDb}, spectrum, cfg.SampleRate, cfg.FFTSize, snip) signals[i].Class = cls } diff --git a/cmd/sdrd/helpers.go b/cmd/sdrd/helpers.go index de3a74c..8f9fdcc 100644 --- a/cmd/sdrd/helpers.go +++ b/cmd/sdrd/helpers.go @@ -7,6 +7,7 @@ import ( "sdr-visual-suite/internal/config" "sdr-visual-suite/internal/demod/gpudemod" + "sdr-visual-suite/internal/detector" "sdr-visual-suite/internal/dsp" ) @@ -57,34 +58,56 @@ func extractSignalIQ(iq []complex64, sampleRate int, centerHz float64, sigHz flo if len(iq) == 0 || sampleRate <= 0 { return nil } - offset := sigHz - centerHz + results := extractSignalIQBatch(iq, sampleRate, centerHz, []detector.Signal{{CenterHz: sigHz, BWHz: bwHz}}) + if len(results) == 0 { + return nil + } + return results[0] +} + +func extractSignalIQBatch(iq []complex64, sampleRate int, centerHz float64, signals []detector.Signal) [][]complex64 { + out := make([][]complex64, len(signals)) + if len(iq) == 0 || sampleRate <= 0 || len(signals) == 0 { + return out + } decimTarget := 200000 if decimTarget <= 0 { decimTarget = sampleRate } + + var eng *gpudemod.Engine if gpudemod.Available() { - if eng, err := gpudemod.New(len(iq), sampleRate); err == nil { + if gpuEng, err := gpudemod.New(len(iq), sampleRate); err == nil { + eng = gpuEng defer eng.Close() - if out, _, err := eng.ShiftFilterDecimate(iq, offset, bwHz, decimTarget); err == nil && len(out) > 0 { - return out - } } } - shifted := dsp.FreqShift(iq, sampleRate, offset) - cutoff := bwHz / 2 - if cutoff < 200 { - cutoff = 200 - } - if cutoff > float64(sampleRate)/2-1 { - cutoff = float64(sampleRate)/2 - 1 - } - taps := dsp.LowpassFIR(cutoff, sampleRate, 101) - filtered := dsp.ApplyFIR(shifted, taps) - decim := sampleRate / decimTarget - if decim < 1 { - decim = 1 + + for i, sig := range signals { + offset := sig.CenterHz - centerHz + if eng != nil { + if gpuOut, _, err := eng.ShiftFilterDecimate(iq, offset, sig.BWHz, decimTarget); err == nil && len(gpuOut) > 0 { + out[i] = gpuOut + continue + } + } + shifted := dsp.FreqShift(iq, sampleRate, offset) + cutoff := sig.BWHz / 2 + if cutoff < 200 { + cutoff = 200 + } + if cutoff > float64(sampleRate)/2-1 { + cutoff = float64(sampleRate)/2 - 1 + } + taps := dsp.LowpassFIR(cutoff, sampleRate, 101) + filtered := dsp.ApplyFIR(shifted, taps) + decim := sampleRate / decimTarget + if decim < 1 { + decim = 1 + } + out[i] = dsp.Decimate(filtered, decim) } - return dsp.Decimate(filtered, decim) + return out } func parseSince(raw string) (time.Time, error) {