adding some method, and look for cause issue #3
This commit is contained in:
parent
218f81d5be
commit
f6ef5949a1
@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -55,4 +55,9 @@ namespace mumlib {
|
|||||||
PRIORITY_SPEAKER,
|
PRIORITY_SPEAKER,
|
||||||
RECORDING
|
RECORDING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class VoiceTargetType {
|
||||||
|
CHANNEL,
|
||||||
|
USER
|
||||||
|
};
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user