merge and clean
This commit is contained in:
commit
f362194922
@ -42,7 +42,7 @@ set(MUMLIB_SRC
|
|||||||
src/Audio.cpp
|
src/Audio.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MUMLIB_LIBRARIES
|
set(SPEEX_LIBRARIES
|
||||||
speex
|
speex
|
||||||
speexdsp
|
speexdsp
|
||||||
)
|
)
|
||||||
@ -50,15 +50,15 @@ set(MUMLIB_LIBRARIES
|
|||||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS Mumble.proto)
|
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS Mumble.proto)
|
||||||
|
|
||||||
add_library(mumlib SHARED ${MUMLIB_SRC} ${MUMLIB_PUBLIC_HEADERS} ${MUMLIB_PRIVATE_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS})
|
add_library(mumlib SHARED ${MUMLIB_SRC} ${MUMLIB_PUBLIC_HEADERS} ${MUMLIB_PRIVATE_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS})
|
||||||
target_link_libraries(mumlib ${MUMLIB_LIBRARIES})
|
target_link_libraries(mumlib
|
||||||
target_link_libraries(mumlib ${PROTOBUF_LIBRARIES})
|
${SPEEX_LIBRARIES}
|
||||||
target_link_libraries(mumlib ${Boost_LIBRARIES})
|
${PROTOBUF_LIBRARIES}
|
||||||
target_link_libraries(mumlib ${OPENSSL_LIBRARIES})
|
${Boost_LIBRARIES}
|
||||||
target_link_libraries(mumlib ${LOG4CPP_LIBRARIES})
|
${OPENSSL_LIBRARIES}
|
||||||
target_link_libraries(mumlib ${OPUS_LIBRARIES})
|
${LOG4CPP_LIBRARIES}
|
||||||
|
${OPUS_LIBRARIES})
|
||||||
|
|
||||||
|
# add_executable(mumlib_example mumlib_example.cpp)
|
||||||
add_executable(mumlib_example mumlib_example.cpp)
|
# target_link_libraries(mumlib_example mumlib)
|
||||||
target_link_libraries(mumlib_example mumlib)
|
|
||||||
|
|
||||||
install(TARGETS mumlib LIBRARY DESTINATION lib)
|
install(TARGETS mumlib LIBRARY DESTINATION lib)
|
||||||
|
@ -38,19 +38,19 @@ namespace mumlib {
|
|||||||
|
|
||||||
void addFrameToBuffer(uint8_t *inputBuffer, int inputLength, int sequence);
|
void addFrameToBuffer(uint8_t *inputBuffer, int inputLength, int sequence);
|
||||||
|
|
||||||
void fetchAudio(uint8_t *inputBuffer, int bufferOffset, int inputLength);
|
// todo: mix audio
|
||||||
|
void mixAudio(uint8_t *dest, uint8_t *src, int bufferOffset, int inputLength);
|
||||||
void mixAudio(uint8_t *inputBuffer, uint8_t *outputBuffer, int bufferOffset, int inputLength);
|
|
||||||
|
|
||||||
void resizeBuffer();
|
void resizeBuffer();
|
||||||
|
|
||||||
|
std::pair<int, bool> decodeOpusPayload(int16_t *pcmBuffer,
|
||||||
|
int pcmBufferSize);
|
||||||
|
|
||||||
std::pair<int, bool> decodeOpusPayload(uint8_t *inputBuffer,
|
std::pair<int, bool> decodeOpusPayload(uint8_t *inputBuffer,
|
||||||
int inputLength,
|
int inputLength,
|
||||||
int16_t *pcmBuffer,
|
int16_t *pcmBuffer,
|
||||||
int pcmBufferSize);
|
int pcmBufferSize);
|
||||||
|
|
||||||
std::pair<int, bool> decodeOpusPayload(int16_t *pcmBuffer,
|
|
||||||
int pcmBufferSize);
|
|
||||||
|
|
||||||
int encodeAudioPacket(
|
int encodeAudioPacket(
|
||||||
int target,
|
int target,
|
||||||
@ -74,17 +74,15 @@ namespace mumlib {
|
|||||||
OpusEncoder *opusEncoder;
|
OpusEncoder *opusEncoder;
|
||||||
JitterBuffer *jbBuffer;
|
JitterBuffer *jbBuffer;
|
||||||
|
|
||||||
mutex m_jitter_mutex;
|
|
||||||
|
|
||||||
int64_t outgoingSequenceNumber;
|
int64_t outgoingSequenceNumber;
|
||||||
|
|
||||||
unsigned int mSampleRate;
|
unsigned int iSampleRate;
|
||||||
unsigned int mChannels;
|
unsigned int iChannels;
|
||||||
unsigned int mFrameSize;
|
unsigned int iFrameSize;
|
||||||
unsigned int mAudioBufferSize;
|
unsigned int iAudioBufferSize;
|
||||||
|
|
||||||
float *mFadeIn;
|
float *fFadeIn;
|
||||||
float *mFadeOut;
|
float *fFadeOut;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::system_clock> lastEncodedAudioPacketTimestamp;
|
std::chrono::time_point<std::chrono::system_clock> lastEncodedAudioPacketTimestamp;
|
||||||
};
|
};
|
||||||
|
@ -8,14 +8,14 @@ mumlib::Audio::Audio(int sampleRate, int bitrate, int channels)
|
|||||||
: logger(log4cpp::Category::getInstance("mumlib.Audio")),
|
: logger(log4cpp::Category::getInstance("mumlib.Audio")),
|
||||||
opusDecoder(nullptr),
|
opusDecoder(nullptr),
|
||||||
opusEncoder(nullptr),
|
opusEncoder(nullptr),
|
||||||
outgoingSequenceNumber(0) {
|
outgoingSequenceNumber(0),
|
||||||
|
iSampleRate(sampleRate),
|
||||||
|
iChannels(channels) {
|
||||||
|
|
||||||
int error, ret;
|
int error, ret;
|
||||||
mSampleRate = sampleRate;
|
iFrameSize = sampleRate / 100;
|
||||||
mChannels = channels;
|
iAudioBufferSize = iFrameSize;
|
||||||
mFrameSize = sampleRate / 100;
|
iAudioBufferSize *= 12;
|
||||||
mAudioBufferSize = mFrameSize;
|
|
||||||
mAudioBufferSize *= 12;
|
|
||||||
|
|
||||||
opusDecoder = opus_decoder_create(sampleRate, channels, &error);
|
opusDecoder = opus_decoder_create(sampleRate, channels, &error);
|
||||||
if (error != OPUS_OK) {
|
if (error != OPUS_OK) {
|
||||||
@ -55,17 +55,17 @@ mumlib::Audio::Audio(int sampleRate, int bitrate, int channels)
|
|||||||
|
|
||||||
resetEncoder();
|
resetEncoder();
|
||||||
|
|
||||||
jbBuffer = jitter_buffer_init(mFrameSize);
|
jbBuffer = jitter_buffer_init(iFrameSize);
|
||||||
int margin = 10 * mFrameSize;
|
int margin = 10 * iFrameSize;
|
||||||
jitter_buffer_ctl(jbBuffer, JITTER_BUFFER_SET_MARGIN, &margin);
|
jitter_buffer_ctl(jbBuffer, JITTER_BUFFER_SET_MARGIN, &margin);
|
||||||
|
|
||||||
mFadeIn = new float[mFrameSize];
|
fFadeIn = new float[iFrameSize];
|
||||||
mFadeOut = new float[mFrameSize];
|
fFadeOut = new float[iFrameSize];
|
||||||
|
|
||||||
// Sine function to represent fade in/out. Period is FRAME_SIZE.
|
// Sine function to represent fade in/out. Period is FRAME_SIZE.
|
||||||
float mul = static_cast<float>(M_PI / 2.0 * static_cast<double>(mFrameSize));
|
float mul = static_cast<float>(M_PI / 2.0 * static_cast<double>(iFrameSize));
|
||||||
for(unsigned int i = 0; i < mFrameSize; i++) {
|
for(unsigned int i = 0; i < iFrameSize; i++) {
|
||||||
mFadeIn[i] = mFadeOut[mFrameSize - 1 - 1] = sinf(static_cast<float>(i) * mul);
|
fFadeIn[i] = fFadeOut[iFrameSize - 1 - 1] = sinf(static_cast<float>(i) * mul);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,8 +80,8 @@ mumlib::Audio::~Audio() {
|
|||||||
|
|
||||||
jitter_buffer_destroy(jbBuffer);
|
jitter_buffer_destroy(jbBuffer);
|
||||||
|
|
||||||
delete[] mFadeIn;
|
delete[] fFadeIn;
|
||||||
delete[] mFadeOut;
|
delete[] fFadeOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mumlib::Audio::setOpusEncoderBitrate(int bitrate) {
|
void mumlib::Audio::setOpusEncoderBitrate(int bitrate) {
|
||||||
@ -111,17 +111,20 @@ void mumlib::Audio::addFrameToBuffer(uint8_t *inputBuffer, int inputLength, int
|
|||||||
|
|
||||||
auto *packet = reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]);
|
auto *packet = reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]);
|
||||||
int frame = opus_packet_get_nb_frames(packet, opusDataLength);
|
int frame = opus_packet_get_nb_frames(packet, opusDataLength);
|
||||||
int samples = frame * opus_packet_get_samples_per_frame(packet, mSampleRate);
|
int samples = frame * opus_packet_get_samples_per_frame(packet, iSampleRate);
|
||||||
|
int channel = opus_packet_get_nb_channels(packet);
|
||||||
|
|
||||||
if(not sequence) {
|
if(not sequence) {
|
||||||
resetJitterBuffer();
|
resetJitterBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info("Opus packet, frame: %d, samples: %d, channel: %d", frame, samples, channel);
|
||||||
|
|
||||||
JitterBufferPacket jbPacket;
|
JitterBufferPacket jbPacket;
|
||||||
jbPacket.data = reinterpret_cast<char *>(&inputBuffer[dataPointer]);
|
jbPacket.data = reinterpret_cast<char *>(&inputBuffer[dataPointer]);
|
||||||
jbPacket.len = opusDataLength;
|
jbPacket.len = opusDataLength;
|
||||||
jbPacket.span = samples;
|
jbPacket.span = samples;
|
||||||
jbPacket.timestamp = mFrameSize * sequence;
|
jbPacket.timestamp = iFrameSize * sequence;
|
||||||
jbPacket.user_data = lastPacket;
|
jbPacket.user_data = lastPacket;
|
||||||
|
|
||||||
jitter_buffer_put(jbBuffer, &jbPacket);
|
jitter_buffer_put(jbBuffer, &jbPacket);
|
||||||
@ -129,8 +132,12 @@ void mumlib::Audio::addFrameToBuffer(uint8_t *inputBuffer, int inputLength, int
|
|||||||
|
|
||||||
std::pair<int, bool> mumlib::Audio::decodeOpusPayload(int16_t *pcmBuffer, int pcmBufferSize) {
|
std::pair<int, bool> mumlib::Audio::decodeOpusPayload(int16_t *pcmBuffer, int pcmBufferSize) {
|
||||||
int avail = 0;
|
int avail = 0;
|
||||||
int ts = jitter_buffer_get_pointer_timestamp(jbBuffer);
|
spx_uint32_t remaining = 0;
|
||||||
jitter_buffer_ctl(jbBuffer, JITTER_BUFFER_GET_AVAILABLE_COUNT, &avail);
|
jitter_buffer_ctl(jbBuffer, JITTER_BUFFER_GET_AVAILABLE_COUNT, &avail);
|
||||||
|
jitter_buffer_remaining_span(jbBuffer, remaining);
|
||||||
|
int timestamp = jitter_buffer_get_pointer_timestamp(jbBuffer);
|
||||||
|
|
||||||
|
logger.warn("jbBufer, avail: %d, remain: %d, timestamp: %d", avail, remaining, timestamp);
|
||||||
|
|
||||||
char data[4096];
|
char data[4096];
|
||||||
JitterBufferPacket jbPacket;
|
JitterBufferPacket jbPacket;
|
||||||
@ -142,10 +149,9 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(int16_t *pcmBuffer, int pc
|
|||||||
int outputSize;
|
int outputSize;
|
||||||
spx_uint32_t lastPacket;
|
spx_uint32_t lastPacket;
|
||||||
|
|
||||||
if(jitter_buffer_get(jbBuffer, &jbPacket, mFrameSize, &startofs) == JITTER_BUFFER_OK) {
|
if(jitter_buffer_get(jbBuffer, &jbPacket, iFrameSize, &startofs) == JITTER_BUFFER_OK) {
|
||||||
opusDataLength = jbPacket.len;
|
opusDataLength = jbPacket.len;
|
||||||
lastPacket = jbPacket.user_data;
|
lastPacket = jbPacket.user_data;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
jitter_buffer_update_delay(jbBuffer, &jbPacket, NULL);
|
jitter_buffer_update_delay(jbBuffer, &jbPacket, NULL);
|
||||||
}
|
}
|
||||||
@ -162,16 +168,16 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(int16_t *pcmBuffer, int pc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(outputSize < 0) {
|
if(outputSize < 0) {
|
||||||
outputSize = mFrameSize;
|
outputSize = iFrameSize;
|
||||||
memset(pcmBuffer, 0, mFrameSize * sizeof(float));
|
memset(pcmBuffer, 0, iFrameSize * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lastPacket) {
|
if(lastPacket) {
|
||||||
for(unsigned int i = 0; i < mFrameSize; i++)
|
for(unsigned int i = 0; i < iFrameSize; i++)
|
||||||
pcmBuffer[i] *= mFadeOut[i];
|
pcmBuffer[i] *= fFadeOut[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = outputSize / mFrameSize; i > 0; --i) {
|
for (int i = outputSize / iFrameSize; i > 0; --i) {
|
||||||
jitter_buffer_tick(jbBuffer);
|
jitter_buffer_tick(jbBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +187,7 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(int16_t *pcmBuffer, int pc
|
|||||||
return std::make_pair(outputSize, lastPacket);
|
return std::make_pair(outputSize, lastPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mumlib::Audio::mixAudio(uint8_t *inputBuffer, uint8_t *outputBuffer, int bufferOffset, int inputLength) {
|
void mumlib::Audio::mixAudio(uint8_t *dest, uint8_t *src, int bufferOffset, int inputLength) {
|
||||||
for(int i = 0; i < inputLength; i++) {
|
for(int i = 0; i < inputLength; i++) {
|
||||||
float mix = 0;
|
float mix = 0;
|
||||||
|
|
||||||
@ -190,7 +196,7 @@ void mumlib::Audio::mixAudio(uint8_t *inputBuffer, uint8_t *outputBuffer, int bu
|
|||||||
mix = 1;
|
mix = 1;
|
||||||
else if(mix < -1)
|
else if(mix < -1)
|
||||||
mix = -1;
|
mix = -1;
|
||||||
outputBuffer[i + bufferOffset] = mix;
|
dest[i + bufferOffset] = mix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +228,7 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
|
|||||||
// Separate streams must be decoded with separate decoder states and can be decoded in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK defined.
|
// Separate streams must be decoded with separate decoder states and can be decoded in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK defined.
|
||||||
auto *packet = reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]);
|
auto *packet = reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]);
|
||||||
int frame = opus_packet_get_nb_frames(packet, opusDataLength);
|
int frame = opus_packet_get_nb_frames(packet, opusDataLength);
|
||||||
int samples = frame * opus_packet_get_samples_per_frame(packet, mSampleRate);
|
int samples = frame * opus_packet_get_samples_per_frame(packet, iSampleRate);
|
||||||
int outputSize = opus_decode(opusDecoder,
|
int outputSize = opus_decode(opusDecoder,
|
||||||
packet,
|
packet,
|
||||||
opusDataLength,
|
opusDataLength,
|
||||||
@ -280,7 +286,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 / mSampleRate;
|
int incrementNumber = 100 * inputLength / iSampleRate;
|
||||||
|
|
||||||
outgoingSequenceNumber += incrementNumber;
|
outgoingSequenceNumber += incrementNumber;
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ namespace mumlib {
|
|||||||
int sessionId = 0;
|
int sessionId = 0;
|
||||||
int channelId = 0;
|
int channelId = 0;
|
||||||
int64_t seq = 0;
|
int64_t seq = 0;
|
||||||
mutex jitter_mutex;
|
|
||||||
|
|
||||||
std::vector<MumbleUser> listMumbleUser;
|
std::vector<MumbleUser> listMumbleUser;
|
||||||
std::vector<MumbleChannel> listMumbleChannel;
|
std::vector<MumbleChannel> listMumbleChannel;
|
||||||
@ -67,8 +66,6 @@ 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];
|
||||||
|
|
||||||
audio.addFrameToBuffer(incomingAudioPacket.audioPayload,
|
audio.addFrameToBuffer(incomingAudioPacket.audioPayload,
|
||||||
@ -84,13 +81,12 @@ namespace mumlib {
|
|||||||
|
|
||||||
if(status.second) seq = 0; else seq++;
|
if(status.second) seq = 0; else seq++;
|
||||||
|
|
||||||
// logger.warn("Decode audio: %d , seq %d", incomingAudioPacket.sessionId, seq);
|
|
||||||
|
|
||||||
callback.audio(incomingAudioPacket.target,
|
callback.audio(incomingAudioPacket.target,
|
||||||
incomingAudioPacket.sessionId,
|
incomingAudioPacket.sessionId,
|
||||||
incomingAudioPacket.sequenceNumber,
|
incomingAudioPacket.sequenceNumber,
|
||||||
pcmData,
|
pcmData,
|
||||||
status.first);
|
status.first);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Incoming audio packet doesn't contain Opus data, calling unsupportedAudio callback.");
|
logger.warn("Incoming audio packet doesn't contain Opus data, calling unsupportedAudio callback.");
|
||||||
callback.unsupportedAudio(incomingAudioPacket.target,
|
callback.unsupportedAudio(incomingAudioPacket.target,
|
||||||
|
Loading…
Reference in New Issue
Block a user