audio-buffer-utils
Version:
Utility functions for AudioBuffers
238 lines (175 loc) • 9.47 kB
Markdown
# audio-buffer-utils [](https://travis-ci.org/audiojs/audio-buffer-utils) [](http://github.com/badges/stability-badges) [](https://greenkeeper.io/)
Utility functions for [_AudioBuffers_](https://github.com/audiojs/audio-buffer) in web-audio and node. Optimized for performance.
* [util.create(src, ch|opts?)](https://github.com/audiojs/audio-buffer-utils#utilcreatedatalength-optionschannels1-samplerate44100)
* [util.shallow(buf)](#utilshallowbuffer)
* [util.clone(buf)](#utilclonebuffer)
* [util.copy(buf, dst, start?)](#utilcopyfrombuffer-tobuffer-offset0)
* [util.slice(buf, start?, end?)](#utilslicebuffer-start0-end-0)
* [util.subbuffer(buf, start?, end?, ch?)](#utilsubbufferbuffer-start0-end-0-channels)
* [util.concat(a, b, ...)](#utilconcatbuffer1-buffer2-buffer3-buffern-)
* [util.repeat(buf, n)](#utilrepeatbuffer-times)
* [util.reverse(src, dst?, start?, end?)](#utilreversebuffer-target-start0-end-0)
* [util.invert(src, dst?, start?, end?)](#utilinvertbuffer-target-start0-end-0)
* [util.zero(buf)](#utilzerobuffer)
* [util.noise(buf)](#utilnoisebuffer)
* [util.equal(a, b, ...)](#utilequalbuffera-bufferb-)
* [util.fill(buf, dst?, val, start?, end?)](#utilfillbuffer-target-valuevalue-i-channelvalue-start0-end-0)
* [util.resize(buf, len)](#utilresizebuffer-length)
* [util.pad(buf, len, val?)](#utilpadbufferlength-lengthbuffer-value0)
* [util.shift(buf, off)](#utilshiftbuffer-offset)
* [util.rotate(buf, off)](#utilrotatebuffer-offset)
* [util.normalize(buf, dst?, start?, end?)](#utilnormalizebuffer-target-start0-end-0)
* [util.removeStatic(buf, dst?, start?, end?)](#utilremovestaticbuffer-target-start0-end-0)
* [util.trim(buf, lvl)](#utiltrimbuffer-threshold0)
* [util.mix(a, b, amt?, off?)](#utilmixbuffera-bufferb-ratiovala-valb-i-channelval-offset0)
* [util.size(buf)](#utilsizebuffer)
* [util.data(buf, dst?)](#utildatabuffer-data)
## Usage
[](https://npmjs.org/package/audio-buffer-utils/)
### `util.create(data|length, options|channels=1, sampleRate=44100)`
Create a new buffer from any argument.
Data can be a length, an array with channels' data, an other buffer or plain array. See [audio-buffer-from](https://github.com/audiojs/audio-buffer-from) module.
```js
//mono buffer with 100 samples
let a = util.create(100)
//stereo buffer with predefined channels data
let b = util.create([Array(100).fill(0.5), Array(100).fill(0.4)])
//minimal length buffer (1 sample, 1 channel)
let c = util.create()
//create 2 seconds buffer with reduced sample rate
let rate = 22050
let d = util.create(2 * rate, 2, rate)
```
### `util.shallow(buffer)`
Create a new buffer with the same characteristics as `buffer`, contents are undefined.
```js
//create buffer with the same shape as `a`
let b = util.shallow(a)
util.equal(a, b) //false
```
### `util.clone(buffer)`
Create a new buffer with the same characteristics as `buffer`, fill it with a copy of `buffer`'s data, and return it.
```js
//clone buffer `a`
let b = util.clone(a)
util.equal(a, b) //true
```
### `util.copy(fromBuffer, toBuffer, offset=0)`
Copy the data from one buffer to another, with optional offset. If length of `fromBuffer` exceeds `offset + toBuffer.length`, an error will be thrown.
### `util.slice(buffer, start=0, end=-0)`
Create a new buffer by slicing the current one.
### `util.subbuffer(buffer, start=0, end=-0, channels?)`
Create a new buffer by subreferencing the current one. The new buffer represents a handle for the source buffer, working on it's data. Note that it is null-context buffer, meaning that it is not bound to web audio API. To convert it to real _AudioBuffer_, use `util.slice` or `util.create`.
`channels` array may apply channels mapping to pick only indicated channels from the initial buffer. See also [audio-buffer-remix](https://github.com/audiojs/audio-buffer-remix).
```js
var a = util.create(100, 2)
var b = util.subbuffer(10, 90)
//b references a
b.getChannelData(0)[0] = 1
a.getChannelData(0)[10] // 1
//convert b to web-audio-api buffer
b = util.slice(b)
//create mono-buffer from a
var c = util.subbuffer(a, [1])
```
### `util.concat(buffer1, [buffer2, buffer3], bufferN, ...)`
Create a new buffer by concatting buffers or list.
Channels are extended to the buffer with maximum number.
### `util.repeat(buffer, times)`
Return a new buffer with contents of the initial one repeated defined number of times.
### `util.reverse(buffer, target?, start=0, end=-0)`
Reverse `buffer`. Place data to `target` buffer, if any, otherwise modify `buffer` in-place.
### `util.invert(buffer, target?, start=0, end=-0)`
Invert `buffer`. Place data to `target` buffer, if any, otherwise modify `buffer` in-place.
### `util.zero(buffer)`
Zero all of `buffer`'s channel data. `buffer` is modified in-place.
### `util.noise(buffer)`
Fill `buffer` with random data. `buffer` is modified in-place.
### `util.equal(bufferA, bufferB, ...)`
Test whether the content of N buffers is the same.
```js
let a = util.create(1024, 2)
util.noise(a)
let b = util.clone(a)
let c = util.shallow(a)
util.copy(a, c)
if (util.equal(a, b, c)) {
//true
}
```
### `util.fill(buffer, target?, value|(value, i, channel)=>value, start=0, end=-0)`
Fill `buffer` with provided function or value.
Place data to `target` buffer, if any, otherwise modify `buffer` in-place (that covers _map_ functionality).
Pass optional `start` and `end` indexes.
```js
let frequency = 440, rate = 44100
//create 2 seconds buffer
let a = util.create(2 * rate)
//populate with 440hz sine wave
util.fill(a, (value, i, channel)=>Math.sin(Math.PI * 2 * frequency * i / rate))
```
### `util.resize(buffer, length)`
Return new buffer based on the passed one, with shortened/extended length.
Initial data is whether sliced or filled with zeros. Combines `util.pad` and `util.slice`.
```js
//change duration to 2s
let b = util.resize(a, 2 * a.sampleRate)
```
### `util.pad(buffer|length, length|buffer, value=0)`
### `util.padLeft(buffer, length, value=0)`
### `util.padRight(buffer, length, value=0)`
Right/left-pad buffer to the length, filling with value.
```js
let buf = util.create(3, 1)
util.fill(buf, .2)
util.pad(buf, 5) // [.2,.2,.2, 0,0]
util.pad(5, buf) // [0,0, .2,.2,.2]
util.pad(buf, 5, .1) // [.2,.2,.2, .1,.1]
util.pad(5, buf, .1) // [.1,.1, .2,.2,.2]
```
### `util.shift(buffer, offset)`
Shift signal in the time domain by `offset` samples, filling with zeros.
Modify `buffer` in-place.
### `util.rotate(buffer, offset)`
Shift signal in the time domain by `offset` samples, in circular fashion.
Modify `buffer` in-place.
### `util.normalize(buffer, target?, start=0, end=-0)`
Normalize buffer by the amplitude, bring to -1..+1 range. Channel amplitudes ratio will be preserved. You may want to remove static level beforehead, because normalization preserves zero static level. Note that it is not the same as [array-normalize](https://github.com/dy/array-noramalize).
Places data to `target` buffer, if any, otherwise modifies `buffer` in-place.
```js
const AudioBuffer = require('audio-buffer')
const util = require('audio-buffer-utils')
let buf = AudioBuffer(1, [0, 0.2, 0, -0.4]);
util.normalize(buf);
buf.getChannelData(0) // [0, .5, 0, -1]
```
### `util.removeStatic(buffer, target?, start=0, end=-0)`
Remove DC (Direct Current) offset from the signal, i.e. remove static level, that is bring mean to zero. DC offset will be reduced for every channel independently.
```js
var a = AudioBuffer(2, [.5,.7,.3,.5])
util.removeStatic(a)
a.getChannelData(0) // [-.1, .1]
a.getChannelData(1) // [-.1, .1]
```
### `util.trim(buffer, threshold=0)`
### `util.trimLeft(buffer, threshold=0)`
### `util.trimRight(buffer, threshold=0)`
Create buffer with trimmed zeros from the start and/or end, by the threshold amplitude.
### `util.mix(bufferA, bufferB, ratio|(valA, valB, i, channel)=>val?, offset=0)`
Mix second buffer into the first one. Pass optional weight value or mixing function.
### `util.size(buffer)`
Return buffer size, in bytes. Use [pretty-bytes](https://npmjs.org/package/pretty-bytes) package to format bytes to a string, if needed.
### `util.data(buffer, data?)`
Get channels' data in array. Pass existing array to transfer the data to it.
Useful in audio-workers to transfer buffer to output.
```js
let a = util.create(3, 2)
let audioData = util.data(a) // [[0,0,0], [0,0,0]]
```
## Related
> [audio-buffer](https://github.com/audiojs/audio-buffer) — audio data container, both for node/browser.<br/>
> [audio-buffer-list](https://github.com/audiojs/audio-buffer-list) — linked audio buffers sequence structure<br/>
> [audio](https://github.com/audiojs/audio) — class for high-level audio manipulations, comprising the functionality of above mentioned.
> [ciseaux](https://github.com/mohayonao/ciseaux)
## Credits
Thanks to [**@jaz303**](https://github.com/jaz303/) for [the initial idea](https://github.com/jaz303/audio-buffer-utils) and collaboration.