///
///
class VoiceConnection {
constructor(client) {
this.codecs = [
undefined,
undefined,
undefined,
undefined,
undefined,
undefined //opus music
];
this.vpacketId = 0;
this.chunkVPacketId = 0;
this.client = client;
this.voiceRecorder = new VoiceRecorder(this);
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
this.codecs[4] = new OpusCodec(1, OpusType.VOIP);
this.codecs[5] = new OpusCodec(2, OpusType.AUDIO);
for (let index = 0; index < this.codecs.length; index++) {
if (!this.codecs[index])
continue;
let codec = this.codecs[index];
console.log("Got codec " + codec.name());
codec.initialise();
codec.on_encoded_data = buffer => this.sendVoicePacket(buffer, index);
}
}
sendVoicePacket(data, codec) {
if (this.dataChannel) {
this.vpacketId++;
if (this.vpacketId > 65535)
this.vpacketId = 0;
let packet = new Uint8Array(data.byteLength + 2 + 3);
packet[0] = this.chunkVPacketId++ < 5 ? 1 : 0; //Flag header
packet[1] = 0; //Flag frag mented
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
packet[4] = codec; //Codec
packet.set(data, 5);
this.dataChannel.send(packet);
}
else {
console.warn("Could not transfer audio (not connected)");
}
}
createSession() {
const config = {};
this.rtcPeerConnection = new RTCPeerConnection(config);
const dataChannelConfig = { ordered: false, maxRetransmits: 0 };
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
this.dataChannel.binaryType = "arraybuffer";
let sdpConstraints = {};
sdpConstraints.offerToReceiveAudio = 0;
sdpConstraints.offerToReceiveVideo = 0;
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
console.error("Could not create ice offer!");
}, sdpConstraints);
}
dropSession() {
if (this.dataChannel)
this.dataChannel.close();
if (this.rtcPeerConnection)
this.rtcPeerConnection.close();
//TODO here!
}
handleControlPacket(json) {
if (json["request"] === "create") {
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp: json["sdp"] }));
}
else if (json["request"] === "ice") {
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate({ candidate: json["candidate"], sdpMid: json["session"], sdpMLineIndex: json["line"] }));
}
}
//Listeners
onIceCandidate(event) {
console.log("Got ice candidate! Event:");
console.log(event);
if (event && event.candidate) {
this.client.serverConnection.sendData(JSON.stringify({
type: 'WebRTC',
request: "ice",
candidate: event.candidate.candidate,
line: event.candidate.sdpMLineIndex,
session: event.candidate.sdpMid
}));
}
}
onOfferCreated(localSession) {
console.log("Offer created and accepted");
this.rtcPeerConnection.setLocalDescription(localSession);
this.client.serverConnection.sendData(JSON.stringify({ type: 'WebRTC', request: "create", session: localSession }));
}
onDataChannelOpen(channel) {
console.log("Got new data channel!");
}
onDataChannelMessage(message) {
let bin = new Uint8Array(message.data);
let clientId = bin[2] << 8 | bin[3];
let packetId = bin[0] << 8 | bin[1];
let codec = bin[4];
//console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
let client = this.client.channelTree.findClient(clientId);
if (!client) {
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
return;
}
if (!this.codecs[codec]) {
console.error("Could not playback codec " + codec);
return;
}
let encodedData;
if (message.data.subarray)
encodedData = message.data.subarray(5);
else
encodedData = new Uint8Array(message.data, 5);
this.codecs[codec].decodeSamples(encodedData).then(buffer => {
client.getAudioController().play(buffer);
}).catch(error => {
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
});
}
handleVoiceData(data, head) {
if (head) {
this.chunkVPacketId = 0;
this.client.getClient().speaking = true;
}
this.codecs[4].encodeSamples(data); //TODO Use channel codec!
//this.client.getClient().getAudioController().play(data);
}
handleVoiceEnded() {
console.log("Voice ended");
this.client.getClient().speaking = false;
//TODO!
}
}
//# sourceMappingURL=VoiceHandler.js.map