adding some method, and look for cause issue #3

This commit is contained in:
Auzan 2018-04-20 11:43:27 +07:00
parent 218f81d5be
commit f6ef5949a1
5 changed files with 83 additions and 40 deletions

View File

@ -65,9 +65,9 @@ namespace mumlib {
int getChannelId(); int getChannelId();
vector<MumbleUser> getListUser(); vector<MumbleUser> getListAllUser();
vector<MumbleChannel> getListChannel(); vector<MumbleChannel> getListAllChannel();
void sendAudioData(int16_t *pcmData, int pcmLength); void sendAudioData(int16_t *pcmData, int pcmLength);
@ -79,9 +79,9 @@ namespace mumlib {
void joinChannel(std::string channelName); void joinChannel(std::string channelName);
void sendVoiceTarget(int targetId, int channelId); void sendVoiceTarget(mumlib::VoiceTargetType type, int targetId, int id);
void sendVoiceTarget(int targetId, std::string channelName); bool sendVoiceTarget(mumlib::VoiceTargetType type, int targetId, std::string name);
void sendUserState(mumlib::UserState state, bool val); void sendUserState(mumlib::UserState state, bool val);
@ -90,6 +90,8 @@ namespace mumlib {
private: private:
_Mumlib_Private *impl; _Mumlib_Private *impl;
int getListChannelIdBy(std::string channelName); int getChannelIdBy(std::string channelName);
int getUserIdBy(std::string userName);
}; };
} }

View File

@ -55,4 +55,9 @@ namespace mumlib {
PRIORITY_SPEAKER, PRIORITY_SPEAKER,
RECORDING RECORDING
}; };
enum class VoiceTargetType {
CHANNEL,
USER
};
} }

View File

@ -76,6 +76,16 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
% inputLength % dataPointer % opusDataLength).str()); % inputLength % dataPointer % opusDataLength).str());
} }
// Issue #3 (Users speaking simultaneously)
// https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__decoder.html
// Opus is a stateful codec with overlapping blocks and as a result Opus packets are not coded independently of each other.
// Packets must be passed into the decoder serially and in the correct order for a correct decode.
// Lost packets can be replaced with loss concealment by calling the decoder with a null pointer and zero length for the missing packet.
// A single codec state may only be accessed from a single thread at a time and any required locking must be performed by the caller.
// Separate streams must be decoded with separate decoder states and can be decoded in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK defined.
int frame = opus_packet_get_nb_frames(&inputBuffer[dataPointer], opusDataLength);
int samples = frame * opus_packet_get_samples_per_frame(&inputBuffer[dataPointer], sampleRate);
int outputSize = opus_decode(opusDecoder, int outputSize = opus_decode(opusDecoder,
reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]), reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]),
opusDataLength, opusDataLength,
@ -133,7 +143,7 @@ int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int in
memcpy(outputBuffer, &header[0], header.size()); memcpy(outputBuffer, &header[0], header.size());
memcpy(outputBuffer + header.size(), tmpOpusBuffer, (size_t) outputSize); memcpy(outputBuffer + header.size(), tmpOpusBuffer, (size_t) outputSize);
int incrementNumber = 100 * inputLength / this->sampleRate; int incrementNumber = 100 * inputLength / sampleRate;
outgoingSequenceNumber += incrementNumber; outgoingSequenceNumber += incrementNumber;

View File

