mirror of
https://github.com/musix-org/musix-oss
synced 2025-06-17 10:46:01 +00:00
Modules
This commit is contained in:
86
node_modules/node-opus/lib/Decoder.js
generated
vendored
Normal file
86
node_modules/node-opus/lib/Decoder.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
|
||||
var util = require( 'util' );
|
||||
var Transform = require( 'stream' ).Transform;
|
||||
var ogg_packet = require( 'ogg-packet' );
|
||||
|
||||
var OpusEncoder = require( './OpusEncoder' );
|
||||
|
||||
var Decoder = function( rate, channels, frameSize ) {
|
||||
Transform.call( this, { writableObjectMode: true } );
|
||||
|
||||
this.rate = rate || 48000;
|
||||
this.channels = channels || 1;
|
||||
this.frameSize = frameSize || this.rate * 0.04;
|
||||
|
||||
this.encoder = null;
|
||||
|
||||
this.header = {};
|
||||
this.tags = null;
|
||||
this.pos = 0;
|
||||
this.samplesWritten = 0;
|
||||
|
||||
this.packetBuffer = [];
|
||||
};
|
||||
util.inherits( Decoder, Transform );
|
||||
|
||||
/**
|
||||
* Transform stream callback
|
||||
*/
|
||||
Decoder.prototype._transform = function( packet, encoding, done ) {
|
||||
|
||||
// Write the header if it hasn't been written yet
|
||||
if( !this.encoder ) {
|
||||
this._parseHeader( packet );
|
||||
} else if( !this.tags ) {
|
||||
// TODO: Not implemented
|
||||
// this._parseTags( packet );
|
||||
this.tags = {};
|
||||
} else {
|
||||
this._processInput( packet );
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
Decoder.prototype._parseHeader = function( packet ) {
|
||||
|
||||
var header = packet.packet;
|
||||
|
||||
var signature = header.slice( 0, 8 );
|
||||
if( signature.toString( 'ascii' ) !== 'OpusHead' ) {
|
||||
return this.emit( 'error', 'Bad header' );
|
||||
}
|
||||
|
||||
this.header.version = header.readUInt8( 8 );
|
||||
this.header.channels = header.readUInt8( 9 );
|
||||
this.header.preSkip = header.readUInt16LE( 10 );
|
||||
this.header.rate = header.readUInt32LE( 12 );
|
||||
this.header.gain = header.readUInt16LE( 16 );
|
||||
this.header.channelMap = header.readUInt8( 18 );
|
||||
|
||||
this.emit( 'format', {
|
||||
channels: this.channels,
|
||||
sampleRate: this.rate,
|
||||
bitDepth: 16,
|
||||
float: false,
|
||||
signed: true,
|
||||
|
||||
gain: this.header.gain,
|
||||
preSkip: this.header.preSkip,
|
||||
version: this.header.version
|
||||
});
|
||||
|
||||
this.encoder = new OpusEncoder( this.rate, this.channels );
|
||||
};
|
||||
|
||||
Decoder.prototype._processInput = function( packet ) {
|
||||
|
||||
var frame = packet.packet;
|
||||
|
||||
var pcm = this.encoder.decode( frame );
|
||||
this.push( pcm );
|
||||
};
|
||||
|
||||
module.exports = Decoder;
|
||||
|
||||
|
188
node_modules/node-opus/lib/Encoder.js
generated
vendored
Normal file
188
node_modules/node-opus/lib/Encoder.js
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
|
||||
var util = require( 'util' );
|
||||
var Transform = require( 'stream' ).Transform;
|
||||
var ogg_packet = require( 'ogg-packet' );
|
||||
var OpusEncoder = require( './OpusEncoder' );
|
||||
|
||||
// These are the valid rates for libopus according to
|
||||
// https://www.opus-codec.org/docs/opus_api-1.1.2/group__opus__encoder.html#gaa89264fd93c9da70362a0c9b96b9ca88
|
||||
var VALID_RATES = [ 8000, 12000, 16000, 24000, 48000 ];
|
||||
|
||||
var Encoder = function( rate, channels, frameSize ) {
|
||||
Transform.call( this, { readableObjectMode: true } );
|
||||
|
||||
this.rate = rate || 48000;
|
||||
|
||||
// Ensure the range is valid.
|
||||
if( VALID_RATES.indexOf( this.rate ) === -1 ) {
|
||||
throw new RangeError(
|
||||
'Encoder rate (' + this.rate + ') is not valid. ' +
|
||||
'Valid rates are: ' + VALID_RATES.join( ', ' ) );
|
||||
}
|
||||
|
||||
this.channels = channels || 1;
|
||||
this.frameSize = frameSize || this.rate * 0.04;
|
||||
|
||||
this.encoder = new OpusEncoder( this.rate, this.channels );
|
||||
this.frameOverflow = Buffer.alloc(0);
|
||||
|
||||
this.headerWritten = false;
|
||||
this.pos = 0;
|
||||
this.granulepos = 0;
|
||||
this.samplesWritten = 0;
|
||||
};
|
||||
util.inherits( Encoder, Transform );
|
||||
|
||||
/**
|
||||
* Transform stream callback
|
||||
*/
|
||||
Encoder.prototype._transform = function( buf, encoding, done ) {
|
||||
|
||||
// Transform the buffer
|
||||
this._processOutput( buf );
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
Encoder.prototype._writeHeader = function() {
|
||||
|
||||
// OpusHead packet
|
||||
var magicSignature = Buffer.from( 'OpusHead', 'ascii' );
|
||||
var data = Buffer.from([
|
||||
0x01, // version
|
||||
this.channels,
|
||||
0x00, 0x0f, // Preskip (default and recommended 3840)
|
||||
( ( this.rate & 0x000000ff ) >> 0 ),
|
||||
( ( this.rate & 0x0000ff00 ) >> 8 ),
|
||||
( ( this.rate & 0x00ff0000 ) >> 16 ),
|
||||
( ( this.rate & 0xff000000 ) >> 24 ),
|
||||
0x00, 0x00, // gain
|
||||
0x00, // Channel mappign (RTP, mono/stereo)
|
||||
]);
|
||||
|
||||
var header = Buffer.concat([ magicSignature, data ]);
|
||||
|
||||
|
||||
var packet = new ogg_packet();
|
||||
packet.packet = header;
|
||||
packet.bytes = header.length;
|
||||
packet.b_o_s = 1;
|
||||
packet.e_o_s = 0;
|
||||
packet.granulepos = -1;
|
||||
packet.packetno = this.pos++;
|
||||
|
||||
this.push( packet );
|
||||
|
||||
// OpusTags packet
|
||||
magicSignature = Buffer.from( 'OpusTags', 'ascii' );
|
||||
var vendor = Buffer.from( 'node-opus', 'ascii' );
|
||||
var vendorLength = Buffer.alloc( 4 );
|
||||
vendorLength.writeUInt32LE( vendor.length, 0 );
|
||||
var commentLength = Buffer.alloc( 4 );
|
||||
commentLength.writeUInt32LE( 0, 0 );
|
||||
|
||||
header = Buffer.concat([
|
||||
magicSignature, vendorLength, vendor, commentLength, Buffer.from([ 0xff ])
|
||||
]);
|
||||
|
||||
packet = new ogg_packet();
|
||||
packet.packet = header;
|
||||
packet.bytes = header.length;
|
||||
packet.b_o_s = 0;
|
||||
packet.e_o_s = 0;
|
||||
packet.granulepos = -1;
|
||||
packet.packetno = this.pos++;
|
||||
packet.flush = true;
|
||||
|
||||
this.push( packet );
|
||||
|
||||
this.headerWritten = true;
|
||||
};
|
||||
|
||||
Encoder.prototype._processOutput = function( buf ) {
|
||||
|
||||
// Calculate the total data available and data required for each frame.
|
||||
var totalData = buf.length + this.frameOverflow.length;
|
||||
var requiredData = this.frameSize * 2 * this.channels;
|
||||
|
||||
// Process output while we got enough for a frame.
|
||||
while( totalData >= requiredData ) {
|
||||
|
||||
// If we got overflow, use it up first.
|
||||
var buffer;
|
||||
if( this.frameOverflow ) {
|
||||
|
||||
buffer = Buffer.concat([
|
||||
this.frameOverflow,
|
||||
buf.slice( 0, requiredData - this.frameOverflow.length )
|
||||
]);
|
||||
|
||||
// Cut the already used part off the buf.
|
||||
buf = buf.slice( requiredData - this.frameOverflow.length );
|
||||
|
||||
// Remove overflow. We'll set it later so it'll never be null
|
||||
// outside of this function.
|
||||
this.frameOverflow = null;
|
||||
|
||||
} else {
|
||||
|
||||
// We got no overflow.
|
||||
// Just cut the required bits from the buffer
|
||||
buffer = buf.slice( 0, requiredData );
|
||||
buf = buf.slice( requiredData );
|
||||
}
|
||||
|
||||
// Flush frame and remove bits from the total data counter before
|
||||
// repeating loop.
|
||||
this._flushFrame( buffer );
|
||||
totalData -= requiredData;
|
||||
}
|
||||
|
||||
// Store the remainign buffer in the overflow.
|
||||
this.frameOverflow = buf;
|
||||
};
|
||||
|
||||
Encoder.prototype._flushFrame = function( frame, end ) {
|
||||
var encoded = this.encoder.encode( frame );
|
||||
this._pushEncodedBuffer(encoded, end);
|
||||
};
|
||||
|
||||
Encoder.prototype._pushEncodedBuffer = function( encoded, end ) {
|
||||
// Write the header if it hasn't been written yet
|
||||
if( !this.headerWritten ) {
|
||||
this._writeHeader();
|
||||
}
|
||||
|
||||
if( this.lastPacket ) {
|
||||
this.push( this.lastPacket );
|
||||
}
|
||||
|
||||
// Scale the frame size into 48 kHz bitrate, which is used for the
|
||||
// granule positioning. We'll still update the samplesWritten just to
|
||||
// ensure backwards compatibility.
|
||||
this.granulepos += this.frameSize / this.rate * 48000;
|
||||
this.samplesWritten += this.frameSize;
|
||||
|
||||
var packet = new ogg_packet();
|
||||
packet.packet = encoded;
|
||||
packet.bytes = encoded.length,
|
||||
packet.b_o_s = 0;
|
||||
packet.e_o_s = 0;
|
||||
packet.granulepos = this.granulepos;
|
||||
packet.packetno = this.pos++;
|
||||
packet.flush = true;
|
||||
|
||||
this.lastPacket = packet;
|
||||
};
|
||||
|
||||
Encoder.prototype._flush = function( done ) {
|
||||
|
||||
if( this.lastPacket ) {
|
||||
this.lastPacket.e_o_s = 1;
|
||||
this.push( this.lastPacket );
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
module.exports = Encoder;
|
5
node_modules/node-opus/lib/OpusEncoder.js
generated
vendored
Normal file
5
node_modules/node-opus/lib/OpusEncoder.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var binding = require('bindings')('node-opus');
|
||||
module.exports = binding.OpusEncoder;
|
Reference in New Issue
Block a user