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 -= 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. type PilotGenerator struct { Oscillator Level float64 } // NewPilotGenerator constructs a pilot tone generator for the given sample rate and level. func NewPilotGenerator(sampleRate, level float64) PilotGenerator { return PilotGenerator{ Oscillator: Oscillator{Frequency: 19000, SampleRate: sampleRate}, Level: level, } } // Sample returns the next pilot sample. func (p *PilotGenerator) Sample() float64 { return p.Level * p.Oscillator.Tick() }