package synth_test import ( "testing" "github.com/netsynth/netsynth/synth" ) func TestEnvelopeAttackRise(t *testing.T) { // Sustained protocol (Bursty=false): slow 2s attack cfg := synth.FreqConfig{ BaseHz: 440.0, Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}}, Pan: 0.0, Group: "Web", } layer := synth.NewLayer(cfg, synth.SampleRate, 1.0) // Trigger envelope by sending traffic layer.UpdateTarget(100, 100) // After 2 seconds (full attack), envelope level should be significant for i := 0; i < synth.SampleRate*2; i++ { layer.AdvanceSample() } if layer.CurrentAmp() <= 0.5 { t.Errorf("expected envelope level > 0.5 after 2 second attack, got %.4f", layer.CurrentAmp()) } } func TestBurstyEnvelopeFastAttack(t *testing.T) { // Bursty protocol: fast 30ms attack cfg := synth.FreqConfig{ BaseHz: 440.0, Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}}, Pan: 0.0, Group: "Infrastructure", Bursty: true, } layer := synth.NewLayer(cfg, synth.SampleRate, 1.0) layer.UpdateTarget(100, 100) // After 100ms, bursty envelope should have peaked and be decaying for i := 0; i < synth.SampleRate/10; i++ { layer.AdvanceSample() } // Bursty: sustain=0, so it should already be fading // But it should have been triggered (not zero at peak) if !layer.Seen() { t.Error("expected layer.Seen() to be true after receiving traffic") } } func TestEnvelopeRelease(t *testing.T) { cfg := synth.FreqConfig{ BaseHz: 440.0, Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}}, Pan: 0.0, Group: "Web", } layer := synth.NewLayer(cfg, synth.SampleRate, 1.0) // Build up layer.UpdateTarget(100, 100) for i := 0; i < synth.SampleRate*3; i++ { layer.AdvanceSample() } peakAmp := layer.CurrentAmp() // Release: set count to 0 layer.UpdateTarget(0, 100) for i := 0; i < synth.SampleRate*5; i++ { layer.AdvanceSample() } // After 5 seconds of release (release time is 4s), should be much lower if layer.CurrentAmp() >= peakAmp*0.5 { t.Errorf("expected envelope to decay significantly, peak=%.4f, current=%.4f", peakAmp, layer.CurrentAmp()) } } func TestLayerNotSeenIssilent(t *testing.T) { cfg := synth.FreqConfig{ BaseHz: 440.0, Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}}, Pan: 0.0, Group: "Web", } layer := synth.NewLayer(cfg, synth.SampleRate, 1.0) // Never seen — UpdateTarget with zero count layer.UpdateTarget(0, 100) if layer.Seen() { t.Error("expected Seen()=false for layer that never had traffic") } // Advance some samples — output should be zero for i := 0; i < 100; i++ { sample := layer.AdvanceSample() if sample != 0 { t.Errorf("expected zero output for unseen layer, got %v at sample %d", sample, i) break } } } func TestLayerSeenFlag(t *testing.T) { cfg := synth.FreqConfig{ BaseHz: 440.0, Harmonics: []synth.HarmonicDef{{Ratio: 1, Amplitude: 1.0}}, Pan: 0.0, Group: "Web", } layer := synth.NewLayer(cfg, synth.SampleRate, 1.0) if layer.Seen() { t.Error("expected Seen()=false initially") } layer.UpdateTarget(1, 100) if !layer.Seen() { t.Error("expected Seen()=true after receiving traffic") } }