diff --git a/.gitignore b/.gitignore index 95ccccf..cfb822d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,32 @@ git config --global core.excludesfile ~/.gitignore //update files since .ignore won't if already tracked git rm --cached +# Node GYP # +############ +/build + +# Binding # +########### +Makefile +Makefile.in +configure +config.status +config.h.in +config.log +config.cache +autom4te.cache +aclocal.m4 +libmpg123.pc +libout123.pc +libmpg123.spec +mpg123.spec +unix2dos +unix2dos.c +/libtool +/.Tpo +/.deps +/.libs + # Compiled source # ################### *.com @@ -91,6 +117,7 @@ bower_components .CVS intermediate publish +.vscode .idea .graphics _test @@ -104,5 +131,5 @@ tmp .netrwhist bundle.* -build -_demo \ No newline at end of file + +_demo diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..57019a1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/mpg123"] + path = src/mpg123 + url = https://github.com/audiojs/mpg123 diff --git a/.travis.yml b/.travis.yml index 9300167..f80f3ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,30 @@ sudo: false language: node_js node_js: + - "node" - "6" - "5" - "4" - - "0.12" - - "0.10" +addons: + apt: + packages: + - libgnome-keyring-dev + - g++-4.8 + - libasound2-dev + sources: + - ubuntu-toolchain-r-test +env: + - CXX=g++-4.8 +install: + - npm install -g npm + - npm install -g node-pre-gyp + - npm install + - cd ./node_modules/audio-mpg123 + - node-pre-gyp clean + - node-pre-gyp rebuild --mpg123-module=dummy +script: + - node -v + - npm -v + - npm run test matrix: fast_finish: true - allow_failures: - - node_js: "0.10" - - node_js: "0.12" diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..6f3ab14 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +Copyright (c) 2016 AudioJS + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/browser-direct.js b/browser-direct.js deleted file mode 100644 index 11a9fc2..0000000 --- a/browser-direct.js +++ /dev/null @@ -1,15 +0,0 @@ -/** @module audio-speaker/browser */ - -'use strict'; - -var Writer = require('web-audio-stream/index'); -var context = require('audio-context'); - -module.exports = Speaker; - - -function Speaker(options) { - let ctx = options && options.context || context; - - return Writer(ctx.destination, options); -} diff --git a/browser-stream.js b/browser-stream.js deleted file mode 100644 index db3f852..0000000 --- a/browser-stream.js +++ /dev/null @@ -1,22 +0,0 @@ -/** @module audio-speaker/browser */ - -'use strict'; - -var inherits = require('inherits'); -var WAAStream = require('web-audio-stream/writable'); -var context = require('audio-context'); - - -module.exports = Speaker; - - -inherits(Speaker, WAAStream); - - -function Speaker(options) { - if (!(this instanceof Speaker)) return new Speaker(options); - - let ctx = options && options.context || context; - - WAAStream.call(this, ctx.destination, options); -} diff --git a/browser.js b/browser.js new file mode 100644 index 0000000..c3c34cc --- /dev/null +++ b/browser.js @@ -0,0 +1,22 @@ +/** @module audio-speaker/browser */ +'use strict' + +var objectAssign = require('object-assign') +var createContext = require('audio-context') +var createWriter = require('web-audio-write') + +module.exports = Speaker + +function Speaker (opts) { + var options = {} + + options = objectAssign({ + channels: 1, + sampleRate: 44100 + }, opts) + + var ctx = options.context || createContext(options) + var write = createWriter(ctx.destination, options) + + return write +} diff --git a/cli.js b/cli.js deleted file mode 100644 index e69de29..0000000 diff --git a/direct.js b/direct.js deleted file mode 100644 index 52bdf02..0000000 --- a/direct.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @module audio-speaker/direct - * - * Outputs chunk of data to audio output in node - * - */ -'use strict'; - -const pcm = require('pcm-util'); -const isAudioBuffer = require('is-audio-buffer'); -const extend = require('xtend/mutable'); - -const format = { - float: false, - interleaved: true, - bitDepth: 16, - signed: true -}; - - -let NodeSpeaker, Sink; - -try { - NodeSpeaker = require('speaker'); -} -catch (e) { - console.warn('`speaker` package was not found. Using `audio-sink` instead.'); - Sink = require('audio-sink/direct'); -} - - -module.exports = function (opts) { - opts = extend({}, format, opts); - - return opts.sink || !NodeSpeaker ? createSink(opts) : createSpeaker(opts); -} - - -/** - * Speaker is just a format wrapper for node-speaker, - * as node-speaker doesn’t support any input format in some platforms, like windows. - * So we need to force the most safe format. - * - * @constructor - */ -function createSpeaker (opts) { - //create node-speaker with default options - the most cross-platform case - let speaker = new NodeSpeaker(opts); - let ended = false; - - //FIXME: sometimes this lil fckr does not end stream hanging tests - write.end = () => { - ended = true; - write(true); - } - - return write; - - function write (chunk, cb) { - if (chunk == null || chunk === true || ended) { - ended = true; - cb && cb(true); - return; - } - - let buf = isAudioBuffer(chunk) ? pcm.toBuffer(chunk, format) : chunk; - speaker.write(buf, () => { - if (ended) { - speaker.close(); - speaker.end(); - return cb && cb(true); - } - cb && cb(null, chunk); - }); - } -} - -function createSink (opts) { - let ended = false; - - let sampleRate = opts.sampleRate || 44100; - let samplesPerFrame = opts.samplesPerFrame || 1024; - - let sink = Sink((data, cb) => { - if (ended || data == null || data == true) return cb && cb(true); - cb && setTimeout(cb, samplesPerFrame / sampleRate); - }); - - sink.end = () => { - ended = true; - sink(true); - } - - return sink; -} - - diff --git a/element.html b/element.html deleted file mode 100644 index a5d18b7..0000000 --- a/element.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/element.js b/element.js deleted file mode 100644 index 4ded7d0..0000000 --- a/element.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * html element - * - * Does not export anything as it is not a module, it is pre-cooked web-component. - * - * To make it work, browserify bundle first with dependencies: - * `browserify -r audio-element -r audio-speaker` - * and connect it before the import link: - * - * - * @module audio-speaker/element - */ -'use strict'; - -var Speaker = require('audio-speaker'); -var AudioElement = require('audio-element'); - - -/** - * Audio speaker element API - */ -var SpeakerProto = Object.create(AudioElement.prototype); - -SpeakerProto.createdCallback = function () { - this.stream = Speaker(); - - AudioElement.prototype.createdCallback.call(this); -}; - - -/** Meta */ -SpeakerProto.label = 'Speaker'; -SpeakerProto.thumbnail = ''; -SpeakerProto.description = 'Output the sound'; - - -/** Connection logic */ -SpeakerProto.numberOfOutputs = 0; -SpeakerProto.numberOfInputs = 1; - - -document.registerElement('audio-speaker', { - prototype: SpeakerProto -}); diff --git a/index.js b/index.js index 861c11e..ad70661 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,172 @@ -/** @module audio-speaker */ -'use strict'; -module.exports = require('./direct'); +/** @module audio-speaker/index */ +'use strict' + +var convert = require('pcm-convert') +var binding = require('audio-mpg123') +var isAudioBuffer = require('is-audio-buffer') +function noop () {} + +module.exports = Speaker + +/** + * The Speaker function initializes a new audio handler, + * then returns the write method to output audio to. + * + * @param {Object} opts options for the speaker + * @return {Function} write write audio from a buffer or audiobuffer + * @module Speaker + * @api public + */ +function Speaker (opts) { + var options = Object.assign({ + channels: 1, + format: 'int16', + sampleRate: 44100, + autoFlush: true + }, opts) + + var format = Speaker.getFormat(options.format) + if (!format) throw new Error('Invalid format options.') + + // Options we use directly + var channels = options.channels + var sampleRate = options.sampleRate + var autoFlush = options.autoFlush + var chunkSize = NaN//1024 + + // Writing state + var busy = false + + var handler = binding.create((success) => { + if (!success) throw new Error('Failed to create the audio handler.') + }) + + if (handler) { + binding.open(handler, sampleRate, channels, format, (success) => { + if (!success) throw new Error('Could not start the audio output with these properties.') + }) + } + + write.end = end + return write + + /** + * The write function takes a buffer or audiobuffer and + * writes it to the speaker output. If the chunks are too + * large it will break it up and put the remainding chunks + * into a queue. + * NOTE: You can only write new chunks once the callback is + * called with no errors. + * + * @param {AudioBuffer} chunk (or Buffer) containing the data to be output + * @param {Function} callback callback with error and chunk parameters + * @return void + * @api public + */ + function write (buf, callback) { + if (!callback) callback = noop + if (!handler) return callback(new Error('Write occurred after the speaker closed.')) + if (busy) return callback(new Error('Write occurred before the speaker flushed.')) + + //make sure audio buffer is converted to proper format + if (isAudioBuffer(buf)) { + if (buf._data) buf = buf._data + else { + var arr = new Float32Array(buf.length * channels) + for (var c = 0, l = buf.length; c < channels; c++) { + arr.set(buf.getChannelData(c), c*l) + } + buf = arr + } + + buf = Buffer.from(convert(buf, { + dtype: 'float32', + interleaved: false, + channels: channels + }, { + dtype: options.format, + interleaved: true + }).buffer + ) + } + + next(buf, null, callback) + + function next (chunk, rest, callback) { + if (!handler) return callback(new Error('Speaker closed while writing')) + + busy = true + + var queue = !rest || !rest.length ? chunk : Buffer.concat([rest, chunk]) + if (!queue) queue = new Buffer(0) // meh + + var output = queue.length > chunkSize ? queue.slice(0, chunkSize) : queue + var remaining = queue.length > chunkSize ? queue.slice(chunkSize, queue.length) : new Buffer(0) + + binding.write(handler, output, output.length, (written) => { + // Play next chunk + if (rest && rest.length) return next(null, remaining, callback) + // Stream finished. Flush and callback + var err = null + if (autoFlush) { + binding.flush(handler, (success) => { + if (!success) err = new Error('Flushing speaker failed') + }) + } + busy = false + callback(err) + }) + } + } + + /** + * The end function closes the speaker and stops + * it from writing anymore data. The output data + * that was already written will be flushed if the + * auto flush option is set. + * NOTE: You cannot write anymore data after closing the speaker. + * + * @return void + * @api public + */ + function end () { + if (!handler) return + + binding.flush(handler, (success) => { + if (!success) throw new Error('Failed to flush speaker.') + }) + + binding.close(handler, (success) => { + if (!success) throw new Error('Could not close the speaker.') + handler = null + }) + } +} + +Speaker.getFormat = function (format) { + switch (format) { + case 'uint8': + case 'uint8_clamped': + return binding.MPG123_ENC_UNSIGNED_8; + case 'uint16': + return binding.MPG123_ENC_UNSIGNED_16; + case 'uint24': + return binding.MPG123_ENC_UNSIGNED_24; + case 'uint32': + return binding.MPG123_ENC_UNSIGNED_32; + case 'int8': + return binding.MPG123_ENC_SIGNED_8; + case 'int16': + return binding.MPG123_ENC_SIGNED_16; + case 'int24': + return binding.MPG123_ENC_SIGNED_24; + case 'int32': + return binding.MPG123_ENC_SIGNED_32; + case 'array': + case 'float32': + return binding.MPG123_ENC_FLOAT_32; + case 'float64': + return binding.MPG123_ENC_FLOAT_64; + } +} + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..939ea05 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1570 @@ +{ + "name": "audio-speaker", + "version": "2.0.0-5", + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "optional": true + }, + "acorn": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=" + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "optional": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, + "atob-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-1.0.0.tgz", + "integrity": "sha1-uI3KYAaSK5YglPdVaCa6sxxKKWs=", + "dev": true + }, + "audio-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-4.0.1.tgz", + "integrity": "sha1-YrYe7L/KplFHFQ0Y/kP3Z6yANLg=" + }, + "audio-buffer-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer-list/-/audio-buffer-list-3.2.1.tgz", + "integrity": "sha512-ledga5njMOlJMG/yifwqQvscho97IadzhddR7OyTvyIKzyqXsA8YMvC+yAd2B3EmzlIlJJHd4zbmQF3/xlLhcw==" + }, + "audio-buffer-utils": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/audio-buffer-utils/-/audio-buffer-utils-5.0.1.tgz", + "integrity": "sha1-5i2RAQo3Yg3W5Qx9nUQ4KH/afLI=" + }, + "audio-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/audio-context/-/audio-context-1.0.1.tgz", + "integrity": "sha1-zsTbis5u9KrL8Q7vCXekVxRo1Ks=" + }, + "audio-generator": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/audio-generator/-/audio-generator-2.1.2.tgz", + "integrity": "sha1-lEhPofavlHuNoDhi9NzuhLe81ak=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-2.4.6.tgz", + "integrity": "sha1-L5e9srucpG0i07AdQzT0mSTromA=", + "dev": true + }, + "audio-buffer-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/audio-buffer-utils/-/audio-buffer-utils-4.3.2.tgz", + "integrity": "sha1-1VX67Y1s7rEgYZ45+mkTdPIQM4A=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + } + } + }, + "audio-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/audio-context/-/audio-context-1.0.1.tgz", + "integrity": "sha1-zsTbis5u9KrL8Q7vCXekVxRo1Ks=", + "dev": true + }, + "pcm-util": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-2.1.0.tgz", + "integrity": "sha1-UazkawngEX+5L2VPYy3LLtnIYGU=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + } + } + } + } + }, + "audio-lena": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/audio-lena/-/audio-lena-2.1.0.tgz", + "integrity": "sha1-lCuItva4a4uZgyXVSmltNbLfCt4=", + "dev": true + }, + "audio-mpg123": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/audio-mpg123/-/audio-mpg123-1.2.3.tgz", + "integrity": "sha1-rvNk1JQafv0HJ47QPkyXhiwGdOA=", + "optional": true + }, + "audio-sink": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/audio-sink/-/audio-sink-1.1.6.tgz", + "integrity": "sha1-4UVOsTeFIimNIXC3ywMsM/0faIU=" + }, + "audio-through": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/audio-through/-/audio-through-2.2.3.tgz", + "integrity": "sha1-FPyMN7YT0chwz67gS/RFTCiVn78=", + "dev": true, + "dependencies": { + "audio-buffer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/audio-buffer/-/audio-buffer-3.2.1.tgz", + "integrity": "sha1-y/8sFXf7CvxckjKQLVQ7L5bdQz0=", + "dev": true + }, + "pcm-util": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-2.1.0.tgz", + "integrity": "sha1-UazkawngEX+5L2VPYy3LLtnIYGU=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + } + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "optional": true + }, + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=" + }, + "buffer-to-arraybuffer": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz", + "integrity": "sha1-8+Xj9vJjLHHnzevnbtFxj61CHUw=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "circular-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", + "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", + "dev": true + }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true + }, + "cli-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "data-uri-regex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/data-uri-regex/-/data-uri-regex-0.1.4.tgz", + "integrity": "sha1-Hh22yDl+yopI7NtVrRuSfsC7rC4=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "optional": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true + }, + "es-abstract": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", + "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", + "dev": true + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.0.0.tgz", + "integrity": "sha1-cnfAFDf99B3M0WjVqg5Jt1yh8mA=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true + }, + "espree": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", + "dev": true + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "optional": true + }, + "external-editor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", + "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", + "dev": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true + }, + "flat-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "dev": true + }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "optional": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=" + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "optional": true + }, + "function-bind": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==" + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=" + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "optional": true + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "optional": true + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "optional": true + }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "dev": true + }, + "ignore": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", + "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "optional": true + }, + "inquirer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz", + "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "dev": true + } + } + }, + "is-audio-buffer": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/is-audio-buffer/-/is-audio-buffer-1.0.11.tgz", + "integrity": "sha1-Hs443PML9U3aNvIKRS63J9I96zY=" + }, + "is-browser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.0.1.tgz", + "integrity": "sha1-i/C695mpxi/Z3lvO5M8zl8PnUpo=" + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-data-uri": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-data-uri/-/is-data-uri-0.1.0.tgz", + "integrity": "sha1-Ru5ntjwYwf+gvU36ss0sgccoI38=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=" + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", + "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "js-yaml": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", + "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jschardet": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", + "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=" + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.1.tgz", + "integrity": "sha1-1oaT9rNLtB1mvGizpPne/HnXFJs=", + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negative-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/negative-index/-/negative-index-1.0.2.tgz", + "integrity": "sha1-uws0n53oCHkybPpUxW+2tnykeI0=" + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "optional": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true + }, + "npmlog": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "optional": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.2.2.tgz", + "integrity": "sha1-yCEV5PzIiK6hTWTCLk8X9qcNXlo=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "optional": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "pcm-util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pcm-util/-/pcm-util-3.0.0.tgz", + "integrity": "sha1-L33/SBOidIHZlffSwY2hdnj6MDw=" + }, + "pcm-volume": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pcm-volume/-/pcm-volume-1.0.0.tgz", + "integrity": "sha1-6qhRyUloq24ULOLhKVNwi+Sn8MA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "optional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true + }, + "pluralize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", + "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "optional": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "optional": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", + "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "optional": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=" + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "optional": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=" + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", + "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "dev": true + } + } + }, + "tape": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.6.3.tgz", + "integrity": "sha1-Y353WB6ass4XV36b1M5PV1gG2LY=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=" + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "optional": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "dev": true + }, + "to-array-buffer": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-1.2.4.tgz", + "integrity": "sha1-fv3DGUpaDSsLqT+6nT7cM6EllHM=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "optional": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedarray-methods": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typedarray-methods/-/typedarray-methods-1.0.1.tgz", + "integrity": "sha512-fstWAa225OZ856/4npMqgJP6U1U3vTWnqkn9wokZXzME9pORW9dV8u/v1VRGpo584udKMvCIYlNXzKoIb+UUGg==", + "dev": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "optional": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "optional": true + }, + "web-audio-write": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/web-audio-write/-/web-audio-write-1.2.1.tgz", + "integrity": "sha1-iFlr1ch/8QvFloCXhJ1pHtyHvm4=" + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } +} diff --git a/package.json b/package.json index d59d229..d7ae78b 100644 --- a/package.json +++ b/package.json @@ -1,59 +1,51 @@ { "name": "audio-speaker", - "version": "1.4.3", - "description": "Output audio data to speaker in browser/node", - "main": "stream.js", + "version": "2.0.0-5", + "description": "Write audio to the speaker in node/browser", "scripts": { - "preversion": "npm run lint && npm run test", - "lint": "eslint *.js --ignore-pattern test*", - "test:browser": "budo test.js", - "test": "node test" + "test": "node test", + "test:browser": "budo test", + "lint": "eslint *.js --ignore-pattern test*" }, "repository": { "type": "git", - "url": "https://github.com/audiojs/audio-speaker" + "url": "git+https://github.com/audiojs/audio-speaker.git" }, + "main": "./index", + "browser": "./browser", "keywords": [ + "PCM", + "output", "audio", "audiojs", - "pcm", - "speaker", - "web-audio", - "sound", - "sink" + "binding", + "native" + ], + "author": "Connor Hartley (https://github.com/connorhartley)", + "contributors": [ + "Jamen Marz ", + "Dima Yv " ], - "browser": { - "./direct.js": "./browser-direct.js", - "./stream.js": "./browser-stream.js" - }, - "author": "Dima Yv ", "license": "MIT", "bugs": { "url": "https://github.com/audiojs/audio-speaker/issues" }, - "homepage": "https://github.com/audiojs/audio-speaker", + "homepage": "https://github.com/audiojs/audio-speaker#readme", + "dependencies": { + "audio-context": "^1.0.1", + "is-audio-buffer": "^1.0.11", + "object-assign": "^4.1.1", + "pcm-convert": "^1.3.1", + "web-audio-write": "^1.2.1" + }, "devDependencies": { - "audio-buffer-utils": "^3.1.2", - "audio-context": "^0.1.0", - "audio-generator": "^2.0.1", - "eslint": "^3.4.0", - "insert-styles": "^1.2.1", - "pcm-util": "^2.0.2", + "audio-buffer-utils": "^5.0.1", + "audio-generator": "^2.1.2", + "audio-lena": "^2.1.0", "pcm-volume": "^1.0.0", - "tst": "^1.1.8", - "wavefont": "^1.2.1" + "tape": "^4.6.3" }, "optionalDependencies": { - "audio-sink": "^1.0.2", - "speaker": "^0.3.0" - }, - "dependencies": { - "audio-through": "^2.1.1", - "inherits": "^2.0.1", - "is-audio-buffer": "^1.0.1", - "pcm-util": "^2.0.3", - "pull-stream": "^3.4.5", - "web-audio-stream": "^2.1.2", - "xtend": "^4.0.1" + "audio-mpg123": "^1.2.3" } } diff --git a/pull.js b/pull.js deleted file mode 100644 index 95c1b95..0000000 --- a/pull.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @module audio-speaker/pull - * - */ -'use strict'; - -const Writer = require('./direct'); -const drain = require('pull-stream/sinks/drain'); -const asyncMap = require('pull-stream/throughs/async-map'); -const pull = require('pull-stream/pull'); - - -module.exports = function PullSpeaker (opts) { - let sinkFn = Writer(opts); - let d = drain(); - - let sink = pull(asyncMap(sinkFn), d); - - sink.abort = d.abort; - - return sink; -} diff --git a/readme.md b/readme.md index e1fe16c..ab81f97 100644 --- a/readme.md +++ b/readme.md @@ -1,63 +1,69 @@ -#audio-speaker [![Build Status](https://travis-ci.org/audiojs/audio-speaker.svg?branch=master)](https://travis-ci.org/audiojs/audio-speaker) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) +# audio-speaker [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/audiojs/audio-speaker.svg)](https://travis-ci.org/audiojs/audio-speaker) [![Greenkeeper badge](https://badges.greenkeeper.io/audiojs/audio-speaker.svg)](https://greenkeeper.io/) -Output audio stream to speaker in node or browser. +Write [AudioBuffer](https://github.com/audiojs/audio-buffer) to the speaker in node or browser. -[![npm install audio-speaker](https://nodei.co/npm/audio-speaker.png?mini=true)](https://npmjs.org/package/audio-speaker/) +```js +var generator = require('audio-generator') +var speaker = require('audio-speaker') +// Create a 440Hz sine wave +var sine = generator(time => { + return Math.sin(PI * 2 * time * 440) +}) -### Use as a stream +(function loop () { + speaker(sine(), loop) +})() +``` -```js -var Speaker = require('audio-speaker/stream'); -var Generator = require('audio-generator/stream'); +See more examples in [`test`](test.js). -Generator(function (time) { - //panned unisson effect - var τ = Math.PI * 2; - return [Math.sin(τ * time * 441), Math.sin(τ * time * 439)]; -}) -.pipe(Speaker({ - //PCM input format defaults, optional. - //channels: 2, - //sampleRate: 44100, - //byteOrder: 'LE', - //bitDepth: 16, - //signed: true, - //float: false, - //interleaved: true, -})); + +## Install + +```sh +npm i audio-speaker ``` -### Use as a pull-stream +**Note:** When only on browser you can use `--no-optional` to skip downloading the Node.js backend. + +## Usage + +### `let speaker = createSpeaker(options?)` + +Accepts the options: + + - `autoFlush` (default `true`) + - `channels` (default `1`) + - `sampleRate` (default `44100`) + +Returns a speaker funciton you can use to write `AudioBuffer`s. ```js -const pull = require('pull-stream/pull'); -const speaker = require('audio-speaker/pull'); -const osc = require('audio-oscillator/pull'); +var speaker = createSpeaker() -pull(osc({frequency: 440}), speaker()); +// Or with options +var speaker = createSpeaker({ channels: 2, sampleRate: 48000 }) ``` -### Use directly +### `speaker(buf, done?)` -Speaker is [async-sink](https://github.com/audiojs/contributing/wiki/Streams-convention) with `fn(data, cb)` notation. +Writes an `AudioBuffer` to the speaker and plays it back. ```js -const createSpeaker = require('audio-speaker'); -const createGenerator = require('audio-generator'); +var sine = oscillator({ wave: 'sine', duration: 1 }) -let output = createSpeaker(); -let generate = createGenerator(t => Math.sin(t * Math.PI * 2 * 440)); - -(function loop (err, buf) { - let buffer = generate(); - output(buffer, loop); -})(); +write(sine(), err => { + // Played +}) ``` -#### Related +## Related + + - [`audio-speaker-stream`](https://github.com/audiojs/audio-speaker-stream) for use with [Node streams](https://nodejs.org/api/stream.html). + - [`pull-audio-speaker`](https://github.com/audiojs/pull-audio-speaker) for a [pull-stream](https://github.com/pull-stream/pull-stream) sink function. + - [`audio-mpg123`](https://github.com/audiojs/audio-mpg123): Fork of mpg123 made to suit audio-speaker. + +## License -> [web-audio-stream](https://github.com/audiojs/web-audio-stream) — stream data to web-audio.
-> [audio-through](http://npmjs.org/package/audio-through) — universal stream for processing audio.
-> [node-speaker](http://npmjs.org/package/speaker) — output pcm stream to speaker in node.
-> [audio-feeder](https://github.com/brion/audio-feeder) — cross-browser speaker for pcm data.
+© 2017 AudioJS. MIT License diff --git a/stream.js b/stream.js deleted file mode 100644 index 67203c1..0000000 --- a/stream.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @module audio-speaker - * - * Wraps node-speaker to ensure format. - * - */ -'use strict'; - -var inherits = require('inherits'); -var extend = require('xtend/mutable'); -var Through = require('audio-through'); - -var NodeSpeaker; -try { - NodeSpeaker = require('speaker'); -} catch (e) { - console.warn('`speaker` package was not found. Using `audio-sink` instead.'); - NodeSpeaker = require('audio-sink'); -} - -/** - * Speaker is just a format wrapper for node-speaker, - * as node-speaker doesn’t support any input format in some platforms, like windows. - * So we need to force the most safe format. - * - * @constructor - */ -function AudioSpeaker (opts) { - if (!(this instanceof AudioSpeaker)) { - return new AudioSpeaker(opts); - } - - Through.call(this, opts); - - //create node-speaker with default options - the most cross-platform case - this.speaker = new NodeSpeaker({ - channels: this.channels - }); - - this.pipe(this.speaker); -} - -inherits(AudioSpeaker, Through); - - -/** - * Predefined format for node-speaker - */ -extend(AudioSpeaker.prototype, { - float: false, - interleaved: true, - bitDepth: 16, - signed: true -}); - - -module.exports = AudioSpeaker; diff --git a/test.html b/test.html deleted file mode 100644 index bab0f2e..0000000 --- a/test.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Audio-speaker browser and custom element test - - - - - - - - - \ No newline at end of file diff --git a/test.js b/test.js index 52fc521..60feaa4 100644 --- a/test.js +++ b/test.js @@ -1,181 +1,73 @@ -'use strict'; - -var Speaker = require('./stream'); -var Generator = require('audio-generator/stream'); -var Generate = require('audio-generator/index'); -var Readable = require('stream').Readable; -var util = require('audio-buffer-utils'); -var pcm = require('pcm-util'); -var Through = require('audio-through'); -Through.log = true; -var Volume = require('pcm-volume'); -var test = require('tst')//.only(); -var SpeakerWriter = require('./direct'); -var pull = require('pull-stream'); -var PullSpeaker = require('./pull'); -var pullGenerator = require('audio-generator/pull'); - - -require('insert-styles')(` - @font-face { - font-family: wavefont; - src: url(./wavefont.otf) format("opentype"); - } -`); - -test('Pure function', function (done) { - let generate = Generate(t => { - return Math.sin(t * Math.PI * 2 * 440); - }, 1); - - let write = SpeakerWriter(); - - (function loop (err, buf) { - if (err) return write(null); - write(generate(buf), loop) - })(); - - setTimeout(() => { - write(null); - done(); - }, 200); -}); - -test('Pull stream', function (done) { - let out = PullSpeaker(); - - pull( - pullGenerator(time => 2 * time * 440 - 1, {frequency: 440}), - out - ); - - setTimeout(() => { - out.abort(); - done(); - }, 500); -}); - -test('Cleanness of wave', function () { - Through(function (buffer) { - var self = this; - util.fill(buffer, function (sample, idx, channel) { - return Math.sin(Math.PI * 2 * (self.count + idx) * 440 / 44100); - }); - - if (this.time > 1) return this.end(); - - return buffer; - }) - .pipe(Speaker()); - // .pipe(WAASteam(context.destination)); -}); - -test('Feed audio-through', function () { - Generator({ - generate: function (time) { - return [ - Math.sin(Math.PI * 2 * time * 538 ) / 5, - Math.sin(Math.PI * 2 * time * 542 ) / 5 - // Math.random() - ] - }, - duration: .4 - }).pipe(Speaker()); -}); - -test('Feed raw pcm', function () { - var count = 0; - Readable({ - read: function (size) { - var abuf = util.create(2, 1024, 44100); - - //EGG: swap ch & i and hear wonderful sfx - util.fill(abuf, function (v, i, ch) { - v = Math.sin(Math.PI * 2 * ((count + i)/44100) * (738 + ch*2) ) / 5; - return v; - }); - - count += 1024; - - if (count > 1e4 ) return this.push(null); - - let buf = pcm.toBuffer(abuf); - - this.push(buf); - } - }) - .pipe(Speaker({ - channels: 2 - })); -}); - -//FIXME: use transform stream here to send floats data to speaker -test.skip('Feed custom pcm', function () { - var count = 0; - Readable({ - // objectMode: 1, - read: function (size) { - var abuf = util.create(2, 1024, 44100); - - util.fill(abuf, function (v, i, ch) { - return Math.sin(Math.PI * 2 * ((count + i)/44100) * (938 + ch*2) ); - }); - - count += 1024; - - if (count > 1e4 ) return this.push(null); - - let buf = pcm.toBuffer(abuf, { - float: true - }); - - this.push(buf); - } - }).pipe(Speaker({ - channels: 2, - - //EGG: comment this and hear wonderful sfx - float: true - })); -}); - -test.skip('Feed random buffer size'); - -test('Volume case', function () { - Generator({ - generate: function (time) { - return [ - Math.sin(Math.PI * 2 * time * 1038 ) / 5, - Math.sin(Math.PI * 2 * time * 1042 ) / 5 - ]; - }, - duration: 1 - }) - .pipe(Volume(5)) - .pipe(Speaker()); -}); - - - - -//little debigger -if (typeof document !== 'undefined') { - var el = document.body.appendChild(document.createElement('div')); - el.style.cssText = ` - font-family: wavefont; - max-width: 100vw; - word-break: break-all; - white-space: pre-wrap; - font-size: 32px; - `; - - function draw (arr) { - let str = ''; - - for (let i = 0; i < arr.length; i++) { - str += String.fromCharCode(0x200 + Math.floor(arr[i] * 128 * 5)); - } - - el.innerHTML += '\n' + str; - } -} +'use strict' + +var test = require('tape') + +var util = require('audio-buffer-utils') +var LenaBuffer = require('audio-lena/raw') +var createSpeaker = require('./') +var createGenerator = require('audio-generator/direct') + + +test('play noise', t => { + t.plan(1) + + var write = createSpeaker() + + let buffer = util.create(10000) + util.noise(buffer) + + write(buffer, (err) => { + if (err) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + write.end() + t.pass('Output successful.') + } + }) +}) + + +test('play lena', t => { + t.plan(1) + + var write = createSpeaker({ channels: 1, float: false, bitDepth: 16, signed: true }) + var buf = util.create(LenaBuffer) + buf = util.slice(buf, 0, 44100) + + write(buf, (err) => { + if (err) { + t.error(err, 'Write callback caught an unexpected error.') + } else { + write.end() + t.pass('Output successful.') + } + }) +}) + +test('play sine', t => { + t.plan(1) + + var generate = createGenerator(time => { + return [ + Math.sin(Math.PI * 2 * time * 439), + Math.sin(Math.PI * 2 * time * 441) + ] + }, { duration: 1, channels: 2 }) + + var write = createSpeaker({ channels: 2, autoFlush: false }); + + setTimeout(() => { + write.end() + t.pass('Output successful.') + }, 500); + + (function loop (err) { + if (err) { + // Ignore errors as we are intentionally cutting this short. + return + } else { + let buf = generate() + write(buf, loop) + } + })(); +}) diff --git a/todo.md b/todo.md deleted file mode 100644 index 4181ef1..0000000 --- a/todo.md +++ /dev/null @@ -1,16 +0,0 @@ -* Restrain buffers piping to node-speaker, bind to RT. Do not generate more than needed. - * node-speaker restrains pressure, but with a 3s buffer - it should be able to be regulated. -* replace node-speaker with good implementation. It fails on estimating big buffers -* Decrease buffer, significantly. Make gain work realtime -* Flash fallback -* Create scriptProcessorNode mode. As an alternative. -* For old browsers generate sound like t='data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgA',new Audio(t+btoa(t+S)).play() - * http://www.p01.org/JS1K_Speech_Synthesizer/ - -* Detect audioBufferSize based on some performance measure, to avoid GC glitches -* Test in Firefox, Opera, Safari, iOS Safari, IE, others. - -* Test variety of channels -* Test different sample rates - -* CLI \ No newline at end of file