I have some JS cobbled together with the ToneJS library to toggle some sounds on/off.
function togglePlay() {
const status = Tone.Transport.state; // Is either 'started', 'stopped' or 'paused'
const element = document.getElementById("play-stop-toggle");
if (status == "started") {
element.innerText = "PLAY";
Tone.Transport.stop()
} else {
element.innerText = "STOP";
Tone.Transport.start()
}
document.querySelector('#status').textContent = status;
}
var filter = new Tone.Filter({
type: 'lowpass',
Q: 12
}).toMaster()
var fmOsc = new Tone.AMOscillator("Ab3", "sine", "square").toMaster()
var fmOsc2 = new Tone.AMOscillator("Cb3", "sine", "square").toMaster()
var fmOsc3 = new Tone.AMOscillator("Eb3", "sine", "square").toMaster()
var synth = new Tone.MembraneSynth().toMaster()
//create a loop
var loop = new Tone.Loop(function(time){
// synth.triggerAttackRelease("A1", "8n", time)
// fmOsc.start()
fmOsc2.start()
fmOsc3.start();
}, "4n")
//play the loop between 0-2m on the transport
loop.start(0)
// loop.start(0).stop('2m')
Inside the loop
I have a drum beat that I have commented out currently. When it was commented in, the togglePlay()
function would start and stop it as expected.
However, the fmOsc2
and fmOsc3
functions will start when I toggle start, but do not terminate when I toggle stop.
For reference, here is what the HTML side looks like: <div class="trackPlay" id="play-stop-toggle" onclick="togglePlay()">PLAY</div>
How can I get the fmOsc2
and fmOsc3
functions to toggle with the button state?
The Tone Transport is not meant to be used in this way, either for starting or stopping oscillators (it can start/stop oscillators, of course, but I don't think that it's doing what you want it to do) :-)
If you add a
console.log
within the function that you're passing toTone.Loop
, you will see that it's being called repeatedly i.e., you're callingfmOsc.start()
over and over again. (It does make sense to do the repeating drum beat in thatLoop
though)Calling
Tone.Transport.stop()
does not stop the oscillators -- it only stops theLoop
/ Transport function (i.e., the "time keeping"). The drum beat makes it obvious -- pressingStop
in your UI kills the drums, but the oscillators keep oscillating.The easiest / most direct (and only?) way of stopping the oscillators is to call
.stop()
on them: