Audio.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #include "mumlib/Audio.hpp"
  2. #include <boost/format.hpp>
  3. static boost::posix_time::seconds RESET_SEQUENCE_NUMBER_INTERVAL(5);
  4. mumlib::Audio::Audio(int opusSampleRate, int opusEncoderBitrate, int channels)
  5. : logger(log4cpp::Category::getInstance("mumlib.Audio")),
  6. opusDecoder(nullptr),
  7. opusEncoder(nullptr),
  8. outgoingSequenceNumber(0) {
  9. int error;
  10. this->sampleRate = opusSampleRate;
  11. opusDecoder = opus_decoder_create(opusSampleRate, channels, &error);
  12. if (error != OPUS_OK) {
  13. throw AudioException((boost::format("failed to initialize OPUS decoder: %s") % opus_strerror(error)).str());
  14. }
  15. opusEncoder = opus_encoder_create(opusSampleRate, channels, OPUS_APPLICATION_VOIP, &error);
  16. if (error != OPUS_OK) {
  17. throw AudioException((boost::format("failed to initialize OPUS encoder: %s") % opus_strerror(error)).str());
  18. }
  19. opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0));
  20. setOpusEncoderBitrate(opusEncoderBitrate);
  21. resetEncoder();
  22. }
  23. mumlib::Audio::~Audio() {
  24. if (opusDecoder) {
  25. opus_decoder_destroy(opusDecoder);
  26. }
  27. if (opusEncoder) {
  28. opus_encoder_destroy(opusEncoder);
  29. }
  30. }
  31. void mumlib::Audio::setOpusEncoderBitrate(int bitrate) {
  32. int error = opus_encoder_ctl(opusEncoder, OPUS_SET_BITRATE(bitrate));
  33. if (error != OPUS_OK) {
  34. throw AudioException((boost::format("failed to initialize transmission bitrate to %d B/s: %s")
  35. % bitrate % opus_strerror(error)).str());
  36. }
  37. }
  38. int mumlib::Audio::getOpusEncoderBitrate() {
  39. opus_int32 bitrate;
  40. int error = opus_encoder_ctl(opusEncoder, OPUS_GET_BITRATE(&bitrate));
  41. if (error != OPUS_OK) {
  42. throw AudioException((boost::format("failed to read Opus bitrate: %s") % opus_strerror(error)).str());
  43. }
  44. return bitrate;
  45. }
  46. std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
  47. int inputLength,
  48. int16_t *pcmBuffer,
  49. int pcmBufferSize) {
  50. int64_t opusDataLength;
  51. int dataPointer = 0;
  52. VarInt varInt(inputBuffer);
  53. opusDataLength = varInt.getValue();
  54. dataPointer += varInt.getEncoded().size();
  55. bool lastPacket = (opusDataLength & 0x2000) != 0;
  56. opusDataLength = opusDataLength & 0x1fff;
  57. if (inputLength < opusDataLength + dataPointer) {
  58. throw AudioException((boost::format("invalid Opus payload (%d B): header %d B, expected Opus data length %d B")
  59. % inputLength % dataPointer % opusDataLength).str());
  60. }
  61. // Issue #3 (Users speaking simultaneously)
  62. // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__decoder.html
  63. // Opus is a stateful codec with overlapping blocks and as a result Opus packets are not coded independently of each other.
  64. // Packets must be passed into the decoder serially and in the correct order for a correct decode.
  65. // Lost packets can be replaced with loss concealment by calling the decoder with a null pointer and zero length for the missing packet.
  66. // 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.
  67. // Separate streams must be decoded with separate decoder states and can be decoded in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK defined.
  68. int frame = opus_packet_get_nb_frames(&inputBuffer[dataPointer], opusDataLength);
  69. int samples = frame * opus_packet_get_samples_per_frame(&inputBuffer[dataPointer], sampleRate);
  70. int outputSize = opus_decode(opusDecoder,
  71. reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]),
  72. opusDataLength,
  73. pcmBuffer,
  74. pcmBufferSize,
  75. 0);
  76. if (outputSize <= 0) {
  77. throw AudioException((boost::format("failed to decode %d B of OPUS data: %s") % inputLength %
  78. opus_strerror(outputSize)).str());
  79. }
  80. logger.debug("%d B of Opus data decoded to %d PCM samples, last packet: %d.",
  81. opusDataLength, outputSize, lastPacket);
  82. return std::make_pair(outputSize, lastPacket);
  83. }
  84. int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int inputLength, uint8_t *outputBuffer,
  85. int outputBufferSize) {
  86. using namespace std::chrono;
  87. const int lastAudioPacketSentInterval = duration_cast<milliseconds>(
  88. system_clock::now() - lastEncodedAudioPacketTimestamp).count();
  89. if (lastAudioPacketSentInterval > RESET_SEQUENCE_NUMBER_INTERVAL.total_milliseconds() + 1000) {
  90. logger.debug("Last audio packet was sent %d ms ago, resetting encoder.", lastAudioPacketSentInterval);
  91. resetEncoder();
  92. }
  93. std::vector<uint8_t> header;
  94. header.push_back(static_cast<unsigned char &&>(0x80 | target));
  95. auto sequenceNumberEnc = VarInt(outgoingSequenceNumber).getEncoded();
  96. header.insert(header.end(), sequenceNumberEnc.begin(), sequenceNumberEnc.end());
  97. uint8_t tmpOpusBuffer[1024];
  98. const int outputSize = opus_encode(opusEncoder,
  99. inputPcmBuffer,
  100. inputLength,
  101. tmpOpusBuffer,
  102. min(outputBufferSize, 1024)
  103. );
  104. if (outputSize <= 0) {
  105. throw AudioException((boost::format("failed to encode %d B of PCM data: %s") % inputLength %
  106. opus_strerror(outputSize)).str());
  107. }
  108. auto outputSizeEnc = VarInt(outputSize).getEncoded();
  109. header.insert(header.end(), outputSizeEnc.begin(), outputSizeEnc.end());
  110. memcpy(outputBuffer, &header[0], header.size());
  111. memcpy(outputBuffer + header.size(), tmpOpusBuffer, (size_t) outputSize);
  112. int incrementNumber = 100 * inputLength / sampleRate;
  113. outgoingSequenceNumber += incrementNumber;
  114. lastEncodedAudioPacketTimestamp = std::chrono::system_clock::now();
  115. return static_cast<int>(outputSize + header.size());
  116. }
  117. void mumlib::Audio::resetEncoder() {
  118. int status = opus_encoder_ctl(opusEncoder, OPUS_RESET_STATE, nullptr);
  119. if (status != OPUS_OK) {
  120. throw AudioException((boost::format("failed to reset encoder: %s") % opus_strerror(status)).str());
  121. }
  122. outgoingSequenceNumber = 0;
  123. }
  124. mumlib::IncomingAudioPacket mumlib::Audio::decodeIncomingAudioPacket(uint8_t *inputBuffer, int inputBufferLength) {
  125. mumlib::IncomingAudioPacket incomingAudioPacket{};
  126. incomingAudioPacket.type = static_cast<AudioPacketType >((inputBuffer[0] & 0xE0) >> 5);
  127. incomingAudioPacket.target = inputBuffer[0] & 0x1F;
  128. std::array<int64_t *, 2> varInts = {&incomingAudioPacket.sessionId, &incomingAudioPacket.sequenceNumber};
  129. int dataPointer = 1;
  130. for (int64_t *val : varInts) {
  131. VarInt varInt(&inputBuffer[dataPointer]);
  132. *val = varInt.getValue();
  133. dataPointer += varInt.getEncoded().size();
  134. }
  135. incomingAudioPacket.audioPayload = &inputBuffer[dataPointer];
  136. incomingAudioPacket.audioPayloadLength = inputBufferLength - dataPointer;
  137. if (dataPointer >= inputBufferLength) {
  138. throw AudioException((boost::format("invalid incoming audio packet (%d B): header %d B") % inputBufferLength %
  139. dataPointer).str());
  140. }
  141. logger.debug(
  142. "Received %d B of audio packet, %d B header, %d B payload (target: %d, sessionID: %ld, seq num: %ld).",
  143. inputBufferLength,
  144. dataPointer,
  145. incomingAudioPacket.audioPayloadLength,
  146. incomingAudioPacket.target,
  147. incomingAudioPacket.sessionId,
  148. incomingAudioPacket.sequenceNumber);
  149. return incomingAudioPacket;
  150. }