3
votes

I'm quite new to the Web Audio API and I'm trying to change the playback rate of a sound without having to stop/ pause it. Currently, this piece of code works (TypeScript): I load the sound like this:

private init(): void {
    const tmpLoop: Audio = this.engineLoop = new Audio(this.cameraManager.listener);
    const idleLoader: AudioLoader = new AudioLoader();
    idleLoader.load("../../assets/sounds/engine.ogg",
        (buffer: AudioBuffer) => {
            tmpLoop.setBuffer(buffer);
            tmpLoop.setLoop(true);
            tmpLoop.setVolume(0.5);
        },
        () => { },
        () => { });

}

And then every frame I change playbackRate like this:

public modifyPlayBackSpeed(rpm: number): void {
    if(rpm > 800)
    {
        this.engineLoop.pause();
        this.engineLoop.playbackRate = (2/4700)*(rpm-800)+1;
        this.engineLoop.play();
    }

But it's nowhere near as fluid as I would like, since it keeps clipping the sample every frame.

I would like the sound to play continuously while changing playback rate, like this engine sound.

2
I'm not sure what engine this is? It's not writing to the Web Audio API. Do you have a full running example to point to? - cwilso
We are using THREE.js (hence the listener linked to the camera). I couldn't succeed using audio nodes from translating JavaScript examples, but I think my solution lies there. I either need a way to load the sounds faster or actually resume the sound at the same place it stopped. - Thierry Dubois
Hmm. It looks like THREE.js doesn't directly expose the underlying web audio bits, which is a shame. But do you really have to pause() and play() around changing the playbackRate? Web Audio lets you change the playback rate while a source is playing, and a quick look at the THREE.js code (github.com/mrdoob/three.js/blob/master/src/audio/Audio.js#L223) says it would change it live, too. (You can't set it smoothly, e.g. setTargetAtTime() on the playback rate, but that should still work pretty well). - cwilso
I found the solution: I had to use this.engineLoop.setPlaybackRate((2/4700)*(rpm-800)+1); And it worked! - Thierry Dubois

2 Answers

1
votes

You can use SoundTouchJS for this. Documentation is a little spotty, so you'll have to look at the source, but there's a 'rate' property you can adjust that will slow/speedup the playback rate of your audio source node. Provide a slider or something in your ui and attach it's value to the 'rate' property in an onChange event.

1
votes

The ThreeJS doc contains : Audio.setPlaybackRate() , which does exactly what you need !

(and it's pretty smooth, I ear no clipping from what I just tested)