Files

42 lines
1.2 KiB
Go
Raw Permalink Normal View History

package synth
import "math"
// Oscillator is a phase-accumulator oscillator that generates additive sine waveforms.
type Oscillator struct {
phase float64
freq float64
sr float64
}
// NewOscillator creates an oscillator at the given frequency and sample rate.
func NewOscillator(freq float64, sampleRate int) *Oscillator {
return &Oscillator{freq: freq, sr: float64(sampleRate)}
}
// Advance returns one sample: fundamental + harmonics summed and normalized to [-1, 1].
// Normalization uses sum of absolute amplitudes so that alternating-sign harmonic series
// (e.g. triangle wave) are correctly bounded. Without math.Abs, signed cancellation
// produces an inflated normalization denominator that causes output to exceed [-1, 1].
func (o *Oscillator) Advance(harmonics []HarmonicDef) float64 {
sum := 0.0
totalWeight := 0.0
for _, h := range harmonics {
sum += h.Amplitude * math.Sin(2*math.Pi*o.phase*float64(h.Ratio))
totalWeight += math.Abs(h.Amplitude)
}
o.phase += o.freq / o.sr
if o.phase >= 1.0 {
o.phase -= 1.0
}
if totalWeight > 0 {
return sum / totalWeight
}
return 0
}
// Phase returns the current phase (for testing).
func (o *Oscillator) Phase() float64 {
return o.phase
}