From 126266e4d97cb53327548a7f724a916437f2d1d6 Mon Sep 17 00:00:00 2001 From: alfred Date: Tue, 31 Dec 2013 10:06:42 +0000 Subject: [PATCH] input objects with mono/stereo conversion --- lib/input.js | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mixer.js | 7 ++-- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 lib/input.js diff --git a/lib/input.js b/lib/input.js new file mode 100644 index 0000000..458220a --- /dev/null +++ b/lib/input.js @@ -0,0 +1,90 @@ +var + Writable = require('stream').Writable, + util = require('util'), + ; + +function Input(args) { + this.buffer = Buffer.concat([this.buffer, chunk]); + + if (typeof args === 'undefined') args = {}; + if (args.channels != 1 && args.channels != 2) args.channels = 2; + if (typeof args.sampleRate !== 'number' || args.sampleRate < 1) args.sampleRate = 44100; + + this.buffer = new Buffer(0); + + if (args.channels == 1) this.readMono = this.read; + if (args.channels == 2) this.readStereo = this.read; + + if (args.bitDepth == 8) { + this.readSample = Buffer.readInt8; + this.writeSample = Buffer.writeInt8; + this.sampleByteLength = 1; + } + else if (args.bitDepth == 32) { + this.readSample = Buffer.readInt32LE; + this.writeSample = Buffer.writeInt32LE; + this.sampleByteLength = 4; + } + else { + args.bitDepth = 16; + this.readSample = Buffer.readInt16LE; + this.writeSample = Buffer.writeInt16LE; + this.sampleByteLength = 2; + } + + this.channels = args.channels; + this.bitDepth = args.bitDepth; + this.sampleRate = args.sampleRate; +} + +util.inherits(Input, Writable); + +Input.prototype.read = function (samples) { + var bytes = samples * (this.bitDepth / 8) * this.channels; + if (this.buffer.length < bytes) bytes = this.buffer.length; + var r = this.buffer.slice(0, bytes); + this.buffer = this.buffer.slice(bytes); + return r; +} + +Input.prototype.readMono = function (samples) { + // This function will be overridden by this.read, if input already is mono. + var stereoBuffer = this.read(samples); + var monoBuffer = new Buffer(stereoBuffer.length / 2); + var s = this.availSamples(stereoBuffer.length); + for (var i = 0; i < s; i++) { + var l = this.readSample.call(stereoBuffer, i * this.sampleByteLength * 2); + var r = this.readSample.call(stereoBuffer, (i * this.sampleByteLength * 2) + this.sampleByteLength); + this.writeSample.call(monoBuffer, Math.round((l + r) / 2), i * this.sampleByteLength); + } + return monoBuffer; +} + +Input.prototype.readStereo = function (samples) { + // This function will be overridden by this.read, if input already is stereo. + var monoBuffer = this.read(samples); + var stereoBuffer = new Buffer(monoBuffer.length * 2); + var s = this.availSamples(monoBuffer.length); + for (var i = 0; i < s; i++) { + var m = this.readSample.call(monoBuffer, i * this.sampleByteLength); + this.writeSample.call(stereoBuffer, m, i * this.sampleByteLength * 2); + this.writeSample.call(stereoBuffer, m, (i * this.sampleByteLength * 2) + this.sampleByteLength); + } + return stereoBuffer; +} + +Input.availSamples = function (length) { + if (typeof length === 'undefined') length = this.buffer.length; + return Math.floor(length / ((this.bitDepth / 8) * this.channels)); +} + +Input.prototype._write = function (chunk, encoding, next) { + /* + if (!Buffer.isBuffer(chunk)) { + chunk = new Buffer(chunk, encoding); + } + */ + this.buffer = Buffer.concat([this.buffer, chunk]); + next(); +} + diff --git a/lib/mixer.js b/lib/mixer.js index 0547782..497f02f 100644 --- a/lib/mixer.js +++ b/lib/mixer.js @@ -1,13 +1,15 @@ var Readable = require('stream').Readable, - util = require('util') + util = require('util'), + + Input = require('./input.js') ; function Mixer(args) { if (typeof args === 'undefined') args = {}; if (args.channels != 1 && args.channels != 2) args.channels = 2; - if (args.bitDepth != 8 && args.bitDepth != 16 && args.bitDepth != 32) args.channels = 2; + if (args.bitDepth != 8 && args.bitDepth != 16 && args.bitDepth != 32) args.bitDepth = 16; if (typeof args.sampleRate === 'number' || args.sampleRate < 1) args.sampleRate = 44100; this.channels = args.channels; @@ -27,6 +29,7 @@ Mixer.prototype.input = function (args) { if (typeof args === 'undefined') args = {}; var input = new Input({ + mixer: this, channels: args.channels || this.channels, bitDepth: args.bitDepth || this.bitDepth, sampleRate: args.sampleRate || this.sampleRate