Search code examples
web-audio-apitonejs

Webaudio timing performance


The file below uses ToneJS to play a steam of steady 8th notes. According to the log of the timing, those 8th notes are precisely 0.25 seconds apart.

However, they don't sound even. The time intervals between the notes are distinctly irregular.

Why is it so? Is there anything that can be done about it? Or is this a performance limitation of Javascript/webaudio-api? I have tested it in Chrome, Firefox, and Safari, all to the same result.

Thanks for any information or suggestions about this!

<!DOCTYPE html>
<html>
<head>
<title>Tone Timing Tester</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.32/Tone.min.js"></script>
</head>

<body>
<button onclick="start()">Start</button>
<button onclick="stop()">Stop</button>
<form>
    <input id="bpm" type="number" value="120">
    <button type="button" onclick="submitBPM()">Enter BPM</button>
</form>

<script type="text/javascript">
    
    var synth = new Tone.Synth().toDestination()

    Tone.Transport.scheduleRepeat(function(time){
        console.log('time', time);
        synth.triggerAttackRelease('C4', '8n')
    }, "8n");

    async function start() {
        await Tone.start()
        Tone.Transport.start();
    }

    function stop() {
        Tone.Transport.stop();
    }

    function submitBPM() {
        var bpm = document.getElementById('bpm').value;
        Tone.Transport.bpm.value = bpm;
    }

</script>
</body>
</html>

Solution

  • For a scheduled triggerAttackRelease, you should pass the time value as the third argument.

    Tone.Transport.scheduleRepeat(function(time){
        console.log('time', time);
        synth.triggerAttackRelease('C4', '8n', time);
    }, "8n");
    

    Here's a codepen that contains the working code.