|
|
|
@@ -205,6 +205,95 @@ func (g *Generator) RDSEncoder() *rds.Encoder { |
|
|
|
return g.rdsEnc |
|
|
|
} |
|
|
|
|
|
|
|
func (g *Generator) resetSource() { |
|
|
|
rawSource, _ := g.sourceFor(g.sampleRate) |
|
|
|
g.source = NewPreEmphasizedSource(rawSource, g.cfg.FM.PreEmphasisTauUS, g.sampleRate, g.cfg.Audio.Gain) |
|
|
|
} |
|
|
|
|
|
|
|
func (g *Generator) resetRDS2Encoder() { |
|
|
|
if !g.cfg.RDS.Enabled || !g.cfg.RDS.RDS2Enabled { |
|
|
|
g.rds2Enc = nil |
|
|
|
return |
|
|
|
} |
|
|
|
g.rds2Enc = rds.NewRDS2Encoder(g.sampleRate) |
|
|
|
g.rds2Enc.Enable(true) |
|
|
|
if g.cfg.RDS.StationLogoPath != "" { |
|
|
|
if err := g.rds2Enc.LoadLogo(g.cfg.RDS.StationLogoPath); err != nil { |
|
|
|
log.Printf("rds2: failed to load station logo: %v", err) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Reset clears stateful DSP/runtime state so the next run starts from a clean baseline |
|
|
|
// without changing the current live parameters or feature enablement. |
|
|
|
func (g *Generator) Reset() { |
|
|
|
if !g.initialized { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
g.resetSource() |
|
|
|
|
|
|
|
mode := g.appliedStereoMode |
|
|
|
if lp := g.liveParams.Load(); lp != nil { |
|
|
|
mode = canonicalStereoMode(lp.StereoMode) |
|
|
|
} |
|
|
|
g.stereoEncoder = stereo.NewStereoEncoder(g.sampleRate) |
|
|
|
g.stereoEncoder.SetMode(stereo.ParseMode(mode), g.sampleRate) |
|
|
|
g.appliedStereoMode = mode |
|
|
|
|
|
|
|
if g.rdsEnc != nil { |
|
|
|
g.rdsEnc.Reset() |
|
|
|
} |
|
|
|
g.resetRDS2Encoder() |
|
|
|
|
|
|
|
if g.audioLPF_L != nil { |
|
|
|
g.audioLPF_L.Reset() |
|
|
|
} |
|
|
|
if g.audioLPF_R != nil { |
|
|
|
g.audioLPF_R.Reset() |
|
|
|
} |
|
|
|
if g.pilotNotchL != nil { |
|
|
|
g.pilotNotchL.Reset() |
|
|
|
} |
|
|
|
if g.pilotNotchR != nil { |
|
|
|
g.pilotNotchR.Reset() |
|
|
|
} |
|
|
|
if g.limiter != nil { |
|
|
|
g.limiter.Reset() |
|
|
|
} |
|
|
|
if g.cleanupLPF_L != nil { |
|
|
|
g.cleanupLPF_L.Reset() |
|
|
|
} |
|
|
|
if g.cleanupLPF_R != nil { |
|
|
|
g.cleanupLPF_R.Reset() |
|
|
|
} |
|
|
|
if g.mpxNotch19 != nil { |
|
|
|
g.mpxNotch19.Reset() |
|
|
|
} |
|
|
|
if g.mpxNotch57 != nil { |
|
|
|
g.mpxNotch57.Reset() |
|
|
|
} |
|
|
|
if g.bs412 != nil { |
|
|
|
g.bs412.Reset() |
|
|
|
} |
|
|
|
if g.compositeClip != nil { |
|
|
|
g.compositeClip.Reset() |
|
|
|
} |
|
|
|
if g.fmMod != nil { |
|
|
|
g.fmMod.Reset() |
|
|
|
} |
|
|
|
|
|
|
|
if g.watermarkEnabled { |
|
|
|
g.stftEmbedder = watermark.NewSTFTEmbedder(g.watermarkKey) |
|
|
|
g.wmDecimLPF = dsp.NewLPF4(5500, g.sampleRate) |
|
|
|
g.wmInterpLPF = dsp.NewLPF4(5500, g.sampleRate) |
|
|
|
} else { |
|
|
|
g.stftEmbedder = nil |
|
|
|
g.wmDecimLPF = nil |
|
|
|
g.wmInterpLPF = nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (g *Generator) init() { |
|
|
|
if g.initialized { |
|
|
|
return |
|
|
|
@@ -268,15 +357,7 @@ func (g *Generator) init() { |
|
|
|
}) |
|
|
|
|
|
|
|
// RDS2: additional subcarriers (66.5, 71.25, 76 kHz) |
|
|
|
if g.cfg.RDS.RDS2Enabled { |
|
|
|
g.rds2Enc = rds.NewRDS2Encoder(g.sampleRate) |
|
|
|
g.rds2Enc.Enable(true) |
|
|
|
if g.cfg.RDS.StationLogoPath != "" { |
|
|
|
if err := g.rds2Enc.LoadLogo(g.cfg.RDS.StationLogoPath); err != nil { |
|
|
|
log.Printf("rds2: failed to load station logo: %v", err) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
g.resetRDS2Encoder() |
|
|
|
} |
|
|
|
ceiling := g.cfg.FM.LimiterCeiling |
|
|
|
if ceiling <= 0 { |
|
|
|
|