audio-buffer-list
Advanced tools
Comparing version 1.0.0 to 1.1.0
156
index.js
@@ -15,2 +15,4 @@ /** | ||
var DuplexStream = require('readable-stream/duplex') | ||
var extend = require('object-assign') | ||
var context = require('audio-context') | ||
@@ -23,7 +25,10 @@ module.exports = AudioBufferList | ||
function AudioBufferList(callback) { | ||
if (!(this instanceof AudioBufferList)) return new AudioBufferList(callback) | ||
function AudioBufferList(callback, options) { | ||
if (!(this instanceof AudioBufferList)) return new AudioBufferList(callback, options) | ||
extend(this, options) | ||
this._bufs = [] | ||
this.length = 0 | ||
this.duration = 0 | ||
@@ -54,9 +59,87 @@ if (typeof callback == 'function') { | ||
//track max channels | ||
AudioBufferList.prototype.channels = 1 | ||
//AudioBuffer interface | ||
AudioBufferList.prototype.numberOfChannels = 0 | ||
AudioBufferList.prototype.sampleRate = context.sampleRate || 44100 | ||
//copy from channel into destination array | ||
AudioBufferList.prototype.copyFromChannel = function (destination, channel, startInChannel) { | ||
if (startInChannel == null) startInChannel = 0 | ||
var offsets = this._offset(startInChannel) | ||
var offset = startInChannel - offsets[1] | ||
var initialOffset = offsets[1] | ||
for (var i = offsets[0], l = this._bufs.length; i < l; i++) { | ||
var buf = this._bufs[i] | ||
var data = buf.getChannelData(channel) | ||
if (startInChannel > offset) data = data.subarray(startInChannel) | ||
if (channel < buf.numberOfChannels) { | ||
destination.set(data, Math.max(0, offset - initialOffset)) | ||
} | ||
offset += buf.length | ||
} | ||
} | ||
//put data from array to channel | ||
AudioBufferList.prototype.copyToChannel = function (source, channel, startInChannel) { | ||
if (startInChannel == null) startInChannel = 0 | ||
var offsets = this._offset(startInChannel) | ||
var offset = startInChannel - offsets[1] | ||
for (var i = offsets[0], l = this._bufs.length; i < l; i++) { | ||
var buf = this._bufs[i] | ||
var data = buf.getChannelData(channel) | ||
if (channel < buf.numberOfChannels) { | ||
data.set(source.subarray(Math.max(offset, startInChannel), offset + data.length), Math.max(0, startInChannel - offset)); | ||
} | ||
offset += buf.length | ||
} | ||
} | ||
//return float array with channel data | ||
AudioBufferList.prototype.getChannelData = function (channel) { | ||
if (!this._bufs.length) return new Float32Array() | ||
if (this._bufs.length === 1) return this._bufs[0].getChannelData(channel) | ||
var floatArray = this._bufs[0].getChannelData(0).constructor | ||
var data = new floatArray(this.length) | ||
var offset = 0 | ||
for (var i = 0, l = this._bufs.length; i < l; i++) { | ||
var buf = this._bufs[i] | ||
if (channel < buf.numberOfChannels) { | ||
data.set(buf.getChannelData(channel), offset); | ||
} | ||
offset += buf.length | ||
} | ||
return data | ||
} | ||
//repeat contents N times | ||
AudioBufferList.prototype.repeat = function (times) { | ||
times = Math.floor(times) | ||
if (!times && times !== 0 || !Number.isFinite(times)) throw RangeError('Repeat count must be non-negative number.') | ||
if (!times) { | ||
this.consume(this.length) | ||
return this | ||
} | ||
if (times === 1) return this | ||
var data = this | ||
for (var i = 1; i < times; i++) { | ||
data = data.slice() | ||
this.append(data) | ||
} | ||
return this | ||
} | ||
//patch BufferList methods | ||
AudioBufferList.prototype.append = function (buf) { | ||
@@ -70,17 +153,17 @@ //FIXME: we may want to do resampling/channel mapping here or something | ||
else if (Array.isArray(buf)) { | ||
for (; i < buf.length; i++) { | ||
this.append(buf[i]) | ||
} | ||
} | ||
// unwrap argument into individual BufferLists | ||
else if (buf instanceof AudioBufferList) { | ||
for (; i < buf._bufs.length; i++) | ||
this.append(buf._bufs[i]) | ||
} | ||
//create AudioBuffer from arg | ||
else if (buf != null) { | ||
for (; i < buf.length; i++) { | ||
this.append(buf[i]) | ||
} | ||
} | ||
// unwrap argument into individual BufferLists | ||
else if (buf instanceof AudioBufferList) { | ||
for (; i < buf._bufs.length; i++) | ||
this.append(buf._bufs[i]) | ||
} | ||
//create AudioBuffer from arg | ||
else if (buf != null) { | ||
if (typeof buf == 'number') { | ||
buf = [buf] | ||
} | ||
buf = new AudioBuffer(this.channels, buf) | ||
buf = new AudioBuffer(this.numberOfChannels, buf) | ||
this._appendBuffer(buf) | ||
@@ -93,6 +176,12 @@ } | ||
AudioBufferList.prototype._appendBuffer = function (buf) { | ||
if (buf.sampleRate != this.sampleRate) throw Error('Required sample rate is ' + this.sampleRate + ', passed ' + buf.sampleRate) | ||
BufferList.prototype._appendBuffer.call(this, buf) | ||
// if (buf.numberOfChannels != this.numberOfChannels) throw Error('Required number of channels is ' + this.numberOfChannels + ', passed ' + buf.numberOfChannels) | ||
//update channels count | ||
this.channels = Math.max(this.channels, buf.numberOfChannels) | ||
this.numberOfChannels = Math.max(this.numberOfChannels, buf.numberOfChannels) | ||
this.duration += buf.duration | ||
return this | ||
} | ||
@@ -112,5 +201,5 @@ | ||
if (srcStart >= this.length) | ||
return dst || new AudioBuffer(this.channels, 1) | ||
return dst || new AudioBuffer(this.numberOfChannels, 0) | ||
if (srcEnd <= 0) | ||
return dst || new AudioBuffer(this.channels, 1) | ||
return dst || new AudioBuffer(this.numberOfChannels, 0) | ||
@@ -130,6 +219,5 @@ var copy = !!dst | ||
return this._bufs.length === 1 | ||
? this._bufs[0] | ||
? util.slice(this._bufs[0]) | ||
: util.concat(this._bufs) | ||
} | ||
// copy, need to copy individual buffers | ||
@@ -148,7 +236,7 @@ for (i = 0; i < this._bufs.length; i++) { | ||
? util.copy(util.subbuffer(this._bufs[off[0]], start, start + bytes), dst, dstStart) | ||
: util.subbuffer(this._bufs[off[0]], start, start + bytes) | ||
: util.slice(this._bufs[off[0]], start, start + bytes) | ||
} | ||
if (!copy) // a slice, we need something to copy in to | ||
dst = new AudioBuffer(len) | ||
dst = new AudioBuffer(this.numberOfChannels, len) | ||
@@ -204,2 +292,3 @@ for (i = off[0]; i < this._bufs.length; i++) { | ||
this.length -= this._bufs[0].length | ||
this.duration -= this._bufs[0].duration | ||
this._bufs.shift() | ||
@@ -209,2 +298,3 @@ } else { | ||
this.length -= bytes | ||
this.duration -= this._bufs[0].duration | ||
break | ||
@@ -256,10 +346,2 @@ } | ||
// AudioBuffer properties & methods | ||
AudioBufferList.prototype.duration | ||
AudioBufferList.prototype.numberOfChannels | ||
AudioBufferList.prototype.sampleRate | ||
AudioBufferList.prototype.copyFromChannel | ||
AudioBufferList.prototype.copyToChannel | ||
AudioBufferList.prototype.getChannelData | ||
// Remove buffer dep | ||
@@ -281,11 +363,1 @@ | ||
// } | ||
// AudioBufferList.prototype.slice = function (start, end) { | ||
// } | ||
// AudioBufferList.prototype.copy = function (dest, destStart, start, end) { | ||
// } | ||
//TODO: shallowSlice or handle or subarray - return pointer |
{ | ||
"name": "audio-buffer-list", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Data structure for sequence of AudioBuffers", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test" | ||
"test": "node test", | ||
"test:browser": "budo test" | ||
}, | ||
@@ -35,2 +36,3 @@ "repository": { | ||
"audio-buffer-utils": "^4.1.1", | ||
"audio-context": "^0.1.0", | ||
"bl": "^1.2.0", | ||
@@ -37,0 +39,0 @@ "inherits": "^2.0.3", |
# audio-buffer-list [![Build Status](https://travis-ci.org/audiojs/audio-buffer-list.svg?branch=master)](https://travis-ci.org/audiojs/audio-buffer-list) [![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges) | ||
Extension of [BufferList](https://npmjs.org/package/bl) for [AudioBuffers](https://npmjs.org/package/audio-buffer). Handy and performant to deal with sequence of audio buffers − accumulate, read, stream, modify, delete etc. | ||
Extension of [BufferList](https://npmjs.org/package/bl) for [AudioBuffers](https://npmjs.org/package/audio-buffer). Handy and performant to deal with sequence of audio buffers − accumulate, read, stream, modify, delete etc. It provides interfaces both of _AudioBuffer_ and _BufferList_, as well as bunch of other useful methods. | ||
@@ -21,2 +21,28 @@ ## Usage | ||
## API | ||
### `new AudioBufferList(source, options?)` | ||
`source` can be _AudioBuffer_, _AudioBuffer_ array, _AudioBufferList_, _AudioBufferList_ array or callback. | ||
`options` may provide `numberOfChannels`, `context` for web audio API context and `sampleRate`. | ||
`new` is not strictly required. | ||
### `list.getChannelData(channel)` | ||
Return _FloatArray_ with merged data for the channel. | ||
### `list.copyFromChannel(destination, channel, startInChannel=0)` | ||
Put data from the channel to destination _FloatArray_. Optional `startInChannel` defines offset in the channel to start from. | ||
### `list.copyToChannel(source, channel, startInChannel=0)` | ||
Put data from the `source` _FloatArray_ into channel, optionally starting at `startInChannel` offset. | ||
### `list.repeat(count)` | ||
Repeats contents of the list specified number of times. Modifies list in-place. | ||
## See also | ||
@@ -23,0 +49,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14217
321
53
7
+ Addedaudio-context@^0.1.0
+ Addedaudio-context@0.1.0(transitive)
+ Addeddom-walk@0.1.2(transitive)
+ Addedglobal@4.2.1(transitive)
+ Addedmin-document@2.19.0(transitive)
+ Addedprocess@0.5.2(transitive)