├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── index.js ├── license ├── package.json ├── readme.md └── test.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "commonjs": true, 6 | "es6": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "rules": { 10 | "strict": 2, 11 | "indent": 0, 12 | "linebreak-style": 0, 13 | "quotes": 0, 14 | "semi": 0, 15 | "no-cond-assign": 1, 16 | "no-constant-condition": 1, 17 | "no-duplicate-case": 1, 18 | "no-empty": 1, 19 | "no-ex-assign": 1, 20 | "no-extra-boolean-cast": 1, 21 | "no-extra-semi": 1, 22 | "no-fallthrough": 1, 23 | "no-func-assign": 1, 24 | "no-global-assign": 1, 25 | "no-implicit-globals": 2, 26 | "no-inner-declarations": ["error", "functions"], 27 | "no-irregular-whitespace": 2, 28 | "no-loop-func": 1, 29 | "no-magic-numbers": ["warn", { "ignore": [1, 0, -1], "ignoreArrayIndexes": true}], 30 | "no-multi-str": 1, 31 | "no-mixed-spaces-and-tabs": 1, 32 | "no-proto": 1, 33 | "no-sequences": 1, 34 | "no-throw-literal": 1, 35 | "no-unmodified-loop-condition": 1, 36 | "no-useless-call": 1, 37 | "no-void": 1, 38 | "no-with": 2, 39 | "wrap-iife": 1, 40 | "no-redeclare": 1, 41 | "no-unused-vars": ["error", { "vars": "all", "args": "none" }], 42 | "no-sparse-arrays": 1 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | node_modules 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "node" 5 | - "6" 6 | - "5" 7 | - "4" 8 | - "0.12" 9 | - "0.10" 10 | matrix: 11 | fast_finish: true 12 | allow_failures: 13 | - node_js: "0.10" 14 | - node_js: "0.12" 15 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module audio-dtype 3 | */ 4 | 5 | 'use strict' 6 | 7 | var AudioBuffer = require('audio-buffer') 8 | var isAudioBuffer = require('is-audio-buffer') 9 | var isObj = require('is-plain-obj') 10 | var getContext = require('audio-context') 11 | var convert = require('pcm-convert') 12 | var format = require('audio-format') 13 | var str2ab = require('string-to-arraybuffer') 14 | var pick = require('pick-by-alias') 15 | 16 | module.exports = function createBuffer (source, options) { 17 | var length, data, channels, sampleRate, format, c, l 18 | 19 | //src, channels 20 | if (typeof options === 'number') { 21 | options = {channels: options} 22 | } 23 | else if (typeof options === 'string') { 24 | options = {format: options} 25 | } 26 | //{} 27 | else if (options === undefined) { 28 | if (isObj(source)) { 29 | options = source 30 | source = undefined 31 | } 32 | else { 33 | options = {} 34 | } 35 | } 36 | 37 | options = pick(options, { 38 | format: 'format type dtype dataType', 39 | channels: 'channel channels numberOfChannels channelCount', 40 | sampleRate: 'sampleRate rate', 41 | length: 'length size', 42 | duration: 'duration time' 43 | }) 44 | 45 | //detect options 46 | channels = options.channels 47 | sampleRate = options.sampleRate 48 | if (options.format) format = getFormat(options.format) 49 | 50 | if (format) { 51 | if (channels && !format.channels) format.channels = channels 52 | else if (format.channels && !channels) channels = format.channels 53 | if (!sampleRate && format.sampleRate) sampleRate = format.sampleRate 54 | } 55 | 56 | //empty buffer 57 | if (source == null) { 58 | if (options.duration != null) { 59 | if (!sampleRate) sampleRate = 44100 60 | length = sampleRate * options.duration 61 | } 62 | else length = options.length 63 | } 64 | 65 | //if audio buffer passed - create fast clone of it 66 | else if (isAudioBuffer(source)) { 67 | length = source.length 68 | if (channels == null) channels = source.numberOfChannels 69 | if (sampleRate == null) sampleRate = source.sampleRate 70 | 71 | if (source._channelData) { 72 | data = source._channelData.slice(0, channels) 73 | } 74 | else { 75 | data = [] 76 | 77 | for (c = 0, l = channels; c < l; c++) { 78 | data[c] = source.getChannelData(c) 79 | } 80 | } 81 | } 82 | 83 | //if create(number, channels? rate?) = create new array 84 | //this is the default WAA-compatible case 85 | else if (typeof source === 'number') { 86 | length = source 87 | } 88 | 89 | //if array with channels - parse channeled data 90 | else if (Array.isArray(source) && (Array.isArray(source[0]) || ArrayBuffer.isView(source[0]))) { 91 | length = source[0].length; 92 | data = [] 93 | if (!channels) channels = source.length 94 | for (c = 0; c < channels; c++) { 95 | data[c] = source[c] instanceof Float32Array ? source[c] : new Float32Array(source[c]) 96 | } 97 | } 98 | 99 | //if ndarray, ndsamples, or anything with data 100 | else if (source.shape && source.data) { 101 | if (source.shape) channels = source.shape[1] 102 | if (!sampleRate && source.format) sampleRate = source.format.sampleRate 103 | 104 | return createBuffer(source.data, { 105 | channels: channels, 106 | sampleRate: sampleRate 107 | }) 108 | } 109 | 110 | //TypedArray, Buffer, DataView etc, ArrayBuffer, Array etc. 111 | //NOTE: node 4.x+ detects Buffer as ArrayBuffer view 112 | else { 113 | if (typeof source === 'string') { 114 | source = str2ab(source) 115 | } 116 | 117 | if (!format) format = getFormat(source) 118 | if (!channels) channels = format.channels || 1 119 | source = convert(source, format, 'float32 planar') 120 | 121 | length = Math.floor(source.length / channels); 122 | data = [] 123 | for (c = 0; c < channels; c++) { 124 | data[c] = source.subarray(c * length, (c + 1) * length); 125 | } 126 | } 127 | 128 | //create buffer of proper length 129 | var audioBuffer = new AudioBuffer((options.context === null || length === 0) ? null : options.context || getContext(), { 130 | length: length == null ? 1 : length, 131 | numberOfChannels: channels || 1, 132 | sampleRate: sampleRate || 44100 133 | }) 134 | 135 | //fill channels 136 | if (data) { 137 | for (c = 0, l = data.length; c < l; c++) { 138 | audioBuffer.getChannelData(c).set(data[c]); 139 | } 140 | } 141 | 142 | 143 | return audioBuffer 144 | } 145 | 146 | 147 | function getFormat (arg) { 148 | return typeof arg === 'string' ? format.parse(arg) : format.detect(arg) 149 | } 150 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Dmitry Ivanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audio-buffer-from", 3 | "version": "1.1.1", 4 | "description": "Create AudioBuffer from any source", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/audiojs/audio-buffer-from.git" 12 | }, 13 | "keywords": [ 14 | "audio", 15 | "audiojs", 16 | "dsp", 17 | "web-audio-api", 18 | "audio-buffer", 19 | "create audio buffer", 20 | "pcm" 21 | ], 22 | "author": "Dima Yv ", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/audiojs/audio-buffer-from/issues" 26 | }, 27 | "homepage": "https://github.com/audiojs/audio-buffer-from#readme", 28 | "dependencies": { 29 | "audio-buffer": "^4.0.4", 30 | "audio-context": "^1.0.1", 31 | "audio-format": "^2.0.0", 32 | "is-audio-buffer": "^1.0.11", 33 | "is-plain-obj": "^1.1.0", 34 | "pcm-convert": "^1.6.0", 35 | "pick-by-alias": "^1.2.0", 36 | "string-to-arraybuffer": "^1.0.0" 37 | }, 38 | "devDependencies": { 39 | "arraybuffer-to-string": "^1.0.1", 40 | "atob-lite": "^2.0.0", 41 | "audio-buffer-list": "^4.1.0", 42 | "create-data-uri": "^1.1.0", 43 | "ndarray": "^1.0.18", 44 | "ndsamples": "^1.0.0", 45 | "object-assign": "^4.1.1", 46 | "tape": "^4.6.3", 47 | "wav-encoder": "^1.1.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # audio-buffer-from [![Build Status](https://travis-ci.org/audiojs/audio-buffer-from.svg?branch=master)](https://travis-ci.org/audiojs/audio-buffer-from) [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges) [![Greenkeeper badge](https://badges.greenkeeper.io/audiojs/audio-buffer-from.svg)](https://greenkeeper.io/) 2 | 3 | Create [AudioBuffer](https://github.com/audiojs/audio-buffer) from any source. 4 | 5 | ## Usage 6 | 7 | [![$ npm install audio-buffer-from](http://nodei.co/npm/audio-buffer-from.png?mini=true)](http://npmjs.org/package/audio-buffer-from) 8 | 9 | ```js 10 | var createBuffer = require('audio-buffer-from') 11 | 12 | //mono-buffer 1024 samples 13 | var abuf = createBuffer(1024) 14 | 15 | //stereo-buffer 1024 samples 16 | var abuf2 = createBuffer(1024, 2) 17 | 18 | //buffer from data with bound audio context 19 | var abuf3 = createBuffer(floatArray, {context: audioContext}) 20 | 21 | //empty 1-sample mono buffer with default context 22 | var abuf4 = createBuffer() 23 | 24 | //0-length no-context buffer 25 | var abuf5 = createBuffer(0) 26 | 27 | //from duration 28 | var abuf6 = createBuffer({duration: 1}) 29 | 30 | //from pcm data 31 | var abuf7 = createBuffer(new Uint8Array([0, 0, 255, 255]), 'interleaved 96000') 32 | 33 | //from data-uri 34 | var abuf8 = createBuffer('data:application/octet-stream;base64,AP8A/w==', 'uint8') 35 | 36 | //from base64 string 37 | var abuf9 = createBuffer('AAAAAAAAAAAAAIA/AACAPw==', 'float32 stereo planar') 38 | 39 | //from node Buffer 40 | var abuf10 = createBuffer(Buffer.from([0, 255, 0, 127]), 'interleaved') 41 | ``` 42 | 43 | ## API 44 | 45 | ### audioBuffer = createBuffer(source|length, channels|format|options) 46 | 47 | Create audio buffer from any `source` data or a number indicating `length`, pass `options` to ensure output buffer parameters. A `channels` number or `format` string can be used to shorthand options argument. 48 | 49 | #### Source: 50 | 51 | | Type | Interpretation | 52 | |---|---| 53 | | `null` | Blank 1-sample length buffer. | 54 | | `Number` | Length of resulting buffer. | 55 | | `Array` of `Arrays` | Every subarray is considered a channel data. | 56 | | `AudioBuffer` | Clone other AudioBuffer. | 57 | | `AudioBufferList` | Coalesce [AudioBufferList](https://github.com/audiojs/audio-buffer-list) to AudioBuffer. | 58 | | `Audio` | Retrieve AudioBuffer from [Audio](https://github.com/audiojs/audio). | 59 | | `Object` | Create based on `length`/`duration`, `channels`/`numberOfChannels` and `sampleRate` properties. | 60 | | `Array` of `Numbers` | Raw data, interpreted by `options.format`, defaults to `float64`. | 61 | | `Float32Array` | Raw `float32` data, amplitude range is `-1..+1`. | 62 | | `Float64Array` | Raw `float64` data, amplitude range is `-1..+1`. | 63 | | `Int8Array` | Raw `int8` data, amplitude range is `-128..+127`. | 64 | | `Uint8Array` | Raw `uint8` data, amplitude range is `0..255`. | 65 | | `TypedArray` | Any other typed array, described by `options.format` argument (see [pcm-convert](https://github.com/audiojs/pcm-convert)). | 66 | | `ArrayBuffer` | Raw data, interpreted by `options.format`. | 67 | | `Buffer` | Raw data, interpreted by `options.format`. | 68 | | `base64` string | [Base64](https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding)-encoded data. | 69 | | `dataURI` string | [DataURI](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) string. | 70 | | `ndarray` | Create from [ndarray](https://npmjs.org/package/ndarray) instance. The `shape` property is considered as `[length, channels]`. | 71 | | `ndsamples` | Create from [ndsamples](https://npmjs.org/package/ndsamples) instance, similar to ndarray. | 72 | 73 | #### Options: 74 | 75 | Property | Default | Meaning 76 | |---|---|--- 77 | `length` | `1` | Buffer length. If `0`, buffer is unbound from context. 78 | `context` | [`audio-context`](https://github.com/audiojs/audio-context) | Audio context to bind. `null`-context creates context-free audio buffer. 79 | `channels`, `numberOfChannels` | `1` | Buffer number of channels. 80 | `sampleRate`, `rate` | `44100` | Buffer sample rate. 81 | `format` | `null` | Source pcm format string or object, see [audio-format](https://github.com/audiojs/audio-format). If `null`, it will be detected from the `source`. 82 | 83 | 84 | ### Related 85 | 86 | * [audio-buffer](https://github.com/audiojs/audio-buffer) 87 | * [audio-buffer-utils](https://github.com/audiojs/audio-buffer-utils) 88 | * [pcm-convert](https://github.com/audiojs/pcm-convert) 89 | 90 | ## License 91 | 92 | © 2017 Dmitry Yv. MIT License 93 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const t = require('tape') 4 | const ndarray = require('ndarray') 5 | const ndsamples = require('ndsamples') 6 | const AudioBuffer = require('audio-buffer') 7 | const createBuffer = require('./') 8 | const atob = require('atob-lite') 9 | const encode = require('wav-encoder').encode 10 | const createUri = require('create-data-uri') 11 | const toString = require('arraybuffer-to-string') 12 | const AudioBufferList = require('audio-buffer-list') 13 | 14 | t('from ndarray', t => { 15 | let a = ndarray(new Float32Array([0, 1, 1, 0]), [2, 2]) 16 | 17 | let buf = createBuffer(a, {sampleRate: 48000}) 18 | 19 | t.equal(buf.length, 2) 20 | t.equal(buf.numberOfChannels, 2) 21 | t.equal(buf.sampleRate, 48000) 22 | t.end() 23 | }) 24 | 25 | t('from ndsamples', t => { 26 | let data = [ 27 | 0, 0.5, 28 | -0.5, 0, 29 | 1, -1, 30 | -1, 1 31 | ] 32 | let shape = [4, 2] 33 | let format = { 34 | sampleRate: 48000 35 | } 36 | let samples = ndsamples({ 37 | data: data, 38 | shape: shape, 39 | format: format 40 | }) 41 | 42 | let buf = createBuffer(samples) 43 | 44 | t.equal(buf.length, 4) 45 | t.equal(buf.numberOfChannels, 2) 46 | t.equal(buf.sampleRate, 48000) 47 | t.end() 48 | }) 49 | 50 | t('from float32 arraybuffer', t => { 51 | let floats = new Float32Array([0, 1, 1, 0]) 52 | 53 | let buf = createBuffer(floats.buffer, {format: 'float32', channels: 2}) 54 | 55 | t.equal(buf.length, 2) 56 | t.deepEqual(buf.getChannelData(0), [0, 1]) 57 | 58 | t.end() 59 | }) 60 | 61 | t('from float64 arraybuffer', t => { 62 | let floats = new Float64Array([0, 1, 1, -1, 0, 1]) 63 | 64 | let buf = createBuffer(floats.buffer, {format: 'float64', channels: 2}) 65 | 66 | t.equal(buf.length, 3) 67 | t.deepEqual(buf.getChannelData(1), [-1, 0, 1]) 68 | 69 | t.end() 70 | }) 71 | 72 | t('from uint8 arraybuffer', t => { 73 | let ints = new Uint8Array([0, 255, 0, 255]) 74 | let buf2 = createBuffer(ints.buffer, {format: 'uint8 interleaved stereo'}) 75 | 76 | t.deepEqual(buf2.getChannelData(0), [-1, -1]) 77 | t.deepEqual(buf2.getChannelData(1), [1, 1]) 78 | t.equal(buf2.length, 2) 79 | t.equal(buf2.numberOfChannels, 2) 80 | 81 | t.end() 82 | }) 83 | 84 | t('from int8 arraybuffer', t => { 85 | let ints = new Int8Array([-128, 127, -128, 127]) 86 | let buf = createBuffer(ints.buffer, 'int8 interleaved 96000') 87 | 88 | t.equal(buf.numberOfChannels, 2) 89 | t.equal(buf.length, 2) 90 | t.deepEqual(buf.getChannelData(0), [-1, -1]) 91 | t.deepEqual(buf.getChannelData(1), [1, 1]) 92 | t.equal(buf.sampleRate, 96000) 93 | 94 | t.end() 95 | }) 96 | 97 | t('from buffer', t => { 98 | let buf = Buffer.from(new Uint8Array([0,255,0,255])) 99 | 100 | let abuf1 = createBuffer(buf) 101 | t.equal(abuf1.numberOfChannels, 1) 102 | t.equal(abuf1.length, 4) 103 | 104 | let abuf2 = createBuffer(buf, {channels: 2}) 105 | t.equal(abuf2.numberOfChannels, 2) 106 | t.equal(abuf2.length, 2) 107 | 108 | let abuf3 = createBuffer(buf, 'stereo interleaved') 109 | t.equal(abuf3.numberOfChannels, 2) 110 | t.equal(abuf3.length, 2) 111 | t.deepEqual(abuf3.getChannelData(0), [-1, -1]) 112 | 113 | t.end() 114 | }) 115 | 116 | t('from array with numbers', t => { 117 | let buf = createBuffer([0, -1, 0, 1]) 118 | 119 | t.equal(buf.numberOfChannels, 1) 120 | t.equal(buf.length, 4) 121 | 122 | 123 | let buf2 = createBuffer([0, -1, 0, 1], 'stereo interleaved') 124 | 125 | t.equal(buf2.numberOfChannels, 2) 126 | t.equal(buf2.length, 2) 127 | t.deepEqual(buf2.getChannelData(1), [-1, 1]) 128 | 129 | t.end() 130 | }) 131 | 132 | t('from array with channels', t => { 133 | let buf = createBuffer([[0, 0], [1, 1]]) 134 | 135 | t.equal(buf.numberOfChannels, 2) 136 | t.equal(buf.length, 2) 137 | 138 | 139 | let buf2 = createBuffer([new Float32Array([0, 0]), new Float32Array([1, 1])]) 140 | 141 | t.equal(buf2.numberOfChannels, 2) 142 | t.equal(buf2.length, 2) 143 | t.deepEqual(buf2.getChannelData(0), [0, 0]) 144 | t.deepEqual(buf2.getChannelData(1), [1, 1]) 145 | 146 | 147 | let buf3 = createBuffer([[-1, -1], [1, 1]], {channels: 3}) 148 | t.equal(buf3.numberOfChannels, 3) 149 | t.equal(buf3.length, 2) 150 | 151 | t.end() 152 | }) 153 | 154 | t('from float32 array', t => { 155 | let b = createBuffer(new Float32Array([-1,0,1])) 156 | 157 | t.equal(b.numberOfChannels, 1) 158 | t.equal(b.length, 3) 159 | 160 | let b2 = createBuffer(new Float32Array([-1, 0, 1, 0]), 'stereo interleaved') 161 | 162 | t.equal(b2.length, 2) 163 | t.equal(b2.numberOfChannels, 2) 164 | t.deepEqual(b2.getChannelData(0), [-1, 1]) 165 | 166 | t.end() 167 | }) 168 | 169 | t('from empty', t => { 170 | let b = createBuffer() 171 | 172 | t.equal(b.length, 1) 173 | t.equal(b.numberOfChannels, 1) 174 | 175 | 176 | let b2 = createBuffer(null) 177 | 178 | t.equal(b2.length, 1) 179 | t.equal(b2.numberOfChannels, 1) 180 | 181 | t.end() 182 | }) 183 | 184 | t('from number', t => { 185 | let b = createBuffer(100) 186 | 187 | t.equal(b.length, 100) 188 | t.equal(b.numberOfChannels, 1) 189 | 190 | let b2 = createBuffer(100, 2) 191 | 192 | t.equal(b2.length, 100) 193 | t.equal(b2.numberOfChannels, 2) 194 | 195 | t.end() 196 | }) 197 | 198 | t('from audiobuffer', t => { 199 | let ab = new AudioBuffer(null, {length: 10, numberOfChannels: 2}) 200 | 201 | let b = createBuffer(ab) 202 | 203 | t.notEqual(b, ab) 204 | t.equal(b.numberOfChannels, ab.numberOfChannels) 205 | t.equal(b.sampleRate, ab.sampleRate) 206 | t.equal(b.length, ab.length) 207 | 208 | t.end() 209 | }) 210 | 211 | t('from object', t => { 212 | //numberOfChannels, channelCount, channels 213 | let b = createBuffer({length: 100}) 214 | 215 | t.equal(b.length, 100) 216 | t.equal(b.numberOfChannels, 1) 217 | 218 | 219 | let b2 = createBuffer({numberOfChannels: 2, length: 5}) 220 | 221 | t.equal(b2.length, 5) 222 | t.equal(b2.numberOfChannels, 2) 223 | 224 | 225 | let b3 = createBuffer({channels: 2, length: 5}) 226 | 227 | t.equal(b3.length, 5) 228 | t.equal(b3.numberOfChannels, 2) 229 | 230 | 231 | let b4 = createBuffer({sampleRate: 12000, length: 5}) 232 | 233 | t.equal(b4.length, 5) 234 | t.equal(b4.numberOfChannels, 1) 235 | t.equal(b4.sampleRate, 12000) 236 | 237 | 238 | let b5 = createBuffer({channelCount: 2, length: 2}) 239 | 240 | t.equal(b5.length, 2) 241 | t.equal(b5.numberOfChannels, 2) 242 | 243 | 244 | let b6 = createBuffer(null, {channels: 3, length: 5}) 245 | 246 | t.equal(b6.length, 5) 247 | t.equal(b6.numberOfChannels, 3) 248 | 249 | 250 | t.end() 251 | }) 252 | 253 | t('0-length buffer', t => { 254 | let b = createBuffer(0, {context: {}}) 255 | 256 | t.equal(b.numberOfChannels, 1) 257 | t.equal(b.length, 0) 258 | 259 | t.end() 260 | }) 261 | 262 | t('from dataURI', t => { 263 | // let header = 'data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgA' 264 | 265 | // smallest mp3 266 | // 'data:audio/mpeg;base64,/+MYxAAAAANIAAAAAExBTUUzLjk4LjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' 267 | 268 | // wav-datauri 269 | // let wave = encode({sampleRate: 44100, channelData: [ 270 | // new Float32Array([0,0,1,1]), 271 | // new Float32Array([0,0,1,1]), 272 | // ]}).then(data => { 273 | // let str = createUri('audio/wav', toString(data, 'base64')) 274 | 275 | // let buf = createBuffer(str) 276 | 277 | // t.equal(t.numberOfChannels) 278 | // }) 279 | 280 | let uint8 = new Uint8Array([0, 255, 0, 255]) 281 | let uri = createUri('application/octet-stream', toString(uint8, 'base64')) 282 | console.log(uri) 283 | let buf = createBuffer(uri, 'uint8 interleaved') 284 | 285 | t.equal(buf.numberOfChannels, 2) 286 | t.equal(buf.length, 2) 287 | t.deepEqual(buf.getChannelData(0), [-1, -1]) 288 | t.deepEqual(buf.getChannelData(1), [1, 1]) 289 | 290 | 291 | let floats = new Float32Array([0, 0, 1, 1]) 292 | let uri2 = createUri('application/octet-stream', toString(floats.buffer, 'base64')) 293 | 294 | let buf2 = createBuffer(uri2, 'float32 planar') 295 | 296 | t.equal(buf2.numberOfChannels, 2) 297 | t.equal(buf2.length, 2) 298 | t.deepEqual(buf2.getChannelData(0), [0, 0]) 299 | t.deepEqual(buf2.getChannelData(1), [1, 1]) 300 | 301 | t.end() 302 | }) 303 | 304 | t('from base64', t => { 305 | let uint8 = new Uint8Array([0, 255, 0, 255]) 306 | let uri = toString(uint8, 'base64') 307 | 308 | let buf = createBuffer(uri, 'uint8 interleaved') 309 | 310 | t.equal(buf.numberOfChannels, 2) 311 | t.equal(buf.length, 2) 312 | t.deepEqual(buf.getChannelData(0), [-1, -1]) 313 | t.deepEqual(buf.getChannelData(1), [1, 1]) 314 | 315 | 316 | let floats = new Float32Array([0, 0, 1, 1]) 317 | let uri2 = toString(floats.buffer, 'base64') 318 | 319 | let buf2 = createBuffer(uri2, 'float32 planar') 320 | 321 | t.equal(buf2.numberOfChannels, 2) 322 | t.equal(buf2.length, 2) 323 | t.deepEqual(buf2.getChannelData(0), [0, 0]) 324 | t.deepEqual(buf2.getChannelData(1), [1, 1]) 325 | 326 | t.end() 327 | }) 328 | 329 | 330 | t('from raw string', t => { 331 | let uint8 = new Uint8Array([0, 255, 0, 255]) 332 | let uri = toString(uint8, 'binary') 333 | 334 | let buf = createBuffer(uri, 'uint8 interleaved') 335 | 336 | t.equal(buf.numberOfChannels, 2) 337 | t.equal(buf.length, 2) 338 | t.deepEqual(buf.getChannelData(0), [-1, -1]) 339 | t.deepEqual(buf.getChannelData(1), [1, 1]) 340 | 341 | 342 | let floats = new Float32Array([-1, -1, 1, 1]) 343 | let uri2 = toString(floats.buffer, 'binary') 344 | 345 | let buf2 = createBuffer(uri2, 'float32 planar') 346 | 347 | t.equal(buf2.numberOfChannels, 2) 348 | t.equal(buf2.length, 2) 349 | t.deepEqual(buf2.getChannelData(0), [-1, -1]) 350 | t.deepEqual(buf2.getChannelData(1), [1, 1]) 351 | 352 | t.end() 353 | }) 354 | 355 | 356 | t('from audiobuffer strip channels', t => { 357 | let a = createBuffer(1, 3) 358 | let b = createBuffer(a, 2) 359 | 360 | t.equal(a.numberOfChannels, 3) 361 | t.equal(b.numberOfChannels, 2) 362 | t.equal(b.length, 1) 363 | 364 | t.end() 365 | }) 366 | 367 | 368 | t('from audiobuffer save sample rate', t => { 369 | let a = createBuffer(1, {channels: 3, sampleRate: 10000}) 370 | let b = createBuffer(a, 2) 371 | 372 | t.equal(a.numberOfChannels, 3) 373 | t.equal(b.numberOfChannels, 2) 374 | t.equal(b.length, 1) 375 | t.equal(b.sampleRate, 10000) 376 | 377 | t.end() 378 | }) 379 | 380 | t('from audio-buffer-list', t => { 381 | let a = AudioBufferList(100, {channels: 2}) 382 | 383 | let ab = createBuffer(a) 384 | 385 | t.equal(ab.length, 100) 386 | t.equal(ab.numberOfChannels, 2) 387 | 388 | t.end() 389 | }) 390 | 391 | t('from object with duration', t => { 392 | let a = createBuffer({duration: .5, channels: 2}) 393 | 394 | t.equal(a.length, 22050) 395 | 396 | let b = createBuffer({duration: 0, channels: 2}) 397 | 398 | t.equal(b.length, 0) 399 | 400 | 401 | let c = createBuffer(null, {duration: 0, channels: 2}) 402 | 403 | t.equal(c.length, 0) 404 | 405 | let d = createBuffer(null, {duration: 0.005, channels: 2}) 406 | 407 | t.equal(d.length, 221) 408 | 409 | t.end() 410 | }) 411 | --------------------------------------------------------------------------------