working example with one input to the mixer
This commit is contained in:
parent
e32bd04065
commit
43c2556d8a
46
example/example.js
Normal file
46
example/example.js
Normal 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
BIN
example/example0.mp3
Normal file
Binary file not shown.
6
example/package.json
Normal file
6
example/package.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"lame": "*",
|
||||||
|
"speaker": "*"
|
||||||
|
}
|
||||||
|
}
|
27
lib/input.js
27
lib/input.js
@ -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;
|
||||||
|
39
lib/mixer.js
39
lib/mixer.js
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user