Add files via upload
This commit is contained in:
		
							
								
								
									
										40
									
								
								node_modules/eris/lib/voice/streams/BaseTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								node_modules/eris/lib/voice/streams/BaseTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const util = require("util"); | ||||
| const Base = require("../../structures/Base"); | ||||
| const TransformStream = require("stream").Transform; | ||||
|  | ||||
| class BaseTransformer extends TransformStream { | ||||
|     constructor(options = {}) { | ||||
|         if(options.allowHalfOpen === undefined) { | ||||
|             options.allowHalfOpen = true; | ||||
|         } | ||||
|         if(options.highWaterMark === undefined) { | ||||
|             options.highWaterMark = 0; | ||||
|         } | ||||
|         super(options); | ||||
|         this.manualCB = false; | ||||
|     } | ||||
|  | ||||
|     setTransformCB(cb) { | ||||
|         if(this.manualCB) { | ||||
|             this.transformCB(); | ||||
|             this._transformCB = cb; | ||||
|         } else { | ||||
|             cb(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     transformCB() { | ||||
|         if(this._transformCB) { | ||||
|             this._transformCB(); | ||||
|             this._transformCB = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [util.inspect.custom]() { | ||||
|         return Base.prototype[util.inspect.custom].call(this); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = BaseTransformer; | ||||
							
								
								
									
										78
									
								
								node_modules/eris/lib/voice/streams/DCAOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								node_modules/eris/lib/voice/streams/DCAOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const BaseTransformer = require("./BaseTransformer"); | ||||
|  | ||||
| class DCAOpusTransformer extends BaseTransformer { | ||||
|     constructor(options = {}) { | ||||
|         super(options); | ||||
|  | ||||
|         this._remainder = null; | ||||
|     } | ||||
|  | ||||
|     process(buffer) { | ||||
|         if(buffer.length - buffer._index < 2) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         const opusLen = buffer.readInt16LE(buffer._index); | ||||
|         buffer._index += 2; | ||||
|  | ||||
|         if(buffer.length - buffer._index < opusLen) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         buffer._index += opusLen; | ||||
|         this.push(buffer.subarray(buffer._index - opusLen, buffer._index)); | ||||
|     } | ||||
|  | ||||
|     _transform(chunk, enc, cb) { | ||||
|         if(this._remainder)  { | ||||
|             chunk = Buffer.concat([this._remainder, chunk]); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|  | ||||
|         if(!this.head) { | ||||
|             if(chunk.length < 4) { | ||||
|                 this._remainder = chunk; | ||||
|                 return cb(); | ||||
|             } else { | ||||
|                 const dcaVersion = chunk.subarray(0, 4); | ||||
|                 if(dcaVersion[0] !== 68 || dcaVersion[1] !== 67 || dcaVersion[2] !== 65) { // DCA0 or invalid | ||||
|                     this.head = true; // Attempt to play as if it were a DCA0 file | ||||
|                 } else if(dcaVersion[3] === 49) { // DCA1 | ||||
|                     if(chunk.length < 8) { | ||||
|                         this._remainder = chunk; | ||||
|                         return cb(); | ||||
|                     } | ||||
|                     const jsonLength = chunk.subarray(4, 8).readInt32LE(0); | ||||
|                     if(chunk.length < 8 + jsonLength) { | ||||
|                         this._remainder = chunk; | ||||
|                         return cb(); | ||||
|                     } | ||||
|                     const jsonMetadata = chunk.subarray(8, 8 + jsonLength); | ||||
|                     this.emit("debug", jsonMetadata); | ||||
|                     chunk = chunk.subarray(8 + jsonLength); | ||||
|                     this.head = true; | ||||
|                 } else { | ||||
|                     this.emit("error", new Error("Unsupported DCA version: " + dcaVersion.toString())); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         chunk._index = 0; | ||||
|  | ||||
|         while(chunk._index < chunk.length) { | ||||
|             const offset = chunk._index; | ||||
|             const ret = this.process(chunk); | ||||
|             if(ret) { | ||||
|                 this._remainder = chunk.subarray(offset); | ||||
|                 cb(); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this.setTransformCB(cb); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = DCAOpusTransformer; | ||||
							
								
								
									
										199
									
								
								node_modules/eris/lib/voice/streams/FFmpegDuplex.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								node_modules/eris/lib/voice/streams/FFmpegDuplex.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| "use strict"; | ||||
| const util = require("util"); | ||||
| const Base = require("../../structures/Base"); | ||||
| const ChildProcess = require("child_process"); | ||||
| const DuplexStream = require("stream").Duplex; | ||||
| const PassThroughStream = require("stream").PassThrough; | ||||
|  | ||||
| const delegateEvents = { | ||||
|     readable: "_reader", | ||||
|     data: "_reader", | ||||
|     end: "_reader", | ||||
|     drain: "_writer", | ||||
|     finish: "_writer" | ||||
| }; | ||||
|  | ||||
| class FFmpegDuplex extends DuplexStream { | ||||
|     constructor(command, options = {}) { | ||||
|         if(options.highWaterMark === undefined) { | ||||
|             options.highWaterMark = 0; | ||||
|         } | ||||
|         super(options); | ||||
|  | ||||
|         this.command = command; | ||||
|         this._reader = new PassThroughStream(options); | ||||
|         this._writer = new PassThroughStream(options); | ||||
|  | ||||
|         this._onError = this.emit.bind(this, "error"); | ||||
|  | ||||
|         this._reader.on("error", this._onError); | ||||
|         this._writer.on("error", this._onError); | ||||
|  | ||||
|         this._readableState = this._reader._readableState; | ||||
|         this._writableState = this._writer._writableState; | ||||
|  | ||||
|         ["on", "once", "removeListener", "removeListeners", "listeners"].forEach((method) => { | ||||
|             const og = DuplexStream.prototype[method]; | ||||
|  | ||||
|             this[method] = function(ev, fn) { | ||||
|                 const substream = delegateEvents[ev]; | ||||
|                 if(substream) { | ||||
|                     return this[substream][method](ev, fn); | ||||
|                 } else { | ||||
|                     return og.call(this, ev, fn); | ||||
|                 } | ||||
|             }; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|     } | ||||
|  | ||||
|     end(chunk, enc, cb) { | ||||
|         return this._writer.end(chunk, enc, cb); | ||||
|     } | ||||
|  | ||||
|     kill() { | ||||
|     } | ||||
|  | ||||
|     noop() { | ||||
|     } | ||||
|  | ||||
|     pipe(dest, opts) { | ||||
|         return this._reader.pipe(dest, opts); | ||||
|     } | ||||
|  | ||||
|     read(size) { | ||||
|         return this._reader.read(size); | ||||
|     } | ||||
|  | ||||
|     setEncoding(enc) { | ||||
|         return this._reader.setEncoding(enc); | ||||
|     } | ||||
|  | ||||
|     spawn(args, options = {}) { | ||||
|         let ex, exited, killed, ended; | ||||
|         let stderr = []; | ||||
|  | ||||
|         const onStdoutEnd = () => { | ||||
|             if(exited && !ended) { | ||||
|                 ended = true; | ||||
|                 this._reader.end(); | ||||
|                 setImmediate(this.emit.bind(this, "close")); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         const onStderrData = (chunk) => { | ||||
|             stderr.push(chunk); | ||||
|         }; | ||||
|  | ||||
|         const cleanup = () => { | ||||
|             this._process = | ||||
|             this._stderr = | ||||
|             this._stdout = | ||||
|             this._stdin = | ||||
|             stderr = | ||||
|             ex = | ||||
|             killed = null; | ||||
|  | ||||
|             this.kill = | ||||
|             this.destroy = this.noop; | ||||
|         }; | ||||
|  | ||||
|         const onExit = (code, signal) => { | ||||
|             if(exited) { | ||||
|                 return; | ||||
|             } | ||||
|             exited = true; | ||||
|  | ||||
|             if(killed) { | ||||
|                 if(ex) { | ||||
|                     this.emit("error", ex); | ||||
|                 } | ||||
|                 this.emit("close"); | ||||
|             } else if(code === 0 && signal == null) { | ||||
|                 // All is well | ||||
|                 onStdoutEnd(); | ||||
|             } else { | ||||
|                 // Everything else | ||||
|                 ex = new Error("Command failed: " + Buffer.concat(stderr).toString("utf8")); | ||||
|                 ex.killed = this._process.killed || killed; | ||||
|                 ex.code = code; | ||||
|                 ex.signal = signal; | ||||
|                 this.emit("error", ex); | ||||
|                 this.emit("close"); | ||||
|             } | ||||
|  | ||||
|             cleanup(); | ||||
|         }; | ||||
|  | ||||
|         const onError = (err) => { | ||||
|             ex = err; | ||||
|             this._stdout.destroy(); | ||||
|             this._stderr.destroy(); | ||||
|             onExit(); | ||||
|         }; | ||||
|  | ||||
|         const kill = () => { | ||||
|             if(killed) { | ||||
|                 return; | ||||
|             } | ||||
|             this._stdout.destroy(); | ||||
|             this._stderr.destroy(); | ||||
|  | ||||
|             killed = true; | ||||
|  | ||||
|             try { | ||||
|                 this._process.kill(options.killSignal || "SIGTERM"); | ||||
|                 setTimeout(() => this._process && this._process.kill("SIGKILL"), 2000); | ||||
|             } catch(e) { | ||||
|                 ex = e; | ||||
|                 onExit(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this._process = ChildProcess.spawn(this.command, args, options); | ||||
|         this._stdin = this._process.stdin; | ||||
|         this._stdout = this._process.stdout; | ||||
|         this._stderr = this._process.stderr; | ||||
|         this._writer.pipe(this._stdin); | ||||
|         this._stdout.pipe(this._reader, { | ||||
|             end: false | ||||
|         }); | ||||
|         this.kill = this.destroy = kill; | ||||
|  | ||||
|         this._stderr.on("data", onStderrData); | ||||
|  | ||||
|         // In some cases ECONNRESET can be emitted by stdin because the process is not interested in any | ||||
|         // more data but the _writer is still piping. Forget about errors emitted on stdin and stdout | ||||
|         this._stdin.on("error", this.noop); | ||||
|         this._stdout.on("error", this.noop); | ||||
|  | ||||
|         this._stdout.on("end", onStdoutEnd); | ||||
|  | ||||
|         this._process.once("close", onExit); | ||||
|         this._process.once("error", onError); | ||||
|  | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     unpipe(dest) { | ||||
|         return this._reader.unpipe(dest) || this.kill(); | ||||
|     } | ||||
|  | ||||
|     write(chunk, enc, cb) { | ||||
|         return this._writer.write(chunk, enc, cb); | ||||
|     } | ||||
|  | ||||
|     [util.inspect.custom]() { | ||||
|         return Base.prototype[util.inspect.custom].call(this); | ||||
|     } | ||||
| } | ||||
|  | ||||
| FFmpegDuplex.prototype.addListener = FFmpegDuplex.prototype.on; | ||||
|  | ||||
| FFmpegDuplex.spawn = function(connection, args, options) { | ||||
|     return new FFmpegDuplex(connection, options).spawn(args, options); | ||||
| }; | ||||
|  | ||||
| module.exports = FFmpegDuplex; | ||||
							
								
								
									
										35
									
								
								node_modules/eris/lib/voice/streams/FFmpegOggTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								node_modules/eris/lib/voice/streams/FFmpegOggTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const FFmpegDuplex = require("./FFmpegDuplex"); | ||||
|  | ||||
| module.exports = function(options = {}) { | ||||
|     if(!options.command) { | ||||
|         throw new Error("Invalid converter command"); | ||||
|     } | ||||
|     if(options.frameDuration === undefined) { | ||||
|         options.frameDuration = 60; | ||||
|     } | ||||
|     let inputArgs = [ | ||||
|         "-analyzeduration", "0", | ||||
|         "-loglevel", "24" | ||||
|     ].concat(options.inputArgs || []); | ||||
|     if(options.format === "pcm") { | ||||
|         inputArgs = inputArgs.concat( | ||||
|             "-f", "s16le", | ||||
|             "-ar", "48000", | ||||
|             "-ac", "2" | ||||
|         ); | ||||
|     } | ||||
|     inputArgs = inputArgs.concat( | ||||
|         "-i", options.input || "-", | ||||
|         "-vn" | ||||
|     ); | ||||
|     const outputArgs = [ | ||||
|         "-c:a", "libopus", | ||||
|         "-vbr", "on", | ||||
|         "-frame_duration", "" + options.frameDuration, | ||||
|         "-f", "ogg", | ||||
|         "-" | ||||
|     ]; | ||||
|     return FFmpegDuplex.spawn(options.command, inputArgs.concat(options.encoderArgs || [], outputArgs)); | ||||
| }; | ||||
							
								
								
									
										26
									
								
								node_modules/eris/lib/voice/streams/FFmpegPCMTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								node_modules/eris/lib/voice/streams/FFmpegPCMTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const FFmpegDuplex = require("./FFmpegDuplex"); | ||||
|  | ||||
| module.exports = function(options = {}) { | ||||
|     if(!options.command) { | ||||
|         throw new Error("Invalid converter command"); | ||||
|     } | ||||
|     if(options.samplingRate === undefined) { | ||||
|         options.samplingRate = 48000; | ||||
|     } | ||||
|     const inputArgs = [ | ||||
|         "-analyzeduration", "0", | ||||
|         "-loglevel", "24" | ||||
|     ].concat(options.inputArgs || [], | ||||
|         "-i", options.input || "-", | ||||
|         "-vn" | ||||
|     ); | ||||
|     const outputArgs = [ | ||||
|         "-f", "s16le", | ||||
|         "-ar", "" + options.samplingRate, | ||||
|         "-ac", "2", | ||||
|         "-" | ||||
|     ]; | ||||
|     return FFmpegDuplex.spawn(options.command, inputArgs.concat(options.encoderArgs || [], outputArgs)); | ||||
| }; | ||||
							
								
								
									
										107
									
								
								node_modules/eris/lib/voice/streams/OggOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								node_modules/eris/lib/voice/streams/OggOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const BaseTransformer = require("./BaseTransformer"); | ||||
|  | ||||
| class OggOpusTransformer extends BaseTransformer { | ||||
|     constructor(options = {}) { | ||||
|         super(options); | ||||
|  | ||||
|         this._remainder = null; | ||||
|         this._bitstream = null; | ||||
|     } | ||||
|  | ||||
|     process(buffer) { | ||||
|         if(buffer.length - buffer._index <= 26) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         if(buffer.toString("utf8", buffer._index, buffer._index + 4) !== "OggS") { | ||||
|             return new Error("Invalid OGG magic string: " + buffer.toString("utf8", buffer._index, buffer._index + 4)); | ||||
|         } | ||||
|  | ||||
|         const typeFlag = buffer.readUInt8(buffer._index + 5); | ||||
|         if(typeFlag === 1) { | ||||
|             return new Error("OGG continued page not supported"); | ||||
|         } | ||||
|  | ||||
|         const bitstream = buffer.readUInt32BE(buffer._index + 14); | ||||
|  | ||||
|         buffer._index += 26; | ||||
|  | ||||
|         const segmentCount = buffer.readUInt8(buffer._index); | ||||
|         if(buffer.length - buffer._index - 1 < segmentCount) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         const segments = []; | ||||
|         let size = 0; | ||||
|         let byte = 0; | ||||
|         let total = 0; | ||||
|         let i = 0; | ||||
|         for(; i < segmentCount; i++) { | ||||
|             byte = buffer.readUInt8(++buffer._index); | ||||
|             if(byte < 255) { | ||||
|                 segments.push(size + byte); | ||||
|                 size = 0; | ||||
|             } else { | ||||
|                 size += byte; | ||||
|             } | ||||
|             total += byte; | ||||
|         } | ||||
|  | ||||
|         ++buffer._index; | ||||
|  | ||||
|         if(buffer.length - buffer._index < total) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         for(let segment of segments) { | ||||
|             buffer._index += segment; | ||||
|             byte = (segment = buffer.subarray(buffer._index - segment, buffer._index)).toString("utf8", 0, 8); | ||||
|             if(this.head) { | ||||
|                 if(byte === "OpusTags") { | ||||
|                     this.emit("debug", segment.toString()); | ||||
|                 } else if(bitstream === this._bitstream) { | ||||
|                     this.push(segment); | ||||
|                 } | ||||
|             } else if(byte === "OpusHead") { | ||||
|                 this._bitstream = bitstream; | ||||
|                 this.emit("debug", (this.head = segment.toString())); | ||||
|             } else { | ||||
|                 this.emit("debug", "Invalid codec: " + byte); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _final() { | ||||
|         if(!this._bitstream) { | ||||
|             this.emit("error", new Error("No Opus stream was found")); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _transform(chunk, enc, cb) { | ||||
|         if(this._remainder)  { | ||||
|             chunk = Buffer.concat([this._remainder, chunk]); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|  | ||||
|         chunk._index = 0; | ||||
|  | ||||
|         while(chunk._index < chunk.length) { | ||||
|             const offset = chunk._index; | ||||
|             const ret = this.process(chunk); | ||||
|             if(ret) { | ||||
|                 this._remainder = chunk.subarray(offset); | ||||
|                 if(ret instanceof Error) { | ||||
|                     this.emit("error", ret); | ||||
|                 } | ||||
|                 cb(); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this.setTransformCB(cb); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = OggOpusTransformer; | ||||
							
								
								
									
										61
									
								
								node_modules/eris/lib/voice/streams/PCMOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								node_modules/eris/lib/voice/streams/PCMOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const BaseTransformer = require("./BaseTransformer"); | ||||
|  | ||||
| class PCMOpusTransformer extends BaseTransformer { | ||||
|     constructor(options = {}) { | ||||
|         super(options); | ||||
|  | ||||
|         this.opus = options.opusFactory(); | ||||
|         this.frameSize = options.frameSize || 2880; | ||||
|         this.pcmSize = options.pcmSize || 11520; | ||||
|  | ||||
|         this._remainder = null; | ||||
|     } | ||||
|  | ||||
|     _destroy(...args) { | ||||
|         if(this.opus.delete) { | ||||
|             this.opus.delete(); | ||||
|         } | ||||
|  | ||||
|         return super._destroy(...args); | ||||
|     } | ||||
|  | ||||
|     _flush(cb) { | ||||
|         if(this._remainder) { | ||||
|             const buf = Buffer.allocUnsafe(this.pcmSize); | ||||
|             this._remainder.copy(buf); | ||||
|             buf.fill(0, this._remainder.length); | ||||
|             this.push(this.opus.encode(buf, this.frameSize)); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|         cb(); | ||||
|     } | ||||
|  | ||||
|     _transform(chunk, enc, cb) { | ||||
|         if(this._remainder) { | ||||
|             chunk = Buffer.concat([this._remainder, chunk]); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|  | ||||
|         if(chunk.length < this.pcmSize) { | ||||
|             this._remainder = chunk; | ||||
|             return cb(); | ||||
|         } | ||||
|  | ||||
|         chunk._index = 0; | ||||
|  | ||||
|         while(chunk._index + this.pcmSize < chunk.length) { | ||||
|             chunk._index += this.pcmSize; | ||||
|             this.push(this.opus.encode(chunk.subarray(chunk._index - this.pcmSize, chunk._index), this.frameSize)); | ||||
|         } | ||||
|  | ||||
|         if(chunk._index < chunk.length) { | ||||
|             this._remainder = chunk.subarray(chunk._index); | ||||
|         } | ||||
|  | ||||
|         this.setTransformCB(cb); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = PCMOpusTransformer; | ||||
							
								
								
									
										50
									
								
								node_modules/eris/lib/voice/streams/VolumeTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								node_modules/eris/lib/voice/streams/VolumeTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const BaseTransformer = require("./BaseTransformer"); | ||||
|  | ||||
| class VolumeTransformer extends BaseTransformer { | ||||
|     constructor(options = {}) { | ||||
|         super(options); | ||||
|  | ||||
|         this._remainder = null; | ||||
|         this.setVolume(1.0); | ||||
|     } | ||||
|  | ||||
|     setVolume(volume) { | ||||
|         if(isNaN(volume) || (volume = +volume) < 0) { | ||||
|             throw new Error("Invalid volume level: " + volume); | ||||
|         } | ||||
|         this.volume = volume; | ||||
|         this.db = 10 * Math.log(1 + this.volume) / 6.931471805599453; | ||||
|     } | ||||
|  | ||||
|     _transform(chunk, enc, cb) { | ||||
|         if(this._remainder)  { | ||||
|             chunk = Buffer.concat([this._remainder, chunk]); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|  | ||||
|         if(chunk.length < 2) { | ||||
|             return cb(); | ||||
|         } | ||||
|  | ||||
|         let buf; | ||||
|         if(chunk.length & 1) { | ||||
|             this._remainder = chunk.subarray(chunk.length - 1); | ||||
|             buf = Buffer.allocUnsafe(chunk.length - 1); | ||||
|         } else { | ||||
|             buf = Buffer.allocUnsafe(chunk.length); | ||||
|         } | ||||
|  | ||||
|         for(let i = 0, num; i < buf.length - 1; i += 2) { | ||||
|             // Bind transformed chunk to to 16 bit | ||||
|             num = ~~(this.db * chunk.readInt16LE(i)); | ||||
|             buf.writeInt16LE(num >= 32767 ? 32767 : num <= -32767 ? -32767 : num, i); | ||||
|         } | ||||
|  | ||||
|         this.push(buf); | ||||
|         this.setTransformCB(cb); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = VolumeTransformer; | ||||
							
								
								
									
										258
									
								
								node_modules/eris/lib/voice/streams/WebmOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								node_modules/eris/lib/voice/streams/WebmOpusTransformer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const BaseTransformer = require("./BaseTransformer"); | ||||
|  | ||||
| // EBML VInt max value is (2 ^ 56 - 2), but JS only supports 2^53 | ||||
| // 45 = 53 - 8 - check before last 8 bytes | ||||
| const MAX_SHIFTED_VINT = Math.pow(2, 45); | ||||
|  | ||||
| const STATE_CONTENT = 0; | ||||
| const STATE_TAG = 1; | ||||
|  | ||||
| const TAG_TYPE_END = 0; | ||||
| const TAG_TYPE_START = 1; | ||||
| const TAG_TYPE_TAG = 2; | ||||
|  | ||||
| const TRACKTYPE_AUDIO = 2; // EBML spec: https://www.matroska.org/technical/specs/index.html#TrackType | ||||
|  | ||||
| class WebmOpusTransformer extends BaseTransformer { | ||||
|     constructor(options = {}) { | ||||
|         super(options); | ||||
|  | ||||
|         this._tag_stack = []; | ||||
|         this._state = STATE_TAG; | ||||
|         this._total = 0; | ||||
|     } | ||||
|  | ||||
|     getVIntLength(buffer, index) { | ||||
|         let length = 1; | ||||
|         for(; length <= 8; ++length) { | ||||
|             if(buffer[index] & (1 << (8 - length))) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         if(length > 8) { | ||||
|             this.emit("debug", new Error(`VInt length ${length} | ${buffer.toString("hex", index, index + length)}`)); | ||||
|             return null; | ||||
|         } | ||||
|         if(index + length > buffer.length) { | ||||
|             return null; | ||||
|         } | ||||
|         return length; | ||||
|     } | ||||
|  | ||||
|     process(type, info) { | ||||
|         if(type === TAG_TYPE_TAG) { | ||||
|             if(info.name === "SimpleBlock" && (info.data.readUInt8(0) & 0xF) === this.firstAudioTrack.TrackNumber) { | ||||
|                 this.push(info.data.subarray(4)); | ||||
|                 return; | ||||
|             } | ||||
|             if(info.name === "CodecPrivate") { | ||||
|                 const head = info.data.toString("utf8", 0, 8); | ||||
|                 if(head !== "OpusHead") { | ||||
|                     this.emit("error", new Error("Invalid codec: " + head)); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 this.codecData = { | ||||
|                     version: info.data.readUInt8(8), | ||||
|                     channelCount: info.data.readUInt8(9), | ||||
|                     preSkip: info.data.readUInt16LE(10), | ||||
|                     inputSampleRate: info.data.readUInt32LE(12), | ||||
|                     outputGain: info.data.readUInt16LE(16), | ||||
|                     mappingFamily: info.data.readUInt8(18) | ||||
|                 }; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if(!this.firstAudioTrack) { | ||||
|             if(info.name === "TrackEntry") { | ||||
|                 if(type === TAG_TYPE_START) { | ||||
|                     this.parsingTrack = {}; | ||||
|                 } else if(type === TAG_TYPE_END) { | ||||
|                     if(this.parsingTrack.TrackNumber && this.parsingTrack.TrackType === TRACKTYPE_AUDIO) { | ||||
|                         this.firstAudioTrack = this.parsingTrack; | ||||
|                     } | ||||
|                     delete this.parsingTrack; | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             if(this.parsingTrack) { | ||||
|                 if(info.name === "TrackNumber") { | ||||
|                     this.parsingTrack.TrackNumber = info.data[0]; | ||||
|                     return; | ||||
|                 } | ||||
|                 if(info.name === "TrackType") { | ||||
|                     this.parsingTrack.TrackType = info.data[0]; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             if(type === TAG_TYPE_END && info.name === "Tracks") { | ||||
|                 this.emit("error", new Error("No audio track")); | ||||
|                 return; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     readContent(buffer) { | ||||
|         const tagObj = this._tag_stack[this._tag_stack.length - 1]; | ||||
|  | ||||
|         if(tagObj.type === "m") { | ||||
|             this.process(TAG_TYPE_START, tagObj); | ||||
|             this._state = STATE_TAG; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         if(buffer.length < buffer._index + tagObj.size) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         tagObj.data = buffer.subarray(buffer._index, buffer._index + tagObj.size); | ||||
|         buffer._index += tagObj.size; | ||||
|         this._total += tagObj.size; | ||||
|         this._state = STATE_TAG; | ||||
|  | ||||
|         this._tag_stack.pop(); | ||||
|  | ||||
|         this.process(TAG_TYPE_TAG, tagObj); | ||||
|  | ||||
|         while(this._tag_stack.length > 0) { | ||||
|             if(this._total < this._tag_stack[this._tag_stack.length - 1].end) { | ||||
|                 break; | ||||
|             } | ||||
|             this.process(TAG_TYPE_END, this._tag_stack.pop()); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     readTag(buffer) { | ||||
|         const tagSize = this.getVIntLength(buffer, buffer._index); | ||||
|         if(tagSize === null) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         const size = this.getVIntLength(buffer, buffer._index + tagSize); | ||||
|         if(size === null) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         const tagStr = buffer.toString("hex", buffer._index, buffer._index + tagSize); | ||||
|  | ||||
|         const tagObj = { | ||||
|             type: "unknown", | ||||
|             name: "unknown", | ||||
|             end: this._total + tagSize | ||||
|         }; | ||||
|         if(schema[tagStr]) { | ||||
|             tagObj.type = schema[tagStr].type; | ||||
|             tagObj.name = schema[tagStr].name; | ||||
|         } | ||||
|  | ||||
|         buffer._index += tagSize; | ||||
|  | ||||
|         let value = buffer[buffer._index] & (1 << (8 - size)) - 1; | ||||
|         for(let i = 1; i < size; ++i) { | ||||
|             if(i === 7 && value >= MAX_SHIFTED_VINT && buffer[buffer._index + 7] > 0) { | ||||
|                 tagObj.end = -1; // Special livestreaming int 0x1FFFFFFFFFFFFFF | ||||
|                 break; | ||||
|             } | ||||
|             value = (value << 8) + buffer[buffer._index + i]; | ||||
|         } | ||||
|         if(tagObj.end !== -1) { | ||||
|             tagObj.end += value + size; | ||||
|         } | ||||
|         tagObj.size = value; | ||||
|  | ||||
|         buffer._index += size; | ||||
|         this._total += tagSize + size; | ||||
|         this._state = STATE_CONTENT; | ||||
|  | ||||
|         this._tag_stack.push(tagObj); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     _transform(chunk, enc, cb) { | ||||
|         if(this._remainder)  { | ||||
|             chunk = Buffer.concat([this._remainder, chunk]); | ||||
|             this._remainder = null; | ||||
|         } | ||||
|  | ||||
|         chunk._index = 0; | ||||
|  | ||||
|         while(chunk._index < chunk.length) { | ||||
|             if(this._state === STATE_TAG && !this.readTag(chunk)) { | ||||
|                 break; | ||||
|             } | ||||
|             if(this._state === STATE_CONTENT && !this.readContent(chunk)) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if(chunk._index < chunk.length) { | ||||
|             this._remainder = chunk.subarray(chunk._index); | ||||
|         } | ||||
|  | ||||
|         this.setTransformCB(cb); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = WebmOpusTransformer; | ||||
|  | ||||
| const schema = { | ||||
|     ae: { | ||||
|         name: "TrackEntry", | ||||
|         type: "m" | ||||
|     }, | ||||
|     d7: { | ||||
|         name: "TrackNumber", | ||||
|         type: "u" | ||||
|     }, | ||||
|     "86": { | ||||
|         name: "CodecID", | ||||
|         type: "s" | ||||
|     }, | ||||
|     "83": { | ||||
|         name: "TrackType", | ||||
|         type: "u" | ||||
|     }, | ||||
|     "1654ae6b": { | ||||
|         name: "Tracks", | ||||
|         type: "m" | ||||
|     }, | ||||
|     "63a2": { | ||||
|         name: "CodecPrivate", | ||||
|         type: "b" | ||||
|     }, | ||||
|     a3: { | ||||
|         name: "SimpleBlock", | ||||
|         type: "b" | ||||
|     }, | ||||
|     "1a45dfa3": { | ||||
|         name: "EBML", | ||||
|         type: "m" | ||||
|     }, | ||||
|     "18538067": { | ||||
|         name: "Segment", | ||||
|         type: "m" | ||||
|     }, | ||||
|     "114d9b74": { | ||||
|         name: "SeekHead", | ||||
|         type: "m" | ||||
|     }, | ||||
|     "1549a966": { | ||||
|         name: "Info", | ||||
|         type: "m" | ||||
|     }, | ||||
|     e1: { | ||||
|         name: "Audio", | ||||
|         type: "m" | ||||
|     }, | ||||
|     "1f43b675": { | ||||
|         name: "Cluster", | ||||
|         type: "m" | ||||
|     } | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user