Simulator first commit

This commit is contained in:
2019-09-18 11:11:16 +03:00
commit 6e1686be67
5028 changed files with 985331 additions and 0 deletions

1
node_modules/lame/lib/bindings.js generated vendored Normal file
View File

@ -0,0 +1 @@
module.exports = require('bindings')('bindings');

155
node_modules/lame/lib/decoder.js generated vendored Normal file
View File

@ -0,0 +1,155 @@
/**
* Module dependencies.
*/
var assert = require('assert');
var binding = require('./bindings');
var inherits = require('util').inherits;
var Transform = require('readable-stream/transform');
var debug = require('debug')('lame:decoder');
/**
* Module exports.
*/
module.exports = Decoder;
/**
* Some constants.
*/
var MPG123_OK = binding.MPG123_OK;
var MPG123_DONE = binding.MPG123_DONE;
var MPG123_NEW_ID3 = binding.MPG123_NEW_ID3;
var MPG123_NEED_MORE = binding.MPG123_NEED_MORE;
var MPG123_NEW_FORMAT = binding.MPG123_NEW_FORMAT;
/**
* One-time calls...
*/
binding.mpg123_init();
process.once('exit', binding.mpg123_exit);
/**
* The recommended size of the "output" buffer when calling mpg123_read().
*/
var safe_buffer = binding.mpg123_safe_buffer();
/**
* `Decoder` Stream class.
* Accepts an MP3 file and spits out raw PCM data.
*/
function Decoder (opts) {
if (!(this instanceof Decoder)) {
return new Decoder(opts);
}
Transform.call(this, opts);
var ret;
ret = binding.mpg123_new(opts ? opts.decoder : null);
if (Buffer.isBuffer(ret)) {
this.mh = ret;
} else {
throw new Error('mpg123_new() failed: ' + ret);
}
ret = binding.mpg123_open_feed(this.mh);
if (MPG123_OK != ret) {
throw new Error('mpg123_open_feed() failed: ' + ret);
}
debug('created new Decoder instance');
}
inherits(Decoder, Transform);
/**
* Calls `mpg123_feed()` with the given "chunk", and then calls `mpg123_read()`
* until MPG123_NEED_MORE is returned.
*
* @param {Buffer} chunk The Buffer instance of PCM audio data to process
* @param {String} encoding ignore...
* @param {Function} done callback function when done processing
* @api private
*/
Decoder.prototype._transform = function (chunk, encoding, done) {
debug('_transform(): (%d bytes)', chunk.length);
var out, mh, self;
self = this;
mh = this.mh;
binding.mpg123_feed(mh, chunk, chunk.length, afterFeed);
function afterFeed (ret) {
// XXX: a hack to ensure that "chunk" doesn't get GC'd until
// after feed() is done. We could do this in C++-land to be "clean", but
// doing this saves sizeof(Persistent<Object>) from the req struct.
// It's also probably overkill...
chunk = chunk;
debug('mpg123_feed() = %d', ret);
if (MPG123_OK != ret) {
return done(new Error('mpg123_feed() failed: ' + ret));
}
read();
}
function read () {
out = new Buffer(safe_buffer);
binding.mpg123_read(mh, out, out.length, afterRead);
// XXX: the `afterRead` function below holds the reference to the "out"
// buffer while being filled by `mpg123_read()` on the thread pool.
}
function afterRead (ret, bytes, meta) {
debug('mpg123_read() = %d (bytes=%d) (meta=%d)', ret, bytes, meta);
if (meta & MPG123_NEW_ID3) {
debug('MPG123_NEW_ID3');
binding.mpg123_id3(mh, function (ret2, id3) {
if (ret2 == MPG123_OK) {
self.emit('id3v' + (id3.tag ? 1 : 2), id3);
handleRead(ret, bytes);
} else {
// error getting ID3 tag info (probably shouldn't happen)...
done(new Error('mpg123_id3() failed: ' + ret2));
}
});
} else {
handleRead(ret, bytes);
}
}
function handleRead (ret, bytes) {
if (bytes > 0) {
// got decoded data
assert(out.length >= bytes);
if (out.length != bytes) {
debug('slicing output buffer from %d to %d', out.length, bytes);
out = out.slice(0, bytes);
}
self.push(out);
}
if (ret == MPG123_DONE) {
debug('done');
return done();
}
if (ret == MPG123_NEED_MORE) {
debug('needs more!');
return done();
}
if (ret == MPG123_NEW_FORMAT) {
var format = binding.mpg123_getformat(mh);
debug('new format: %j', format);
self.emit('format', format);
return read();
}
if (MPG123_OK != ret) {
return done(new Error('mpg123_read() failed: ' + ret));
}
read();
}
};

