audio-buffer
Version:
AudioBuffer ponyfill with operations toolkit
229 lines (154 loc) • 6.7 kB
Markdown
# audio-buffer [](https://github.com/audiojs/audio-buffer/actions/workflows/node.js.yml) [](http://github.com/badges/stability-badges)
> Audio data container with planar float32 layout.
[Web Audio API AudioBuffer](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer) ponyfill for node, bun and other envs.
Comes with optional utils.
```js
import AudioBuffer from 'audio-buffer'
import { from, trim, normalize } from 'audio-buffer/util'
let buf = from([0, 0, 0.5, 0.8, 0.3, 0, 0])
buf = normalize(trim(buf))
```
## API
### Constructor
```js
new AudioBuffer({ length: 1024, sampleRate: 44100, numberOfChannels: 2 })
new AudioBuffer(2, 1024, 44100) // positional form
```
### Properties
All read-only.
* `length` — samples per channel
* `sampleRate` — Hz
* `duration` — seconds
* `numberOfChannels`
Iterable over channels: `for (let ch of buf)`, `let [L, R] = buf`.
### Methods
```js
buf.getChannelData(0) // Float32Array for channel 0
buf.copyFromChannel(dest, 0, 100) // copy channel 0 from sample 100 into dest
buf.copyToChannel(src, 1) // write src into channel 1
```
## Utils
```js
import { from, slice, concat, set } from 'audio-buffer/util'
```
Same-size ops mutate and return the buffer. Size-changing ops return a new buffer.
#### `isAudioBuffer(buf) → boolean`
Check if object is an AudioBuffer instance or duck-typed compatible.
```js
isAudioBuffer(buf) // true
```
#### `from(source, fill?, options?) → AudioBuffer`
Create buffer from anything — number, Float32Array, Array, AudioBuffer, ArrayBuffer. Optional second arg fills samples — a number for constant value, or `fn(sample, index, channel, channelData)` to map (like `Array.from`).
```js
from([0.1, -0.3, 0.5]) // array of samples → mono
from([left, right], { sampleRate: 48000 }) // Float32Array[] → stereo
from(existingBuffer) // clone
from(1024, 0.5) // 1024 samples buffer filled with 0.5
from(1024, (s, i) => Math.sin(i * 0.1)) // generate sine wave
from(buf, v => v * 0.5) // clone with half volume
from(buf, 0) // same shape, zeroed (like)
from({ length: 1024, numberOfChannels: 2 }) // from options
```
#### `slice(buffer, start?, end?) → newBuffer`
Extract sample range into new buffer.
```js
slice(buf, 100, 200) // samples 100–199
slice(buf, -50) // last 50 samples
```
#### `concat(...buffers) → newBuffer`
Join buffers (same sampleRate and channels).
```js
concat(a, b) // a + b end-to-end
concat(a, b, c, d) // join many
```
#### `set(buffer, other, offset?) → buffer`
Overwrite samples from another buffer.
```js
set(buf, patch, 1000) // write patch at sample 1000
```
#### `fill(buffer, value, start?, end?) → buffer`
Fill with constant or per-sample function.
```js
fill(buf, 0) // silence
fill(buf, (s, i, ch) => Math.sin(i * 0.1)) // sine wave
fill(buf, () => Math.random() * 2 - 1) // white noise
fill(buf, v => -v) // phase-invert
```
#### `normalize(buffer, start?, end?) → buffer`
Peak-normalize to 1.0, preserving inter-channel balance.
```js
normalize(buf) // quiet recording → full scale
```
#### `trim(buffer, threshold?) → newBuffer`
Remove silence from both ends.
```js
trim(buf) // remove exact zeros
trim(buf, 0.01) // remove near-silence
```
#### `reverse(buffer, start?, end?) → buffer`
Reverse samples.
```js
reverse(buf) // full reverse
reverse(buf, 0, 100) // reverse first 100 samples
```
#### `mix(a, b, ratio?, offset?) → a`
Blend `b` into `a`. Ratio 0 = keep `a`, 1 = replace with `b`.
```js
mix(track, reverb, 0.3) // 70% dry, 30% wet
mix(a, b, (sa, sb) => Math.max(sa, sb)) // custom blend function
mix(a, b, 0.5, 1000) // mix starting at sample 1000
```
#### `remix(buffer, channels, interpretation?) → newBuffer`
Upmix/downmix channels per [Web Audio spec](https://www.w3.org/TR/webaudio/#channel-up-mixing-and-down-mixing) speaker rules.
```js
remix(stereo, 1) // stereo → mono
remix(mono, 2) // mono → stereo
remix(buf, 6) // → 5.1 surround
remix(buf, 4, 'discrete') // copy channels, silence rest
```
#### `pad(buffer, length, value?, side?) → newBuffer`
Pad to target length.
```js
pad(buf, 44100) // zero-pad to 1 second
pad(buf, 44100, 0, 'start') // pad at start
```
#### `repeat(buffer, times) → newBuffer`
Repeat N times.
```js
repeat(buf, 4) // loop 4x
```
#### `rotate(buffer, offset) → buffer`
Circular shift. Positive = right.
```js
rotate(buf, 100) // shift right 100 samples
rotate(buf, -50) // shift left 50
```
#### `removeDC(buffer, start?, end?) → buffer`
Remove DC offset (subtract mean per channel).
```js
removeDC(buf) // center waveform at zero
```
#### `isEqual(a, b) → boolean`
Deep equality — same shape, same samples.
```js
isEqual(buf, clone) // true if identical
```
## Play
```js
import play from 'audio-buffer/play'
let ctrl = await play(buf, { volume: 0.8, loop: true })
ctrl.pause()
ctrl.play()
ctrl.stop()
ctrl.currentTime // seconds
ctrl.playing // boolean
```
Options: `{ volume, loop, start, end, autoplay, onended }`.
Uses Web Audio API in browsers. In Node.js, install [audio-speaker](https://github.com/audiojs/audio-speaker): `npm i audio-speaker`.
`stop()` resets to start. `play()` restarts from beginning.
## Replaces
* [audio-buffer-utils](https://github.com/audiojs/audio-buffer-utils)
* [audio-buffer-from](https://github.com/audiojs/audio-buffer-from)
* [audio-buffer-remix](https://github.com/audiojs/audio-buffer-remix)
* [audio-play](https://github.com/audiojs/audio-play)
<p align=center><a href="https://github.com/krishnized/license/">🕉</a></p>