Comparing version 0.1.3 to 0.2.0
0.2.0 / 2014-06-22 | ||
================== | ||
* gitignore: ignore root-level dev files | ||
* index: pass the `format` directly to the native open() binding | ||
* index: ensure a valid and supported "format" is given to Speaker instance | ||
* test: add quotes to test names | ||
* index: add `getFormat()` and `isSupported()` functions | ||
* binding: export the `MPG123_ENC_*` constants | ||
* binding: export the result of `get_formats()` | ||
* mpg123: add 64-bit float playback support for CoreAudio backend | ||
* index: use %o formatter some more | ||
* index: default `float` to 32-bit `bitDepth` | ||
0.1.3 / 2014-06-15 | ||
@@ -3,0 +17,0 @@ ================== |
87
index.js
@@ -32,2 +32,51 @@ | ||
/** | ||
* Returns the `MPG123_ENC_*` constant that corresponds to the given "format" | ||
* object, or `null` if the format is invalid. | ||
* | ||
* @param {Object} format - format object with `channels`, `sampleRate`, `bitDepth`, etc. | ||
* @return {Number} MPG123_ENC_* constant, or `null` | ||
* @api public | ||
*/ | ||
exports.getFormat = function getFormat (format) { | ||
var f = null; | ||
if (format.bitDepth == 32 && format.float && format.signed) { | ||
f = binding.MPG123_ENC_FLOAT_32; | ||
} else if (format.bitDepth == 64 && format.float && format.signed) { | ||
f = binding.MPG123_ENC_FLOAT_64; | ||
} else if (format.bitDepth == 8 && format.signed) { | ||
f = binding.MPG123_ENC_SIGNED_8; | ||
} else if (format.bitDepth == 8 && !format.signed) { | ||
f = binding.MPG123_ENC_UNSIGNED_8; | ||
} else if (format.bitDepth == 16 && format.signed) { | ||
f = binding.MPG123_ENC_SIGNED_16; | ||
} else if (format.bitDepth == 16 && !format.signed) { | ||
f = binding.MPG123_ENC_UNSIGNED_16; | ||
} else if (format.bitDepth == 24 && format.signed) { | ||
f = binding.MPG123_ENC_SIGNED_24; | ||
} else if (format.bitDepth == 24 && !format.signed) { | ||
f = binding.MPG123_ENC_UNSIGNED_24; | ||
} else if (format.bitDepth == 32 && format.signed) { | ||
f = binding.MPG123_ENC_SIGNED_32; | ||
} else if (format.bitDepth == 32 && !format.signed) { | ||
f = binding.MPG123_ENC_UNSIGNED_32; | ||
} | ||
return f; | ||
} | ||
/** | ||
* Returns `true` if the given "format" is playable via the "output module" | ||
* that was selected during compilation, or `false` if not playable. | ||
* | ||
* @param {Number} format - MPG123_ENC_* format constant | ||
* @return {Boolean} true if the format is playable, false otherwise | ||
* @api public | ||
*/ | ||
exports.isSupported = function isSupported (format) { | ||
if ('number' !== typeof format) format = exports.getFormat(format); | ||
return (binding.formats & format) === format; | ||
} | ||
/** | ||
* The `Speaker` class accepts raw PCM data written to it, and then sends that data | ||
@@ -86,18 +135,28 @@ * to the default output device of the OS. | ||
if (null == this.channels) { | ||
debug('setting default "channels": %o', 2); | ||
debug('setting default %o: %o', 'channels', 2); | ||
this.channels = 2; | ||
} | ||
if (null == this.bitDepth) { | ||
debug('setting default "bitDepth": %o', 16); | ||
this.bitDepth = 16; | ||
var depth = this.float ? 32 : 16; | ||
debug('setting default %o: %o', 'bitDepth', depth); | ||
this.bitDepth = depth; | ||
} | ||
if (null == this.sampleRate) { | ||
debug('setting default "sampleRate", %o', 44100); | ||
debug('setting default %o: %o', 'sampleRate', 44100); | ||
this.sampleRate = 44100; | ||
} | ||
if (null == this.signed) { | ||
debug('setting default "signed": %o', this.bitDepth != 8); | ||
debug('setting default %o: %o', 'signed', this.bitDepth != 8); | ||
this.signed = this.bitDepth != 8; | ||
} | ||
var format = exports.getFormat(this); | ||
if (null == format) { | ||
throw new Error('invalid PCM format specified'); | ||
} | ||
if (!exports.isSupported(format)) { | ||
throw new Error('specified PCM format is not supported by "' + binding.name + '" backend'); | ||
} | ||
// calculate the "block align" | ||
@@ -109,3 +168,3 @@ this.blockAlign = this.bitDepth / 8 * this.channels; | ||
this.audio_handle = new Buffer(binding.sizeof_audio_output_t); | ||
var r = binding.open(this.audio_handle, this); | ||
var r = binding.open(this.audio_handle, this.channels, this.sampleRate, format); | ||
if (0 !== r) { | ||
@@ -131,23 +190,23 @@ throw new Error('open() failed: ' + r); | ||
if (null != opts.channels) { | ||
debug('setting "channels": %o', opts.channels); | ||
debug('setting %o: %o', 'channels', opts.channels); | ||
this.channels = opts.channels; | ||
} | ||
if (null != opts.bitDepth) { | ||
debug('setting "bitDepth": %o', opts.bitDepth); | ||
debug('setting %o: %o', "bitDepth", opts.bitDepth); | ||
this.bitDepth = opts.bitDepth; | ||
} | ||
if (null != opts.sampleRate) { | ||
debug('setting "sampleRate": %o', opts.sampleRate); | ||
debug('setting %o: %o', "sampleRate", opts.sampleRate); | ||
this.sampleRate = opts.sampleRate; | ||
} | ||
if (null != opts.float) { | ||
debug('setting "float": %o', opts.float); | ||
debug('setting %o: %o', "float", opts.float); | ||
this.float = opts.float; | ||
} | ||
if (null != opts.signed) { | ||
debug('setting "signed": %o', opts.signed); | ||
debug('setting %o: %o', "signed", opts.signed); | ||
this.signed = opts.signed; | ||
} | ||
if (null != opts.samplesPerFrame) { | ||
debug('setting "samplesPerFrame": %o', opts.samplesPerFrame); | ||
debug('setting %o: %o', "samplesPerFrame", opts.samplesPerFrame); | ||
this.samplesPerFrame = opts.samplesPerFrame; | ||
@@ -174,3 +233,3 @@ } | ||
Speaker.prototype._write = function (chunk, encoding, done) { | ||
debug('_write() (%d bytes)', chunk.length); | ||
debug('_write() (%o bytes)', chunk.length); | ||
@@ -197,3 +256,3 @@ if (this._closed) { | ||
if (self._closed) { | ||
debug('aborting remainder of write() call (%d bytes), since speaker is `_closed`', left.length); | ||
debug('aborting remainder of write() call (%o bytes), since speaker is `_closed`', left.length); | ||
return done(); | ||
@@ -200,0 +259,0 @@ } |
@@ -22,3 +22,3 @@ { | ||
], | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://tootallnate.net)", | ||
@@ -25,0 +25,0 @@ "repository": { |
@@ -96,3 +96,3 @@ | ||
it('should not throw an Error if native endianness is specified', function () { | ||
it('should not throw an Error if native "endianness" is specified', function () { | ||
assert.doesNotThrow(function () { | ||
@@ -103,3 +103,3 @@ new Speaker({ endianness: endianness }); | ||
it('should throw an Error if non-native endianness is specified', function () { | ||
it('should throw an Error if non-native "endianness" is specified', function () { | ||
assert.throws(function () { | ||
@@ -110,2 +110,14 @@ new Speaker({ endianness: opposite }); | ||
it('should throw an Error if a non-supported "format" is specified', function (done) { | ||
var speaker = new Speaker({ | ||
bitDepth: 31, | ||
signed: true | ||
}); | ||
speaker.once('error', function (err) { | ||
assert.equal('invalid PCM format specified', err.message); | ||
done(); | ||
}); | ||
speaker.write('a'); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
3411118
521