working example with one input to the mixer

This commit is contained in:
alfred 2014-01-01 02:58:53 +00:00
parent e32bd04065
commit 43c2556d8a
5 changed files with 97 additions and 23 deletions

46
example/example.js Normal file
View File

@ -0,0 +1,46 @@
var
fs = require('fs'),
Speaker = require('speaker'),
Mixer = require('../index.js'),
lame = require('lame')
;
/*
* Create the mixer and stream to speaker:
*/
var mixer = new Mixer({
channels: 1
});
var speaker = new Speaker({
channels: 1,
bitDepth: 16,
sampleRate: 44100
});
mixer.pipe(speaker);
/*
* Decode mp3 and add the stream as mixer input:
*/
var file = fs.createReadStream('example0.mp3');
var decoder = new lame.Decoder();
var mp3stream = file.pipe(decoder);
decoder.on('format', function (format) {
console.log(format);
mp3stream.pipe(mixer.input({
sampleRate: format.sampleRate,
channels: format.channels,
bitDepth: format.bitDepth
}));
});

BIN
example/example0.mp3 Normal file

Binary file not shown.

6
example/package.json Normal file
View File

@ -0,0 +1,6 @@
{
"dependencies": {
"lame": "*",
"speaker": "*"
}
}

View File

@ -1,10 +1,10 @@
var var
Writable = require('stream').Writable, Writable = require('stream').Writable,
util = require('util'), util = require('util')
; ;
function Input(args) { function Input(args) {
this.buffer = Buffer.concat([this.buffer, chunk]); Writable.call(this, args);
if (typeof args === 'undefined') args = {}; if (typeof args === 'undefined') args = {};
if (args.channels != 1 && args.channels != 2) args.channels = 2; if (args.channels != 1 && args.channels != 2) args.channels = 2;
@ -16,19 +16,19 @@ function Input(args) {
if (args.channels == 2) this.readStereo = this.read; if (args.channels == 2) this.readStereo = this.read;
if (args.bitDepth == 8) { if (args.bitDepth == 8) {
this.readSample = Buffer.readInt8; this.readSample = this.buffer.readInt8;
this.writeSample = Buffer.writeInt8; this.writeSample = this.buffer.writeInt8;
this.sampleByteLength = 1; this.sampleByteLength = 1;
} }
else if (args.bitDepth == 32) { else if (args.bitDepth == 32) {
this.readSample = Buffer.readInt32LE; this.readSample = this.buffer.readInt32LE;
this.writeSample = Buffer.writeInt32LE; this.writeSample = this.buffer.writeInt32LE;
this.sampleByteLength = 4; this.sampleByteLength = 4;
} }
else { else {
args.bitDepth = 16; args.bitDepth = 16;
this.readSample = Buffer.readInt16LE; this.readSample = this.buffer.readInt16LE;
this.writeSample = Buffer.writeInt16LE; this.writeSample = this.buffer.writeInt16LE;
this.sampleByteLength = 2; this.sampleByteLength = 2;
} }
@ -42,10 +42,13 @@ function Input(args) {
util.inherits(Input, Writable); util.inherits(Input, Writable);
Input.prototype.read = function (samples) { Input.prototype.read = function (samples) {
console.log('read()');
var bytes = samples * (this.bitDepth / 8) * this.channels; var bytes = samples * (this.bitDepth / 8) * this.channels;
if (this.buffer.length < bytes) bytes = this.buffer.length; if (this.buffer.length < bytes) bytes = this.buffer.length;
console.log(this.buffer.length);
var r = this.buffer.slice(0, bytes); var r = this.buffer.slice(0, bytes);
this.buffer = this.buffer.slice(bytes); this.buffer = this.buffer.slice(bytes);
console.log(this.buffer.length);
if (this.buffer.length <= 131072 && this.getMoreData !== null) { if (this.buffer.length <= 131072 && this.getMoreData !== null) {
var getMoreData = this.getMoreData; var getMoreData = this.getMoreData;
@ -57,6 +60,7 @@ Input.prototype.read = function (samples) {
} }
Input.prototype.readMono = function (samples) { Input.prototype.readMono = function (samples) {
console.log('readMono()');
// This function will be overridden by this.read, if input already is mono. // This function will be overridden by this.read, if input already is mono.
var stereoBuffer = this.read(samples); var stereoBuffer = this.read(samples);
var monoBuffer = new Buffer(stereoBuffer.length / 2); var monoBuffer = new Buffer(stereoBuffer.length / 2);
@ -70,6 +74,7 @@ Input.prototype.readMono = function (samples) {
} }
Input.prototype.readStereo = function (samples) { Input.prototype.readStereo = function (samples) {
console.log('readStereo()');
// This function will be overridden by this.read, if input already is stereo. // This function will be overridden by this.read, if input already is stereo.
var monoBuffer = this.read(samples); var monoBuffer = this.read(samples);
var stereoBuffer = new Buffer(monoBuffer.length * 2); var stereoBuffer = new Buffer(monoBuffer.length * 2);
@ -82,12 +87,15 @@ Input.prototype.readStereo = function (samples) {
return stereoBuffer; return stereoBuffer;
} }
Input.availSamples = function (length) { Input.prototype.availSamples = function (length) {
if (typeof length === 'undefined') length = this.buffer.length; if (typeof length === 'undefined') length = this.buffer.length;
return Math.floor(length / ((this.bitDepth / 8) * this.channels)); return Math.floor(length / ((this.bitDepth / 8) * this.channels));
} }
Input.prototype._write = function (chunk, encoding, next) { Input.prototype._write = function (chunk, encoding, next) {
console.log('_write', arguments);
/* /*
if (!Buffer.isBuffer(chunk)) { if (!Buffer.isBuffer(chunk)) {
chunk = new Buffer(chunk, encoding); chunk = new Buffer(chunk, encoding);
@ -103,3 +111,4 @@ Input.prototype._write = function (chunk, encoding, next) {
} }
module.exports = Input;

View File

@ -6,26 +6,29 @@ var
; ;
function Mixer(args) { function Mixer(args) {
Readable.call(this, args);
if (typeof args === 'undefined') args = {}; if (typeof args === 'undefined') args = {};
if (args.channels != 1 && args.channels != 2) args.channels = 2; if (args.channels != 1 && args.channels != 2) args.channels = 2;
if (typeof args.sampleRate === 'number' || args.sampleRate < 1) args.sampleRate = 44100; if (typeof args.sampleRate === 'number' || args.sampleRate < 1) args.sampleRate = 44100;
this.buffer = new Buffer(0);
this.bitDepth = args.bitDepth; this.bitDepth = args.bitDepth;
if (args.bitDepth == 8) { if (args.bitDepth == 8) {
this.readSample = Buffer.readInt8; this.readSample = this.buffer.readInt8;
this.writeSample = Buffer.writeInt8; this.writeSample = this.buffer.writeInt8;
this.sampleByteLength = 1; this.sampleByteLength = 1;
} }
else if (args.bitDepth == 32) { else if (args.bitDepth == 32) {
this.readSample = Buffer.readInt32LE; this.readSample = this.buffer.readInt32LE;
this.writeSample = Buffer.writeInt32LE; this.writeSample = this.buffer.writeInt32LE;
this.sampleByteLength = 4; this.sampleByteLength = 4;
} }
else { else {
args.bitDepth = 16; args.bitDepth = 16;
this.readSample = Buffer.readInt16LE; this.readSample = this.buffer.readInt16LE;
this.writeSample = Buffer.writeInt16LE; this.writeSample = this.buffer.writeInt16LE;
this.sampleByteLength = 2; this.sampleByteLength = 2;
} }
@ -39,23 +42,33 @@ util.inherits(Mixer, Readable);
Mixer.prototype._read = function() { Mixer.prototype._read = function() {
console.log('_read', arguments);
var samples = 9007199254740992; var samples = 9007199254740992;
this.inputs.forEach(function (input) { this.inputs.forEach(function (input) {
var as = input.availSamples(); var as = input.availSamples();
if (as < samples) samples = as; if (as < samples) samples = as;
}); });
if (samples > 0) { if (samples > 0 && samples != 9007199254740992) {
console.log('read samples', samples);
var mixedBuffer = new Buffer(samples * this.sampleByteLength); var mixedBuffer = new Buffer(samples * this.sampleByteLength * this.channels);
for (var i = 0; i < samples; i++) { mixedBuffer.fill(0);
var mixedSample = 0; this.inputs.forEach(function (input) {
for (var j = 0; j < this.inputs.length; j++) { if (this.channels == 1) {
mixedSample += this.inputs[j].readSample.call(this.inputs[j], i * this.inputs[j].sampleByteLength); var inputBuffer = input.readMono(samples);
} else {
var inputBuffer = input.readStereo(samples);
} }
this.writeSample.call(mixedBuffer, Math.round(mixedSample / this.inputs.length), i * this.sampleByteLength); for (var i = 0; i < samples * this.channels; i++) {
this.writeSample.call(mixedBuffer, this.readSample.call(mixedBuffer, i * this.sampleByteLength) + Math.round(this.readSample.call(inputBuffer, i * this.sampleByteLength) / this.inputs.length), i * this.sampleByteLength);
} }
}.bind(this));
this.push(mixedBuffer); this.push(mixedBuffer);
} else {
console.log('Nothing to read.');
setImmediate(this._read.bind(this));
} }
} }