test('fill to another buffer', function () { var a = new AudioBuffer([1,2,3,4]); var b = util.shallow(a); util.fill(a, b, 1, 1, 3); assert.deepEqual(a.getChannelData(0), [1,2]); assert.deepEqual(a.getChannelData(1), [3,4]); assert.deepEqual(b.getChannelData(0), [0,1]); assert.deepEqual(b.getChannelData(1), [0,1]); });
test('zero', function () { var buf1 = new AudioBuffer([1, 0.5, -1, 0]); util.zero(buf1); assert.deepEqual(buf1.getChannelData(0), [0, 0]); assert.deepEqual(buf1.getChannelData(1), [0, 0]); assert.throws(function () { util.invert(buf1.getChannelData(0)); }); });
test('noise', function () { var buf1 = new AudioBuffer(4); util.noise(buf1); assert.notDeepEqual(buf1.getChannelData(0), [0, 0]); assert.notDeepEqual(buf1.getChannelData(1), [0, 0]); assert.throws(function () { util.noise(buf1.getChannelData(0)); }); });
test('fill with value', function () { var a = new AudioBuffer([1,2,3,4]); util.fill(a, 1, 1, 3); assert.deepEqual(a.getChannelData(0), [1,1]); assert.deepEqual(a.getChannelData(1), [3,1]); assert.throws(function () { util.fill(a.getChannelData(1), 1); }); });
test('fill with function', function () { var a = new AudioBuffer([1,2,3,4]); util.fill(a, function (sample, channel, offset) { return channel + offset }); assert.deepEqual(a.getChannelData(0), [0,1]); assert.deepEqual(a.getChannelData(1), [1,2]); assert.throws(function () { util.fill([1,2,3], function () {}); }); });
test('clone - backing arrays are not shared between buffers', function () { var buf1 = new AudioBuffer([0, 1, 2, 3, 4]); var buf2 = util.clone(buf1); buf2.getChannelData(0)[0] = 100; assert.equal(0, buf1.getChannelData(0)[0]); });
test('invert', function () { var buf1 = new AudioBuffer([1, 0.5, -1, 0]); util.invert(buf1); assert.deepEqual(buf1.getChannelData(0), [-1, -0.5]); assert.deepEqual(buf1.getChannelData(1), [1, 0]); assert.throws(function () { util.invert(new Float32Array([1,2,3])); }); var buf2 = util.shallow(buf1); util.invert(buf1, buf2); assert.deepEqual(buf2.getChannelData(1), [-1, 0]); });
test('reverse', function () { var buf1 = new AudioBuffer([1, 0, -1, 0]); util.reverse(buf1); assert.deepEqual(buf1.getChannelData(0), [0, 1]); assert.deepEqual(buf1.getChannelData(1), [0, -1]); assert.throws(function () { util.reverse([1,2,3]); }); var buf2 = util.shallow(buf1); util.reverse(buf1, buf2); assert.deepEqual(buf2.getChannelData(1), [-1, 0]); });
test('copy', function () { var buf1 = new AudioBuffer([1, 0, -1, 0]); var buf2 = util.shallow(buf1); util.copy(buf1, buf2); assert(util.equal(buf1, buf2)); assert.notEqual(buf1, buf2); buf2.getChannelData(0)[1] = 0.5; assert.deepEqual(buf1.getChannelData(0), [1, 0]); assert.deepEqual(buf2.getChannelData(0), [1, 0.5]); var buf3 = new AudioBuffer(8); util.copy(buf2, buf3, 4); assert.deepEqual(buf3.getChannelData(0), [0,0,0,0, 1, 0.5, 0, 0]); // util.copy(buf3, buf2); });
test('Write Float32Array', function (t) { var stream = Writable(context.destination); var buf = new AudioBuffer(1024*8); util.noise(buf); stream.write(buf.getChannelData(0)); setTimeout(function () { stream.end(); t.end(); }, 300); });
test('clone', function () { var buf1 = new AudioBuffer([1, 0, -1, 0]); var buf2 = util.clone(buf1); assert(util.equal(buf1, buf2)); assert.notEqual(buf1, buf2); buf2.getChannelData(0)[1] = 0.5; assert.deepEqual(buf1.getChannelData(0), [1, 0]); assert.deepEqual(buf2.getChannelData(0), [1, 0.5]); assert.throws(function () { util.clone({}); }); });
test('slice', function () { var a = new AudioBuffer(3, [1,2,3,4,5,6,7,8,9]); var b = util.slice(a, 1); assert.deepEqual(b.getChannelData(0), [2,3]); assert.deepEqual(b.getChannelData(1), [5,6]); var c = util.slice(a, 1, 2); assert.deepEqual(c.getChannelData(0), [2]); assert.deepEqual(c.getChannelData(1), [5]); assert.deepEqual(c.numberOfChannels, 3); b.getChannelData(0)[0] = 1; assert.deepEqual(b.getChannelData(0), [1,3]); assert.deepEqual(a.getChannelData(0), [1, 2, 3]); assert.throws(function () { util.slice([1,2,3,4], 1, 2); }); });
test.skip('subbuffer', function () { //NOTE: in web-audio-API two audiobuffers cannot share the same memory //as far `.buffer` property of typedarrays cannot be overridden //and typedarrays are created by WebAudioBuffer innerly var a = new AudioBuffer(3, [1,2,3,4,5,6,7,8,9]); var b = util.subbuffer(a, 1); assert.deepEqual(b.getChannelData(0), [2,3]); assert.deepEqual(b.getChannelData(1), [5,6]); var c = util.subbuffer(a, 1, 2); assert.deepEqual(c.getChannelData(0), [2]); assert.deepEqual(c.getChannelData(1), [5]); assert.deepEqual(c.numberOfChannels, 3); b.getChannelData(0)[0] = 1; assert.deepEqual(b.getChannelData(0), [1,3]); assert.deepEqual(a.getChannelData(0), [1, 1, 3]); assert.deepEqual(c.getChannelData(0), [1]); });
module.exports = function createBuffer (source, options) { var length, data, channels, sampleRate, format, c, l //src, channels if (typeof options === 'number') { options = {channels: options} } else if (typeof options === 'string') { options = {format: options} } //{} else if (options === undefined) { if (isObj(source)) { options = source source = undefined } else { options = {} } } options = pick(options, { format: 'format type dtype dataType', channels: 'channel channels numberOfChannels channelCount', sampleRate: 'sampleRate rate', length: 'length size', duration: 'duration time' }) //detect options channels = options.channels sampleRate = options.sampleRate if (options.format) format = getFormat(options.format) if (format) { if (channels && !format.channels) format.channels = channels else if (format.channels && !channels) channels = format.channels if (!sampleRate && format.sampleRate) sampleRate = format.sampleRate } //empty buffer if (source == null) { if (options.duration != null) { if (!sampleRate) sampleRate = 44100 length = sampleRate * options.duration } else length = options.length } //if audio buffer passed - create fast clone of it else if (isAudioBuffer(source)) { length = source.length if (channels == null) channels = source.numberOfChannels if (sampleRate == null) sampleRate = source.sampleRate if (source._channelData) { data = source._channelData.slice(0, channels) } else { data = [] for (c = 0, l = channels; c < l; c++) { data[c] = source.getChannelData(c) } } } //if create(number, channels? rate?) = create new array //this is the default WAA-compatible case else if (typeof source === 'number') { length = source } //if array with channels - parse channeled data else if (Array.isArray(source) && (Array.isArray(source[0]) || ArrayBuffer.isView(source[0]))) { length = source[0].length; data = [] if (!channels) channels = source.length for (c = 0; c < channels; c++) { data[c] = source[c] instanceof Float32Array ? source[c] : new Float32Array(source[c]) } } //if ndarray, ndsamples, or anything with data else if (source.shape && source.data) { if (source.shape) channels = source.shape[1] if (!sampleRate && source.format) sampleRate = source.format.sampleRate return createBuffer(source.data, { channels: channels, sampleRate: sampleRate }) } //TypedArray, Buffer, DataView etc, ArrayBuffer, Array etc. //NOTE: node 4.x+ detects Buffer as ArrayBuffer view else { if (typeof source === 'string') { source = str2ab(source) } if (!format) format = getFormat(source) if (!channels) channels = format.channels || 1 source = convert(source, format, 'float32 planar') length = Math.floor(source.length / channels); data = [] for (c = 0; c < channels; c++) { data[c] = source.subarray(c * length, (c + 1) * length); } } //create buffer of proper length var audioBuffer = new AudioBuffer((options.context === null || length === 0) ? null : options.context || getContext(), { length: length == null ? 1 : length, numberOfChannels: channels || 1, sampleRate: sampleRate || 44100 }) //fill channels if (data) { for (c = 0, l = data.length; c < l; c++) { audioBuffer.getChannelData(c).set(data[c]); } } return audioBuffer }
assert.throws(function () { util.invert(buf1.getChannelData(0)); });
assert.throws(function () { util.noise(buf1.getChannelData(0)); });
assert.throws(function () { util.fill(a.getChannelData(1), 1); });