From c75b10c88efa359bc5d3ed08a71312826def1386 Mon Sep 17 00:00:00 2001 From: Jan Svabenik Date: Sun, 22 Mar 2026 23:39:03 +0100 Subject: [PATCH] Normalize broadcast FM signals to WFM_STEREO metadata --- cmd/sdrd/pipeline_runtime.go | 21 ++++++++++++++++++--- internal/pipeline/refiner.go | 20 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/cmd/sdrd/pipeline_runtime.go b/cmd/sdrd/pipeline_runtime.go index a7d2d41..c5e3c04 100644 --- a/cmd/sdrd/pipeline_runtime.go +++ b/cmd/sdrd/pipeline_runtime.go @@ -685,17 +685,32 @@ func (rt *dspRuntime) refineSignals(art *spectrumArtifacts, input pipeline.Refin decision := pipeline.DecideSignalAction(policy, ref.Candidate, cls) decisions = append(decisions, decision) if cls != nil { + if cls.ModType == classifier.ClassWFM { + cls.ModType = classifier.ClassWFMStereo + signals[i].PlaybackMode = string(classifier.ClassWFMStereo) + signals[i].DemodName = string(classifier.ClassWFMStereo) + signals[i].StereoState = "searching" + } pll := classifier.PLLResult{} if i < len(snips) && snips[i] != nil && len(snips[i]) > 256 { pll = classifier.EstimateExactFrequency(snips[i], snipRate, signals[i].CenterHz, cls.ModType) cls.PLL = &pll signals[i].PLL = &pll - if cls.ModType == classifier.ClassWFM && pll.Stereo { - cls.ModType = classifier.ClassWFMStereo + if cls.ModType == classifier.ClassWFMStereo { + if pll.Stereo { + signals[i].StereoState = "locked" + } else if signals[i].StereoState == "" { + signals[i].StereoState = "searching" + } + signals[i].PlaybackMode = string(classifier.ClassWFMStereo) + signals[i].DemodName = string(classifier.ClassWFMStereo) } } - if (cls.ModType == classifier.ClassWFM || cls.ModType == classifier.ClassWFMStereo) && rec != nil { + if cls.ModType == classifier.ClassWFMStereo && rec != nil { rt.updateRDS(art.now, rec, &signals[i], cls) + if signals[i].PLL != nil && signals[i].PLL.RDSStation != "" { + signals[i].StereoState = "locked" + } } } } diff --git a/internal/pipeline/refiner.go b/internal/pipeline/refiner.go index ea405f2..e12fe1b 100644 --- a/internal/pipeline/refiner.go +++ b/internal/pipeline/refiner.go @@ -36,12 +36,28 @@ func RefineCandidates(candidates []Candidate, windows []RefinementWindow, spectr BWHz: sig.BWHz, }, spectrum, sampleRate, fftSize, snip, mode) sig.Class = cls + if cls != nil && cls.ModType == classifier.ClassWFM { + cls.ModType = classifier.ClassWFMStereo + sig.PlaybackMode = string(classifier.ClassWFMStereo) + sig.DemodName = string(classifier.ClassWFMStereo) + if sig.PLL != nil && sig.PLL.Stereo { + sig.StereoState = "locked" + } else { + sig.StereoState = "searching" + } + } if cls != nil && snip != nil && len(snip) > 256 { pll := classifier.EstimateExactFrequency(snip, snipRate, sig.CenterHz, cls.ModType) cls.PLL = &pll sig.PLL = &pll - if cls.ModType == classifier.ClassWFM && pll.Stereo { - cls.ModType = classifier.ClassWFMStereo + if cls.ModType == classifier.ClassWFMStereo { + if pll.Stereo { + sig.StereoState = "locked" + } else if sig.StereoState == "" { + sig.StereoState = "searching" + } + sig.PlaybackMode = string(classifier.ClassWFMStereo) + sig.DemodName = string(classifier.ClassWFMStereo) } } var window RefinementWindow