mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-19 04:53:30 +01:00
Remove dead files
This commit is contained in:
@@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* The base opus encoding engine.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
class BaseOpus {
|
|
||||||
/**
|
|
||||||
* @param {Object} [options] The options to apply to the Opus engine
|
|
||||||
* @param {number} [options.bitrate=48] The desired bitrate (kbps)
|
|
||||||
* @param {boolean} [options.fec=false] Whether to enable forward error correction
|
|
||||||
* @param {number} [options.plp=0] The expected packet loss percentage
|
|
||||||
*/
|
|
||||||
constructor({ bitrate = 48, fec = false, plp = 0 } = {}) {
|
|
||||||
this.ctl = {
|
|
||||||
BITRATE: 4002,
|
|
||||||
FEC: 4012,
|
|
||||||
PLP: 4014,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.samplingRate = 48000;
|
|
||||||
this.channels = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The desired bitrate (kbps)
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.bitrate = bitrate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Miscellaneous Opus options
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.options = { fec, plp };
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
try {
|
|
||||||
this.setBitrate(this.bitrate);
|
|
||||||
|
|
||||||
// Set FEC (forward error correction)
|
|
||||||
if (this.options.fec) this.setFEC(this.options.fec);
|
|
||||||
|
|
||||||
// Set PLP (expected packet loss percentage)
|
|
||||||
if (this.options.plp) this.setPLP(this.options.plp);
|
|
||||||
} catch (err) {
|
|
||||||
// Opus engine likely has no support for libopus CTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
encode(buffer) {
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
decode(buffer) {
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {} // eslint-disable-line no-empty-function
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = BaseOpus;
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
const OpusEngine = require('./BaseOpusEngine');
|
|
||||||
|
|
||||||
let opus;
|
|
||||||
|
|
||||||
class NodeOpusEngine extends OpusEngine {
|
|
||||||
constructor(player) {
|
|
||||||
super(player);
|
|
||||||
try {
|
|
||||||
opus = require('node-opus');
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
this.encoder = new opus.OpusEncoder(this.samplingRate, this.channels);
|
|
||||||
super.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
setBitrate(bitrate) {
|
|
||||||
this.encoder.applyEncoderCTL(this.ctl.BITRATE, Math.min(128, Math.max(16, bitrate)) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFEC(enabled) {
|
|
||||||
this.encoder.applyEncoderCTL(this.ctl.FEC, enabled ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPLP(percent) {
|
|
||||||
this.encoder.applyEncoderCTL(this.ctl.PLP, Math.min(100, Math.max(0, percent * 100)));
|
|
||||||
}
|
|
||||||
|
|
||||||
encode(buffer) {
|
|
||||||
super.encode(buffer);
|
|
||||||
return this.encoder.encode(buffer, 1920);
|
|
||||||
}
|
|
||||||
|
|
||||||
decode(buffer) {
|
|
||||||
super.decode(buffer);
|
|
||||||
return this.encoder.decode(buffer, 1920);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NodeOpusEngine;
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
const { Error } = require('../../../errors');
|
|
||||||
|
|
||||||
const list = [
|
|
||||||
require('./NodeOpusEngine'),
|
|
||||||
require('./OpusScriptEngine'),
|
|
||||||
];
|
|
||||||
|
|
||||||
function fetch(Encoder, engineOptions) {
|
|
||||||
try {
|
|
||||||
return new Encoder(engineOptions);
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === 'MODULE_NOT_FOUND') return null;
|
|
||||||
|
|
||||||
// The Opus engine exists, but another error occurred.
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.add = encoder => {
|
|
||||||
list.push(encoder);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.fetch = engineOptions => {
|
|
||||||
for (const encoder of list) {
|
|
||||||
const fetched = fetch(encoder, engineOptions);
|
|
||||||
if (fetched) return fetched;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('OPUS_ENGINE_MISSING');
|
|
||||||
};
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
const OpusEngine = require('./BaseOpusEngine');
|
|
||||||
|
|
||||||
let OpusScript;
|
|
||||||
|
|
||||||
class OpusScriptEngine extends OpusEngine {
|
|
||||||
constructor(player) {
|
|
||||||
super(player);
|
|
||||||
try {
|
|
||||||
OpusScript = require('opusscript');
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
this.encoder = new OpusScript(this.samplingRate, this.channels);
|
|
||||||
super.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
setBitrate(bitrate) {
|
|
||||||
this.encoder.encoderCTL(this.ctl.BITRATE, Math.min(128, Math.max(16, bitrate)) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFEC(enabled) {
|
|
||||||
this.encoder.encoderCTL(this.ctl.FEC, enabled ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPLP(percent) {
|
|
||||||
this.encoder.encoderCTL(this.ctl.PLP, Math.min(100, Math.max(0, percent * 100)));
|
|
||||||
}
|
|
||||||
|
|
||||||
encode(buffer) {
|
|
||||||
super.encode(buffer);
|
|
||||||
return this.encoder.encode(buffer, 960);
|
|
||||||
}
|
|
||||||
|
|
||||||
decode(buffer) {
|
|
||||||
super.decode(buffer);
|
|
||||||
return this.encoder.decode(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
super.destroy();
|
|
||||||
this.encoder.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = OpusScriptEngine;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
const { Readable } = require('stream');
|
|
||||||
|
|
||||||
class VoiceReadable extends Readable { _read() {} } // eslint-disable-line no-empty-function
|
|
||||||
|
|
||||||
module.exports = VoiceReadable;
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
const EventEmitter = require('events');
|
|
||||||
const secretbox = require('../util/Secretbox');
|
|
||||||
const Readable = require('./VoiceReadable');
|
|
||||||
const OpusEncoders = require('../opus/OpusEngineList');
|
|
||||||
const { Error } = require('../../../errors');
|
|
||||||
|
|
||||||
const nonce = Buffer.alloc(24);
|
|
||||||
nonce.fill(0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives voice data from a voice connection.
|
|
||||||
* ```js
|
|
||||||
* // Obtained using:
|
|
||||||
* voiceChannel.join()
|
|
||||||
* .then(connection => {
|
|
||||||
* const receiver = connection.createReceiver();
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
* @extends {EventEmitter}
|
|
||||||
*/
|
|
||||||
class VoiceReceiver extends EventEmitter {
|
|
||||||
constructor(connection) {
|
|
||||||
super();
|
|
||||||
/*
|
|
||||||
Need a queue because we don't get the ssrc of the user speaking until after the first few packets,
|
|
||||||
so we queue up unknown SSRCs until they become known, then empty the queue
|
|
||||||
*/
|
|
||||||
this.queues = new Map();
|
|
||||||
this.pcmStreams = new Map();
|
|
||||||
this.opusStreams = new Map();
|
|
||||||
this.opusEncoders = new Map();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not this receiver has been destroyed
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
this.destroyed = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The VoiceConnection that instantiated this
|
|
||||||
* @type {VoiceConnection}
|
|
||||||
*/
|
|
||||||
this.voiceConnection = connection;
|
|
||||||
|
|
||||||
this._listener = msg => {
|
|
||||||
const ssrc = +msg.readUInt32BE(8).toString(10);
|
|
||||||
const user = this.voiceConnection.ssrcMap.get(ssrc);
|
|
||||||
if (!user) {
|
|
||||||
if (!this.queues.has(ssrc)) this.queues.set(ssrc, []);
|
|
||||||
this.queues.get(ssrc).push(msg);
|
|
||||||
} else {
|
|
||||||
if (this.queues.get(ssrc)) {
|
|
||||||
this.queues.get(ssrc).push(msg);
|
|
||||||
this.queues.get(ssrc).map(m => this.handlePacket(m, user));
|
|
||||||
this.queues.delete(ssrc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.handlePacket(msg, user);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.voiceConnection.sockets.udp.socket.on('message', this._listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this VoiceReceiver has been destroyed, running `recreate()` will recreate the listener.
|
|
||||||
* This avoids you having to create a new receiver.
|
|
||||||
* <info>Any streams that you had prior to destroying the receiver will not be recreated.</info>
|
|
||||||
*/
|
|
||||||
recreate() {
|
|
||||||
if (!this.destroyed) return;
|
|
||||||
this.voiceConnection.sockets.udp.socket.on('message', this._listener);
|
|
||||||
this.destroyed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys this VoiceReceiver, also ending any streams that it may be controlling.
|
|
||||||
*/
|
|
||||||
destroy() {
|
|
||||||
this.voiceConnection.sockets.udp.socket.removeListener('message', this._listener);
|
|
||||||
for (const [id, stream] of this.pcmStreams) {
|
|
||||||
stream._push(null);
|
|
||||||
this.pcmStreams.delete(id);
|
|
||||||
}
|
|
||||||
for (const [id, stream] of this.opusStreams) {
|
|
||||||
stream._push(null);
|
|
||||||
this.opusStreams.delete(id);
|
|
||||||
}
|
|
||||||
for (const [id, encoder] of this.opusEncoders) {
|
|
||||||
encoder.destroy();
|
|
||||||
this.opusEncoders.delete(id);
|
|
||||||
}
|
|
||||||
this.destroyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when a user stops speaking.
|
|
||||||
* @param {User} user The user that stopped speaking
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
stoppedSpeaking(user) {
|
|
||||||
const opusStream = this.opusStreams.get(user.id);
|
|
||||||
const pcmStream = this.pcmStreams.get(user.id);
|
|
||||||
const opusEncoder = this.opusEncoders.get(user.id);
|
|
||||||
if (opusStream) {
|
|
||||||
opusStream.push(null);
|
|
||||||
opusStream.open = false;
|
|
||||||
this.opusStreams.delete(user.id);
|
|
||||||
}
|
|
||||||
if (pcmStream) {
|
|
||||||
pcmStream.push(null);
|
|
||||||
pcmStream.open = false;
|
|
||||||
this.pcmStreams.delete(user.id);
|
|
||||||
}
|
|
||||||
if (opusEncoder) {
|
|
||||||
opusEncoder.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a readable stream for a user that provides opus data while the user is speaking. When the user
|
|
||||||
* stops speaking, the stream is destroyed.
|
|
||||||
* @param {UserResolvable} user The user to create the stream for
|
|
||||||
* @returns {ReadableStream}
|
|
||||||
*/
|
|
||||||
createOpusStream(user) {
|
|
||||||
user = this.voiceConnection.voiceManager.client.users.resolve(user);
|
|
||||||
if (!user) throw new Error('VOICE_USER_MISSING');
|
|
||||||
if (this.opusStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
|
||||||
const stream = new Readable();
|
|
||||||
this.opusStreams.set(user.id, stream);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a readable stream for a user that provides PCM data while the user is speaking. When the user
|
|
||||||
* stops speaking, the stream is destroyed. The stream is 32-bit signed stereo PCM at 48KHz.
|
|
||||||
* @param {UserResolvable} user The user to create the stream for
|
|
||||||
* @returns {ReadableStream}
|
|
||||||
*/
|
|
||||||
createPCMStream(user) {
|
|
||||||
user = this.voiceConnection.voiceManager.client.users.resolve(user);
|
|
||||||
if (!user) throw new Error('VOICE_USER_MISSING');
|
|
||||||
if (this.pcmStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
|
||||||
const stream = new Readable();
|
|
||||||
this.pcmStreams.set(user.id, stream);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePacket(msg, user) {
|
|
||||||
msg.copy(nonce, 0, 0, 12);
|
|
||||||
let data = secretbox.methods.open(msg.slice(12), nonce, this.voiceConnection.authentication.secretKey);
|
|
||||||
if (!data) {
|
|
||||||
/**
|
|
||||||
* Emitted whenever a voice packet experiences a problem.
|
|
||||||
* @event VoiceReceiver#warn
|
|
||||||
* @param {string} reason The reason for the warning. If it happened because the voice packet could not be
|
|
||||||
* decrypted, this would be `decrypt`. If it happened because the voice packet could not be decoded into
|
|
||||||
* PCM, this would be `decode`
|
|
||||||
* @param {string} message The warning message
|
|
||||||
*/
|
|
||||||
this.emit('warn', 'decrypt', 'Failed to decrypt voice packet');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data = Buffer.from(data);
|
|
||||||
|
|
||||||
// Strip RTP Header Extensions (one-byte only)
|
|
||||||
if (data[0] === 0xBE && data[1] === 0xDE && data.length > 4) {
|
|
||||||
const headerExtensionLength = data.readUInt16BE(2);
|
|
||||||
let offset = 4;
|
|
||||||
for (let i = 0; i < headerExtensionLength; i++) {
|
|
||||||
const byte = data[offset];
|
|
||||||
offset++;
|
|
||||||
if (byte === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
offset += 1 + (0b1111 & (byte >> 4));
|
|
||||||
}
|
|
||||||
while (data[offset] === 0) {
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
data = data.slice(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.opusStreams.get(user.id)) this.opusStreams.get(user.id)._push(data);
|
|
||||||
/**
|
|
||||||
* Emitted whenever voice data is received from the voice connection. This is _always_ emitted (unlike PCM).
|
|
||||||
* @event VoiceReceiver#opus
|
|
||||||
* @param {User} user The user that is sending the buffer (is speaking)
|
|
||||||
* @param {Buffer} buffer The opus buffer
|
|
||||||
*/
|
|
||||||
this.emit('opus', user, data);
|
|
||||||
if (this.listenerCount('pcm') > 0 || this.pcmStreams.size > 0) {
|
|
||||||
if (!this.opusEncoders.get(user.id)) this.opusEncoders.set(user.id, OpusEncoders.fetch());
|
|
||||||
const { pcm, error } = VoiceReceiver._tryDecode(this.opusEncoders.get(user.id), data);
|
|
||||||
if (error) {
|
|
||||||
this.emit('warn', 'decode', `Failed to decode packet voice to PCM because: ${error.message}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.pcmStreams.get(user.id)) this.pcmStreams.get(user.id)._push(pcm);
|
|
||||||
/**
|
|
||||||
* Emits decoded voice data when it's received. For performance reasons, the decoding will only
|
|
||||||
* happen if there is at least one `pcm` listener on this receiver.
|
|
||||||
* @event VoiceReceiver#pcm
|
|
||||||
* @param {User} user The user that is sending the buffer (is speaking)
|
|
||||||
* @param {Buffer} buffer The decoded buffer
|
|
||||||
*/
|
|
||||||
this.emit('pcm', user, pcm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static _tryDecode(encoder, data) {
|
|
||||||
try {
|
|
||||||
return { pcm: encoder.decode(data) };
|
|
||||||
} catch (error) {
|
|
||||||
return { error };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = VoiceReceiver;
|
|
||||||
Reference in New Issue
Block a user