- TestAllClassesHaveConfig, TestFrequenciesInRange, TestFrequenciesUnique - TestHarmonicsNonEmpty, TestPanPositionsInRange - TestOscillatorAdvance, TestOscillatorPhaseWrap, TestOscillatorDistinctFreqs - TestEMAAmplitudeRise, TestEMAAmplitudeDecay, TestWhisperFloor, TestWhisperFloorNotSeenIsZero
89 lines
2.6 KiB
Go
89 lines
2.6 KiB
Go
package synth_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/netsynth/netsynth/synth"
|
|
)
|
|
|
|
func TestEMAAmplitudeRise(t *testing.T) {
|
|
cfg2 := synth.FreqConfig{
|
|
BaseHz: 440.0,
|
|
Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}},
|
|
Pan: 0.0,
|
|
}
|
|
layer := synth.NewLayer(cfg2, synth.SampleRate, 1.0)
|
|
|
|
// Force the layer to have been seen and set target to 1.0
|
|
layer.UpdateTarget(100, 100)
|
|
|
|
// After 1 second (SampleRate samples) with tau=1.0, currentAmp should be > 0.5
|
|
// EMA: after tau seconds, amplitude reaches ~63% of target
|
|
for i := 0; i < synth.SampleRate; i++ {
|
|
layer.AdvanceSample()
|
|
}
|
|
if layer.CurrentAmp() <= 0.5 {
|
|
t.Errorf("expected currentAmp > 0.5 after 1 second rise, got %.4f", layer.CurrentAmp())
|
|
}
|
|
}
|
|
|
|
func TestEMAAmplitudeDecay(t *testing.T) {
|
|
cfg := synth.FreqConfig{
|
|
BaseHz: 440.0,
|
|
Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}},
|
|
Pan: 0.0,
|
|
}
|
|
layer := synth.NewLayer(cfg, synth.SampleRate, 1.0)
|
|
|
|
// Set up: layer has been seen (currentAmp starts at 1.0) and target is whisper floor
|
|
// We'll manually prime by updating target with 100/100 first then re-route to whisper
|
|
layer.UpdateTarget(100, 100) // mark as seen, target=1.0
|
|
// Force currentAmp to 1.0 by running a few cycles at target 1.0
|
|
for i := 0; i < synth.SampleRate*3; i++ {
|
|
layer.AdvanceSample()
|
|
}
|
|
// Now decay: set count=0 (whisper floor kicks in)
|
|
layer.UpdateTarget(0, 100)
|
|
// After 1 second, currentAmp should be < 0.5
|
|
for i := 0; i < synth.SampleRate; i++ {
|
|
layer.AdvanceSample()
|
|
}
|
|
if layer.CurrentAmp() >= 0.5 {
|
|
t.Errorf("expected currentAmp < 0.5 after 1 second decay, got %.4f", layer.CurrentAmp())
|
|
}
|
|
}
|
|
|
|
func TestWhisperFloor(t *testing.T) {
|
|
cfg := synth.FreqConfig{
|
|
BaseHz: 440.0,
|
|
Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}},
|
|
Pan: 0.0,
|
|
}
|
|
layer := synth.NewLayer(cfg, synth.SampleRate, 1.0)
|
|
|
|
// Mark layer as seen by passing count=1, then set count=0
|
|
layer.UpdateTarget(1, 100)
|
|
layer.UpdateTarget(0, 100)
|
|
|
|
// Target should be whisper floor (not zero) because seen=true
|
|
if layer.TargetAmp() < synth.WhisperFloor {
|
|
t.Errorf("expected targetAmp >= WhisperFloor (%.2f) for seen layer at zero count, got %.4f",
|
|
synth.WhisperFloor, layer.TargetAmp())
|
|
}
|
|
}
|
|
|
|
func TestWhisperFloorNotSeenIsZero(t *testing.T) {
|
|
cfg := synth.FreqConfig{
|
|
BaseHz: 440.0,
|
|
Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}},
|
|
Pan: 0.0,
|
|
}
|
|
layer := synth.NewLayer(cfg, synth.SampleRate, 1.0)
|
|
|
|
// Never seen — UpdateTarget with zero count
|
|
layer.UpdateTarget(0, 100)
|
|
if layer.TargetAmp() != 0.0 {
|
|
t.Errorf("expected targetAmp == 0.0 for unseen layer, got %.4f", layer.TargetAmp())
|
|
}
|
|
}
|