import * as Tone from 'tone'; export class AmbientLayer { private rainNoise: Tone.Noise; private vinylNoise: Tone.Noise; private rainFilter: Tone.Filter; private vinylFilter: Tone.Filter; private rainGain: Tone.Gain; private vinylGain: Tone.Gain; private output: Tone.Gain; private lfo: Tone.LFO; constructor(destination: Tone.InputNode) { this.output = new Tone.Gain(0.4); // Rain sound - filtered pink noise this.rainNoise = new Tone.Noise('pink'); this.rainFilter = new Tone.Filter({ frequency: 3000, type: 'lowpass', rolloff: -24, }); this.rainGain = new Tone.Gain(0.15); // Vinyl crackle - filtered brown noise with modulation this.vinylNoise = new Tone.Noise('brown'); this.vinylFilter = new Tone.Filter({ frequency: 1500, type: 'bandpass', Q: 2, }); this.vinylGain = new Tone.Gain(0.1); // LFO for subtle rain intensity variation this.lfo = new Tone.LFO({ frequency: 0.1, min: 0.1, max: 0.2, }); this.lfo.connect(this.rainGain.gain); // Chain rain: noise -> filter -> gain -> output this.rainNoise.connect(this.rainFilter); this.rainFilter.connect(this.rainGain); this.rainGain.connect(this.output); // Chain vinyl: noise -> filter -> gain -> output this.vinylNoise.connect(this.vinylFilter); this.vinylFilter.connect(this.vinylGain); this.vinylGain.connect(this.output); // Output to destination this.output.connect(destination); } start(): void { this.rainNoise.start(); this.vinylNoise.start(); this.lfo.start(); } stop(): void { this.rainNoise.stop(); this.vinylNoise.stop(); this.lfo.stop(); } setVolume(volume: number): void { this.output.gain.rampTo(volume, 0.1); } mute(muted: boolean): void { this.output.gain.rampTo(muted ? 0 : 0.4, 0.1); } setRainIntensity(intensity: number): void { this.rainGain.gain.rampTo(intensity * 0.2, 0.5); } setVinylIntensity(intensity: number): void { this.vinylGain.gain.rampTo(intensity * 0.15, 0.5); } dispose(): void { this.rainNoise.stop(); this.vinylNoise.stop(); this.lfo.stop(); this.rainNoise.dispose(); this.vinylNoise.dispose(); this.rainFilter.dispose(); this.vinylFilter.dispose(); this.rainGain.dispose(); this.vinylGain.dispose(); this.lfo.dispose(); this.output.dispose(); } }