package dsp import "math" // Oscillator produces a sine wave at a configured frequency and sample rate. type Oscillator struct { Frequency float64 SampleRate float64 phase float64 } // Tick advances the oscillator by one sample and returns the current sine value. func (o *Oscillator) Tick() float64 { if o.SampleRate <= 0 || o.Frequency == 0 { return 0 } value := math.Sin(2 * math.Pi * o.phase) step := o.Frequency / o.SampleRate o.phase += step if o.phase >= 1 || o.phase < 0 { o.phase -= math.Floor(o.phase) } return value } // Reset brings the phase back to zero. func (o *Oscillator) Reset() { o.phase = 0 } // Phase returns the current phase of the oscillator in [0, 1). func (o *Oscillator) Phase() float64 { return o.phase } // PilotGenerator emits the 19 kHz pilot tone required by FM stereo. // Output is unity-normalized (peak ±1.0). The caller controls the // actual injection level via the combiner gain. type PilotGenerator struct { Oscillator } // NewPilotGenerator constructs a pilot tone generator for the given sample rate. func NewPilotGenerator(sampleRate float64) PilotGenerator { return PilotGenerator{ Oscillator: Oscillator{Frequency: 19000, SampleRate: sampleRate}, } } // Sample returns the next pilot sample (unity amplitude). func (p *PilotGenerator) Sample() float64 { return p.Oscillator.Tick() }