39 lines
948 B
Go
39 lines
948 B
Go
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].
|
||
|
|
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 += 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
|
||
|
|
}
|