Reputation: 23
Im coming from max/msp and trying to figure out the best practices of programming web audio in terms of optimising my code / getting better performance.
I'm reading about the fact that one cannot call .start(), then .stop() then .start() on an oscillator for optimisation reasons. I would like to know what the best design pattern is if I would like to make a simple 1 oscillator synth class.
I would like to instantiate the synth before I need to play it. This way I imagine I get the best timing, if I would like to play the synth at a later time, so the system don't have to create the oscillator / synth pattern, every time I hit 'play note'.
But it would be great to not use processing power on oscillators I don't hear because e.g. the amplitude envelope is not open.
Here is a simple synth, without amplitude envelope. How could I make a similar pattern, where I only use processing power when the synth is actually playing?
Best, Lasse
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>How to optimize CPU usage</title>
</head>
<body>
<a href="#" id="playButton">Play Note</a> <br><br>
<a href="#" id="stopButton">Stop Note</a>
<script>
class Synth {
constructor () {
this.context = new AudioContext();
this.osc = this.context.createOscillator();
this.osc.connect(this.context.destination);
}
play(freq) {
this.osc.frequency.value = freq;
this.osc.start(0);
}
stop() {
this.osc.stop(0);
}
}
let synth = new Synth();
const playButton = document.getElementById('playButton')
.addEventListener('click', () => {synth.play(440)});
const stopButton = document.getElementById('stopButton')
.addEventListener('click', () => {synth.stop()});
</script>
</body>
</html>
Upvotes: 2
Views: 328
Reputation: 2197
I think this is a little closer to what you want:
let context = new AudioContext();
class Synth {
constructor () {}
play(freq) {
this.osc = context.createOscillator();
this.osc.connect(context.destination);
this.osc.frequency.value = freq;
this.osc.start(0);
}
stop() {
this.osc.stop(0);
}
}
First of all, you only need one audioContext. You shouldn't be creating a new one each time the oscillator plays. As far as your concerns about the performance, I wouldn't worry too hard about that. Oscillators are designed to be cheap and disposable. It's fine to create them on the fly, and forget about them after they play once.
Upvotes: 1