304
node_modules/lame/lib/encoder.js generated vendored Normal file
View File

@ -0,0 +1,304 @@
/**
* Module dependencies.
*/
var assert = require('assert');
var binding = require('./bindings');
var inherits = require('util').inherits;
var Transform = require('readable-stream/transform');
var debug = require('debug')('lame:encoder');
/**
* Module exports.
*/
module.exports = Encoder;
/**
* Constants.
*/
var LAME_OKAY = binding.LAME_OKAY;
var LAME_BADBITRATE = binding.LAME_BADBITRATE;
var LAME_BADSAMPFREQ = binding.LAME_BADSAMPFREQ;
var LAME_INTERNALERROR = binding.LAME_INTERNALERROR;
var PCM_TYPE_SHORT_INT = binding.PCM_TYPE_SHORT_INT;
var PCM_TYPE_FLOAT = binding.PCM_TYPE_FLOAT;
var PCM_TYPE_DOUBLE = binding.PCM_TYPE_DOUBLE;
/**
* Messages for error codes returned from the lame C encoding functions.
*/
var ERRORS = {
'-1': 'output buffer too small',
'-2': 'malloc() problems',
'-3': 'lame_init_params() not called',
'-4': 'psycho acoustic problems'
};
/**
* Map of libmp3lame functions to node-lame property names.
*/
var PROPS = {
'brate': 'bitRate',
'num_channels': 'channels',
'bWriteVbrTag': 'writeVbrTag',
'in_samplerate': 'sampleRate',
'out_samplerate': 'outSampleRate'
};
/**
* The valid bit depths that lame supports encoding in.
*/
var INT_BITS = binding.sizeof_int * 8;
var SHORT_BITS = binding.sizeof_short * 8;
var FLOAT_BITS = binding.sizeof_float * 8;
var DOUBLE_BITS = binding.sizeof_double * 8;
/**
* The `Encoder` class is a Transform stream class.
* Write raw PCM data, out comes an MP3 file.
*
* @param {Object} opts PCM stream format info and stream options
* @api public
*/
function Encoder (opts) {
if (!(this instanceof Encoder)) {
return new Encoder(opts);
}
Transform.call(this, opts);
// lame malloc()s the "gfp" buffer
this.gfp = binding.lame_init();
// set default options
if (!opts) opts = {};
if (null == opts.channels) opts.channels = 2;
if (null == opts.bitDepth) opts.bitDepth = 16;
if (null == opts.sampleRate) opts.sampleRate = 44100;
if (null == opts.signed) opts.signed = opts.bitDepth != 8;
if (opts.float && opts.bitDepth == DOUBLE_BITS) {
this.inputType = PCM_TYPE_DOUBLE;
} else if (opts.float && opts.bitDepth == FLOAT_BITS) {
this.inputType = PCM_TYPE_FLOAT;
} else if (!opts.float && opts.bitDepth == SHORT_BITS) {
this.inputType = PCM_TYPE_SHORT_INT;
} else {
throw new Error('unsupported PCM format!');
}
// copy over opts to the encoder instance
Object.keys(opts).forEach(function(key){
if (key[0] != '_' && Encoder.prototype.hasOwnProperty(key)) {
debug('setting opt %j', key);
this[key] = opts[key];
}
}, this);
}
inherits(Encoder, Transform);
/**
* Default PCM format: signed 16-bit little endian integer samples.
*/
Encoder.prototype.bitDepth = 16;
/**
* Called one time at the beginning of the first `_transform()` call.
*
* @api private
*/
Encoder.prototype._init = function () {
debug('_init()');
var r = binding.lame_init_params(this.gfp);
if (LAME_OKAY !== r) {
throw new Error('error initializing params: ' + r);
}
// constant: number of 'bytes per sample'
this.blockAlign = this.bitDepth / 8 * this.channels;
};
/**
* Calls `lame_encode_buffer_interleaved()` on the given "chunk.
*
* @api private
*/
Encoder.prototype._transform = function (chunk, encoding, done) {
debug('_transform (%d bytes)', chunk.length);
var self = this;
if (!this._initCalled) {
try { this._init(); } catch (e) { return done(e); }
this._initCalled = true;
}
// first handle any _remainder
if (this._remainder) {
debug('concating remainder');
chunk = Buffer.concat([ this._remainder, chunk ]);
this._remainder = null;
}
// set any necessary _remainder (we can only send whole samples at a time)
var remainder = chunk.length % this.blockAlign;
if (remainder > 0) {
debug('setting remainder of %d bytes', remainder);
var slice = chunk.length - remainder;
this._remainder = chunk.slice(slice);
chunk = chunk.slice(0, slice);
}
assert.equal(chunk.length % this.blockAlign, 0);
var num_samples = chunk.length / this.blockAlign;
// TODO: Use better calculation logic from lame.h here
var estimated_size = 1.25 * num_samples + 7200;
var output = new Buffer(estimated_size);
debug('encoding %d byte chunk with %d byte output buffer (%d samples)', chunk.length, output.length, num_samples);
binding.lame_encode_buffer(
this.gfp,
chunk,
this.inputType,
this.channels,
num_samples,
output,
0,
output.length,
cb
);
function cb (bytesWritten) {
debug('after lame_encode_buffer() (rtn: %d)', bytesWritten);
if (bytesWritten < 0) {
var err = new Error(ERRORS[bytesWritten]);
err.code = bytesWritten;
done(err);
} else if (bytesWritten > 0) {
output = output.slice(0, bytesWritten);
debug('writing %d MP3 bytes', output.length);
self.push(output);
done();
} else { // bytesWritten == 0
done();
}
}
};
/**
* Calls `lame_encode_flush_nogap()` on the thread pool.
*/
Encoder.prototype._flush = function (done) {
debug('_flush');
var self = this;
var estimated_size = 7200; // value specified in lame.h
var output = new Buffer(estimated_size);
if (!this._initCalled) {
try { this._init(); } catch (e) { return done(e); }
this._initCalled = true;
}
binding.lame_encode_flush_nogap(
this.gfp,
output,
0,
output.length,
cb
);
function cb (bytesWritten) {
debug('after lame_encode_flush_nogap() (rtn: %d)', bytesWritten);
binding.lame_close(self.gfp);
self.gfp = null;
if (bytesWritten < 0) {
var err = new Error(ERRORS[bytesWritten]);
err.code = bytesWritten;
done(err);
} else if (bytesWritten > 0) {
output = output.slice(0, bytesWritten);
self.push(output);
done();
} else { // bytesWritten == 0
done();
}
}
};
/**
* Define the getter/setters for the lame encoder settings.
*/
Object.keys(binding).forEach(function (key) {
if (!/^lame_[gs]et/.test(key)) return;
var name = key.substring(9);
var prop = PROPS[name] || toCamelCase(name);
debug('processing prop %j as %j', key, prop);
var getter = 'g' == key[5];
/*
console.error({
key: key,
name: name,
prop: prop,
getter: getter
});
*/
var desc = Object.getOwnPropertyDescriptor(Encoder.prototype, prop);
if (!desc) desc = { enumerable: true, configurable: true };
if (getter) {
desc.get = function () {
debug('%s()', key);
return binding[key](this.gfp);
};
} else {
desc.set = function (v) {
debug('%s(%j)', key, v);
var r = binding[key](this.gfp, v);
if (LAME_OKAY !== r) {
throw new Error('error setting prop "' + prop + '": ' + r);
}
return r;
};
}
Object.defineProperty(Encoder.prototype, prop, desc);
});
/**
* The lame encoder only supports "signed" data types.
*/
Object.defineProperty(Encoder.prototype, 'signed', {
enumerable: true,
configurable: true,
get: function () { return true; },
set: function (v) { if (!v) throw new Error('"signed" must be `true`'); }
});
/**
* Converts a string_with_underscores to camelCase.
*
* @param {String} name The name to convert.
* @return {String} The camel case'd name.
* @api private
*/
function toCamelCase (name) {
return name.replace(/(\_[a-zA-Z])/g, function ($1) {
return $1.toUpperCase().replace('_', '');
});
}