private void UnpackVoicePacket(byte[] packet, int type) { var vType = (SpeechCodecs)type; var target = (SpeechTarget)(packet[0] & 0x1F); using (var reader = new UdpPacketReader(new MemoryStream(packet, 1, packet.Length - 1))) { UInt32 session = (uint)reader.ReadVarInt64(); Int64 sequence = reader.ReadVarInt64(); //Null codec means the user was not found. This can happen if a user leaves while voice packets are still in flight IVoiceCodec codec = Protocol.GetCodec(session, vType); if (codec == null) { return; } if (vType == SpeechCodecs.Opus) { int size = (int)reader.ReadVarInt64(); size &= 0x1fff; if (size == 0) { return; } byte[] data = reader.ReadBytes(size); if (data == null) { return; } Protocol.EncodedVoice(data, session, sequence, codec, target); } else { throw new NotImplementedException("Codec is not opus"); //byte header; //do //{ // header = reader.ReadByte(); // int length = header & 0x7F; // if (length > 0) // { // byte[] data = reader.ReadBytes(length); // if (data == null) // break; // //TODO: Put *encoded* packets into a queue, then decode the head of the queue // //TODO: This allows packets to come into late and be inserted into the correct place in the queue (if they arrive before decoding handles a later packet) // byte[] decodedPcmData = codec.Decode(data); // if (decodedPcmData != null) // Protocol.Voice(decodedPcmData, session, sequence); // } //} while ((header & 0x80) > 0); } } }
private void Voice(byte[] packet) { //This is all horrible! //TODO: Move all the decoding related rubbish to within the MumbleConnection (internal void ReceivedEncryptedUdp(byte[] packet) Line 78) //This should just receive ordered blocks of decoded PCM data int type = packet[0] >> 5 & 0x7; int flags = packet[0] & 0x1f; if (type != (int)SpeechCodecs.CeltAlpha && type != (int)SpeechCodecs.CeltBeta && type != (int)SpeechCodecs.Speex) return; using (var reader = new UdpPacketReader(new MemoryStream(packet, 1, packet.Length - 1))) { Int64 session = reader.ReadVarInt64(); User user; if (!_users.TryGetValue((uint)session, out user)) //If we don't know the user for this packet, just ignore the packet return; Int64 sequence = reader.ReadVarInt64(); byte header = 0; do { header = reader.ReadByte(); int length = header & 127; byte[] data = reader.ReadBytes(length); //TODO:: We have a voice packet for this user (data)... do something with it! } while ((header & 128) == 0); } }