WebAudio Oscillators
Live Code Example​
Oscillators Audio Example using WebAudio API only, no WebGPU.
Live Editor
function WebAudioOscillators() { const [playing, setPlaying] = useState(false); const [oscillator, setOscillator] = useState(null); const [freq, setFreq] = useState(440); const { volume, frequency, waveForm } = useControls({ waveForm: {options: ["sine", "triangle", "square", "sawtooth"]}, frequency: { value: 60, min: 0, max: 100, step: 0.0001, onChange: (v) => { const minIn = 0; const maxIn = 100; const minOut = Math.log(40); const maxOut = Math.log(3000); const scale = (maxOut - minOut) / (maxIn - minIn); setFreq(Math.exp(minOut + scale * (v - minIn))); }, }, string: {value: 'Hz', label: freq.toFixed(3), editable: false}, volume: { value: 0.15, min: 0.0, max: 1.0, step: 0.01, }, [playing ? "Stop Sound" : "Play Sound"]: button(() => { setPlaying(!playing) }, {order: -2}) }, [playing, freq]); useEffect(() => { if (playing) { setOscillator(new WebAudioOscillator()); // see class code below } else if (oscillator) { oscillator.stop(); setOscillator(null); } }, [playing]) useEffect(() => { if (oscillator) { oscillator.setVolume(volume); oscillator.setFrequency(freq); oscillator.setWaveForm(waveForm); } }, [volume, freq, waveForm, oscillator]) return ( <Leva fill flat oneLineLabels /> ) }
Result
Loading...
export default class WebAudioOscillator {
constructor() {
this.audioContext = new AudioContext();
this.oscillator = this.audioContext.createOscillator();
this.gain = this.audioContext.createGain();
this.oscillator.connect(this.gain);
this.gain.gain.value = 0;
this.gain.connect(this.audioContext.destination);
this.oscillator.start();
}
setVolume(volume) {
this.gain.gain.setTargetAtTime(volume, this.audioContext.currentTime, 0.01);
}
setFrequency(frequency) {
this.oscillator.frequency.setTargetAtTime(frequency, this.audioContext.currentTime, 0.01);
}
setWaveForm(waveForm) {
this.oscillator.type = waveForm;
}
stop() {
this.gain.gain.setTargetAtTime(0.0, this.audioContext.currentTime, 0.01);
setTimeout(() => {
this.oscillator.stop();
this.oscillator.disconnect();
this.gain.disconnect();
if (this.audioContext) this.audioContext.close();
if (this.audioContext) this.audioContext = undefined;
}, 100);
}
}