@ -191,34 +191,13 @@ bool mumlib::CryptState::decrypt(const unsigned char *source, unsigned char *dst
return true; return true;
} }
#if defined(__LP64__)
#define BLOCKSIZE 2 #define BLOCKSIZE 2
#define SHIFTBITS 63 #define SHIFTBITS 63
typedef uint64_t subblock; typedef uint64_t subblock;
#ifdef __x86_64__ #define SWAP64(x) (__builtin_bswap64(x))
static inline uint64_t SWAP64(register uint64_t __in) { register uint64_t __out; __asm__("bswap %q0" : "=r"(__out) : "0"(__in)); return __out; }
#else
#define SWAP64(x) ((static_cast<uint64_t>(x) << 56) | \
((static_cast<uint64_t>(x) << 40) & 0xff000000000000ULL) | \
((static_cast<uint64_t>(x) << 24) & 0xff0000000000ULL) | \
((static_cast<uint64_t>(x) << 8) & 0xff00000000ULL) | \
((static_cast<uint64_t>(x) >> 8) & 0xff000000ULL) | \
((static_cast<uint64_t>(x) >> 24) & 0xff0000ULL) | \
((static_cast<uint64_t>(x) >> 40) & 0xff00ULL) | \
((static_cast<uint64_t>(x) >> 56)))
#endif
// #define SWAP64(x) (__builtin_bswap64(x))
#define SWAPPED(x) SWAP64(x) #define SWAPPED(x) SWAP64(x)
#else
#define BLOCKSIZE 4
#define SHIFTBITS 31
typedef uint32_t subblock;
#define SWAPPED(x) htonl(x)
#endif
typedef subblock keyblock[BLOCKSIZE]; typedef subblock keyblock[BLOCKSIZE];
static void inline XOR(subblock *dst, const subblock *a, const subblock *b) { static void inline XOR(subblock *dst, const subblock *a, const subblock *b) {

View File

@ -65,6 +65,8 @@ namespace mumlib {
auto incomingAudioPacket = audio.decodeIncomingAudioPacket(buffer, length); auto incomingAudioPacket = audio.decodeIncomingAudioPacket(buffer, length);
if (type == AudioPacketType::OPUS) { if (type == AudioPacketType::OPUS) {
// todo: multiple users speaking simultaneously (Issue #3)
// something weird while decoding the opus payload
int16_t pcmData[5000]; int16_t pcmData[5000];
auto status = audio.decodeOpusPayload(incomingAudioPacket.audioPayload, auto status = audio.decodeOpusPayload(incomingAudioPacket.audioPayload,
incomingAudioPacket.audioPayloadLength, incomingAudioPacket.audioPayloadLength,
@ -127,6 +129,11 @@ namespace mumlib {
case MessageType::CHANNELREMOVE: { case MessageType::CHANNELREMOVE: {
MumbleProto::ChannelRemove channelRemove; MumbleProto::ChannelRemove channelRemove;
channelRemove.ParseFromArray(buffer, length); channelRemove.ParseFromArray(buffer, length);
if(isListChannelContains(channelRemove.channel_id())) {
listChannelRemovedBy(channelRemove.channel_id());
}
callback.channelRemove(channelRemove.channel_id()); callback.channelRemove(channelRemove.channel_id());
} }
break; break;
@ -381,6 +388,12 @@ namespace mumlib {
return true; return true;
return false; return false;
} }
void listChannelRemovedBy(int channelId) {
for(int i = 0; i < listMumbleChannel.size(); i++)
if(listMumbleChannel[i].channelId == channelId)
listMumbleChannel.erase(listMumbleChannel.begin() + i);
}
}; };
Mumlib::Mumlib(Callback &callback) { Mumlib::Mumlib(Callback &callback) {
@ -413,11 +426,11 @@ namespace mumlib {
return impl->channelId; return impl->channelId;
} }
vector<mumlib::MumbleUser> Mumlib::getListUser() { vector<mumlib::MumbleUser> Mumlib::getListAllUser() {
return impl->listMumbleUser; return impl->listMumbleUser;
} }
vector<mumlib::MumbleChannel> Mumlib::getListChannel() { vector<mumlib::MumbleChannel> Mumlib::getListAllChannel() {
return impl->listMumbleChannel; return impl->listMumbleChannel;
} }
@ -468,23 +481,48 @@ namespace mumlib {
} }
void Mumlib::joinChannel(string name) { void Mumlib::joinChannel(string name) {
int channelId = Mumlib::getListChannelIdBy(name); int channelId = Mumlib::getChannelIdBy(name);
Mumlib::joinChannel(channelId); if(!channelId < 0) // when channel has not been registered / create
Mumlib::joinChannel(channelId);
} }
void Mumlib::sendVoiceTarget(int targetId, int channelId) { void Mumlib::sendVoiceTarget(VoiceTargetType type, int targetId, int id) {
MumbleProto::VoiceTarget voiceTarget; MumbleProto::VoiceTarget voiceTarget;
MumbleProto::VoiceTarget_Target voiceTargetTarget; MumbleProto::VoiceTarget_Target voiceTargetTarget;
voiceTargetTarget.set_channel_id(channelId); switch(type) {
voiceTargetTarget.set_children(true); case VoiceTargetType::CHANNEL: {
voiceTargetTarget.set_channel_id(id);
voiceTargetTarget.set_children(true);
}
break;
case VoiceTargetType::USER: {
voiceTargetTarget.add_session(id);
}
break;
default:
return;
}
voiceTarget.set_id(targetId); voiceTarget.set_id(targetId);
voiceTarget.add_targets()->CopyFrom(voiceTargetTarget); voiceTarget.add_targets()->CopyFrom(voiceTargetTarget);
impl->transport.sendControlMessage(MessageType::VOICETARGET, voiceTarget); impl->transport.sendControlMessage(MessageType::VOICETARGET, voiceTarget);
} }
void Mumlib::sendVoiceTarget(int targetId, string channelName) { bool Mumlib::sendVoiceTarget(VoiceTargetType type, int targetId, string name) {
int channelId = Mumlib::getListChannelIdBy(channelName); int id = -1;
Mumlib::sendVoiceTarget(targetId, channelId); switch(type) {
case VoiceTargetType::CHANNEL:
id = getChannelIdBy(name);
break;
case VoiceTargetType::USER:
id = getUserIdBy(name);
break;
default:
break;
}
if(id < 0)
return false;
sendVoiceTarget(type, targetId, id);
return true;
} }
void Mumlib::sendUserState(mumlib::UserState field, bool val) { void Mumlib::sendUserState(mumlib::UserState field, bool val) {
@ -551,12 +589,21 @@ namespace mumlib {
impl->transport.sendControlMessage(MessageType::USERSTATE, userState); impl->transport.sendControlMessage(MessageType::USERSTATE, userState);
} }
int Mumlib::getListChannelIdBy(string name) { int Mumlib::getChannelIdBy(string name) {
vector<mumlib::MumbleChannel> listMumbleChannel = impl->listMumbleChannel; vector<mumlib::MumbleChannel> listMumbleChannel = impl->listMumbleChannel;
int channelId = impl->channelId; int channelId = -1;
for(int i = 0; i < listMumbleChannel.size(); i++) for(int i = 0; i < listMumbleChannel.size(); i++)
if(listMumbleChannel[i].name == name) if(listMumbleChannel[i].name == name)
channelId = listMumbleChannel[i].channelId; channelId = listMumbleChannel[i].channelId;
return channelId; return channelId;
} }
int Mumlib::getUserIdBy(string name) {
vector<mumlib::MumbleUser> listMumbleUser = impl->listMumbleUser;
int sessionId = -1;
for(int i = 0; i < listMumbleUser.size(); i++)
if(listMumbleUser[i].name == name)
sessionId = listMumbleUser[i].sessionId;
return sessionId;
}
} }