Make voice receiving better

This commit is contained in:
Amish Shah
2016-08-25 23:11:58 +01:00
parent 2d6068010b
commit 48762c642c
4 changed files with 46 additions and 12 deletions

File diff suppressed because one or more lines are too long

View File

@@ -56,6 +56,7 @@ class VoiceConnection extends EventEmitter {
* @private
*/
this._reject = reject;
this.ssrcMap = new Map();
this.bindListeners();
}
@@ -143,6 +144,7 @@ class VoiceConnection extends EventEmitter {
});
this.websocket.on('speaking', data => {
const guild = this.channel.guild;
this.ssrcMap.set(+data.ssrc, this.manager.client.users.get(data.user_id));
guild._memberSpeakUpdate(data.user_id, data.speaking);
});
}

View File

@@ -11,34 +11,64 @@ nonce.fill(0);
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();
/**
* The VoiceConnection that instantiated this
* @type {VoiceConnection}
*/
this.connection = connection;
this.connection.udp.udpSocket.on('message', msg => {
msg.copy(nonce, 0, 0, 12);
let data = NaCl.secretbox.open(msg.slice(12), nonce, this.connection.data.secret);
if (!data) {
return this.emit('warn', 'failed to decrypt voice packet');
const ssrc = +msg.readUInt32BE(8).toString(10);
const user = this.connection.ssrcMap.get(ssrc);
if (!user) {
if (!this.queues.has(ssrc)) {
this.queues.set(ssrc, []);
}
this.queues.get(ssrc).push(msg);
}
data = new Buffer(data);
if (user) {
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);
}
}
});
}
handlePacket(msg, user) {
msg.copy(nonce, 0, 0, 12);
let data = NaCl.secretbox.open(msg.slice(12), nonce, this.connection.data.secret);
if (!data) {
/**
* Emitted whenever a voice packet cannot be decrypted
* @event VoiceReceiver#warn
* @param {String} message the warning message
*/
return this.emit('warn', 'failed to decrypt voice packet');
}
data = new Buffer(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', data);
if (this.listenerCount('pcm') > 0) {
this.emit('opus', user, data);
if (this.listenerCount('pcm') > 0) {
/**
* 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', this.connection.player.opusEncoder.decode(data));
}
});
this.emit('pcm', user, this.connection.player.opusEncoder.decode(data));
}
}
}

View File

@@ -145,7 +145,9 @@ client.on('message', msg => {
conn.player.on('debug', console.log);
conn.player.on('error', err => console.log(123, err));
const receiver = conn.createReceiver();
receiver.on('pcm', console.log);
receiver.on('pcm', u => {
console.log(u.username);
});
disp.on('error', err => console.log(123, err));
})
.catch(console.log);