simple-reversible-audio-buffer-source-node v0.0.3
simple-reversible-audio-buffer-source-node
This package implements a ReversibleAudioBufferSourceNode
class that allows for playback of an AudioBuffer
with a negative playback rate. This is useful starting point for many DJ and audio processing applications, where reverse playback is a requirement.
To use this class, clone this repo and spin up our dev server, or install this via npm i simple-reversible-audio-buffer-source-node
and try the following example in a browser environment:
import { ReversibleAudioBufferSourceNode } from "simple-reversible-audio-buffer-source-node";
(async () => {
// Pull down a local file and initialize an audio context.
const audioContext = new AudioContext();
const response = await fetch("/example.mp3");
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
const reversibleAudioBufferSourceNode = new ReversibleAudioBufferSourceNode(
audioContext,
);
reversibleAudioBufferSourceNode.buffer = audioBuffer;
reversibleAudioBufferSourceNode.connect(audioContext.destination);
reversibleAudioBufferSourceNode.start();
reversibleAudioBufferSourceNode.onended((direction) => {
console.log(`node ended in: ${direction}`);
});
// Wait for a few seconds...
await new Promise((resolve) => setTimeout(resolve, 3_000));
// Playback in reverse.
// You should hear the last three seconds (or so) played backwards.
reversibleAudioBufferSourceNode.playbackRate(-1);
})();
Performance considerations
This package specifically deals with AudioBuffer
s, and can quickly get computationally expensive to use when working with large buffers. It's important to note that AudioBuffer
s in general were designed to work with small audio snippets less than 45s in length.
That said, this package does leave some room for a few performance optimizations, noted below.
Pre-process reversed audio buffer
A user can supply the reversed audio buffer by setting the ReversibleAudioBufferSourceNode
's buffer with a pre-processed reversed buffer (e.g. — created offline via ffmpeg or reversed in a worker environment) like so:
const reversibleAudioBufferSourceNode = new ReversibleAudioBufferSourceNode(
audioContext,
);
reversibleAudioBufferSourceNode.buffer = {
forward: audioBuffer,
reversed: reversedAudioBuffer,
};
Otherwise, there will be an in-place creation of a reversed audio buffer, which can be expensive.
For more details, see our reverseAudioBuffer
utility.
Pre-process playback position channel
!NOTE For more information about our approach and why it's still necessary to create an additional channel to accurately track audio playback time, refer to this thread.
A user can supply the reversed audio buffer with an additional playback position channel already supplied.
// In a worker environment:
import {
makePlaybackPositionChannelData,
makeAudioBufferWithPlaybackPositionChannel,
} from "simple-reversible-audio-buffer-source-node";
const playbackPositionChannel = makePlaybackPositionChannelData(audioBuffer);
const audioBufferWithPlaybackPositionChannel =
makeAudioBufferWithPlaybackPositionChannel(
audioBuffer,
playbackPositionChannel,
);
//
// ---
//
// In a browser environment:
import { ReversibleAudioBufferSourceNode } from "simple-reversible-audio-buffer-source-node";
const reversibleAudioBufferSourceNode = new ReversibleAudioBufferSourceNode(
audioContext,
{
shouldCreatePlaybackPositionChannel: false,
},
);
reversibleAudioBufferSourceNode.buffer = audioBufferWithPlaybackPositionChannel;
Otherwise, there will be an in-place creation of a playback position channel, which can be expensive.
For more details, see our makePlaybackPositionChannelData
and makeAudioBufferWithPlaybackPositionChannel
utilities.
Things this package does not yet support:
- Looping, but I'm looking into it.
duration
arg for.start()
, but I'm looking into it.MediaElementAudioSourceNode
support