Graph
Carrier
type
frequency: {{carrier.freq}} Hz
gain: {{carrier.gain.toFixed(2)}}
Modulator {{idx+1}}
type
frequency: {{mod.freq}} Hz
gain: {{mod.gain}}
const playButton = document.getElementById('play') const stopButton = document.getElementById('stop') const AC = new AudioContext() const masterVolume = AC.createGain() masterVolume.gain.value = 0.0 masterVolume.connect(AC.destination) const createAudioNode = ({type = 'sine', freq = 440, gain = 1.0} = {}) => { const osc = AC.createOscillator() osc.frequency.value = freq osc.type = type const _gain = AC.createGain() _gain.gain.value = gain osc.connect(_gain) return { osc, gain: _gain } } const carrier = createAudioNode(%%CARRIER%%) const modulators = [%%MODULATORS%%].map(m => createAudioNode(m)) const startSound = () => { if (modulators.length > 0) { modulators[0].gain.connect(carrier.osc.frequency) modulators.reduce((a, b) => { b.gain.connect(a.gain.gain) return b }) modulators.map(m => m.osc.start()) } carrier.osc.start() carrier.gain.connect(masterVolume) } startSound() const discardSound = () => { modulators.map(m => { m.gain.disconnect() m.osc.stop() }) carrier.osc.disconnect() carrier.osc.stop() } playButton.addEventListener('click', () => { if (AC.state === "suspended") { AC.resume() } if (masterVolume.gain.value === 0.0) { masterVolume.gain.setValueAtTime(0.01, AC.currentTime) } masterVolume.gain.exponentialRampToValueAtTime(1.0, AC.currentTime + 1) }) stopButton.addEventListener('click', () => { masterVolume.gain.exponentialRampToValueAtTime(0.001, AC.currentTime + 1) })