The Web Audio API's linearRampToValueAtTime doesn't work on playbackRate

As a public service, I’m explicitly stating that linearRampToValueAtTime does not work on an AudioBufferSourceNode’s playbackRate, as of February 24, 2023, on Firefox. It does work on Chrome. I’ve included a simple demo here.

Loading sample…

If you click “Play sample with linearRampToValueAtTime”, the browser will play a flute sample and run code that attempts to change the playbackRate of the AudioBufferSourceNode from 1.0 to 2.0 over the course of four seconds. It should sound something like a slide whistle, but on Firefox, it just plays at a normal rate and pitch for four seconds, then jumps up to the target playbackRate, an octave up. Here’s what that code looks like:

    ctx.currentTime + 4

However, if you click “Play sample with homemade ramp”, which doesn’t use linearRampToValueAtTime and instead sets playbackRate.value during a series of callbacks from requestAnimationFrame, then it slides up as expected in both Firefox and Chrome. Here’s what that code looks like, which you can use as a polyfill:

// Warning: cancelScheduledValues doesn't cancel this.
function homemadeLinearRamp({ param, targetVal, ctx, durationSeconds }) {
  const startTime = ctx.currentTime;
  const startVal = param.value;
  const valDelta = targetVal - startVal;

  function updateParam() {
    const elapsed = ctx.currentTime - startTime;
    const progress = elapsed / durationSeconds;
    param.value = startVal + progress * valDelta;
    if (progress < 1) {

(Here, param should be the playbackRate instance from your AudioBufferSourceNode. ctx should be your AudioContext.)

You can use View Source to see the code in context.

Update, 2023-02-27: Same situation in Firefox with StereoPannerNodes and the pan property.

Not mad

I’m not writing to complain about Firefox’s implementation! I know that team has dev resource issues.

I wrote this because I was in this situation in which I was working on a generative music piece which has gotten complex, and I was trying unsuccessfully to use this API method. I was hoping the internet would tell me definitively whether I was using it wrong or if it just didn’t work.

It did not tell me anything conclusive.

Searching the web just seems bad lately, both on Duck Duck Go and Google, and the closest I could get is a Stack Overflow post from six years ago about setValueCurveAtTime not working on playbackRate on Firefox.

So, I had to take the time to test it for myself, which I loathed having to do because I have a lot to do. But now, you don’t have to! I hope this helps, Internet Searcher of the future!