How to play a pitched sound n times?

1 week ago 5
ARTICLE AD BOX

I'm making a game and am using WebAudio API for audio. I want to play a given sound exactly n times, with a different pitch than normal.

As long as I don't change the pitch, i.e. keep playbackRate = 1.0, everything is working fine. However, with a different pitch, be it lower/slower (<1) or higher/faster (>1), I'm facing a different behavior between browser, Firefox against all others.

With Firefox, it works like I want. Regardless of the pitch, the sound is always played exactly as many times as wanted. With other browsers (Chrome/Safari/Edge), the sound is cut in the middle, and isn't played the wanted number of times. If the pitch is higher, it is played more times than desired, and with lower pitch, it's played less times.

The problem is the interpretation of the third parameter of AudioBufferSource.start(), the duration the source has to be played. Firefox takes the playbackRate into account and adjust the real duration accordingly, while other browsers don't do that, they take the duration as a fixed value which doesn't depend on playbackRate.

Here's a quick demo, and the relevant part of the code:

let source = context.createBufferSource(); source.buffer = buffer; source.loop = true; source.playbackRate.setValueAtTime(pitch, context.currentTime); source.connect(context.destination); source.start(context.currentTime, 0, count * buffer.duration);

Fixing the problem for Chrome/Safari/Edge is in fact easy, I just need to adjust the duration depending on the playbackRate myself. But then it becomes broken with Firefox.

source.start(context.currentTime, 0, count * buffer.duration / pitch);

So then my questions are as follows:

Am I doing something completely wrong ?

Am I in fact using non-standard / unspecified features ?

If everything is correct standard-wise, who has actually the correct behavior ? Firefox, or other browsers ?

If I'm indeed using something non-standard, what should I do instead to make it work in all browsers ?

Is there a solution to achieve what I want without resorting to browser detection ?

Read Entire Article