import * as Tone from 'tone'; import { AmbientType } from '@/types/audio'; export class AmbientLayer { private noise1: Tone.Noise | null = null; private noise2: Tone.Noise | null = null; private filter1: Tone.Filter | null = null; private filter2: Tone.Filter | null = null; private gain1: Tone.Gain | null = null; private gain2: Tone.Gain | null = null; private output: Tone.Gain; private lfo: Tone.LFO | null = null; private currentType: AmbientType = 'rain'; private isPlaying = false; private currentVolume: number = 0.4; private isMuted: boolean = false; constructor(destination: Tone.InputNode) { this.output = new Tone.Gain(this.currentVolume); this.output.connect(destination); this.createAmbient('rain'); } private createAmbient(type: AmbientType): void { this.noise1?.dispose(); this.noise2?.dispose(); this.filter1?.dispose(); this.filter2?.dispose(); this.gain1?.dispose(); this.gain2?.dispose(); this.lfo?.dispose(); const configs: Record = { rain: { noise1: { type: 'pink', filter: 3000, filterType: 'lowpass', gain: 0.15 }, noise2: { type: 'brown', filter: 1500, filterType: 'bandpass', gain: 0.1 }, lfoFreq: 0.1, }, vinyl: { noise1: { type: 'brown', filter: 2000, filterType: 'bandpass', gain: 0.12 }, noise2: { type: 'white', filter: 800, filterType: 'lowpass', gain: 0.05 }, lfoFreq: 0.05, }, nature: { noise1: { type: 'pink', filter: 4000, filterType: 'lowpass', gain: 0.1 }, noise2: { type: 'brown', filter: 500, filterType: 'lowpass', gain: 0.08 }, lfoFreq: 0.08, }, space: { noise1: { type: 'pink', filter: 1000, filterType: 'lowpass', gain: 0.12 }, noise2: { type: 'brown', filter: 300, filterType: 'lowpass', gain: 0.1 }, lfoFreq: 0.02, }, }; const config = configs[type]; this.noise1 = new Tone.Noise(config.noise1.type); this.filter1 = new Tone.Filter({ frequency: config.noise1.filter, type: config.noise1.filterType, }); this.gain1 = new Tone.Gain(config.noise1.gain); this.noise1.connect(this.filter1); this.filter1.connect(this.gain1); this.gain1.connect(this.output); this.noise2 = new Tone.Noise(config.noise2.type); this.filter2 = new Tone.Filter({ frequency: config.noise2.filter, type: config.noise2.filterType, }); this.gain2 = new Tone.Gain(config.noise2.gain); this.noise2.connect(this.filter2); this.filter2.connect(this.gain2); this.gain2.connect(this.output); this.lfo = new Tone.LFO({ frequency: config.lfoFreq, min: config.noise1.gain * 0.7, max: config.noise1.gain * 1.2, }); this.lfo.connect(this.gain1.gain); this.currentType = type; if (this.isPlaying) { this.noise1.start(); this.noise2.start(); this.lfo.start(); } } setInstrument(type: AmbientType): void { this.createAmbient(type); } start(): void { this.noise1?.start(); this.noise2?.start(); this.lfo?.start(); this.isPlaying = true; } stop(): void { this.noise1?.stop(); this.noise2?.stop(); this.lfo?.stop(); this.isPlaying = false; } setVolume(volume: number): void { this.currentVolume = volume; if (!this.isMuted) { this.output.gain.rampTo(volume, 0.1); } } mute(muted: boolean): void { this.isMuted = muted; this.output.gain.rampTo(muted ? 0 : this.currentVolume, 0.1); } dispose(): void { this.stop(); this.noise1?.dispose(); this.noise2?.dispose(); this.filter1?.dispose(); this.filter2?.dispose(); this.gain1?.dispose(); this.gain2?.dispose(); this.lfo?.dispose(); this.output.dispose(); } }