#ifdef _WIN32 #include #endif #include "manager.hpp" #include #define MINIAUDIO_IMPLEMENTATION #include #include #include const uint8_t *StripRTPExtensionHeader(const uint8_t *buf, int num_bytes, size_t &outlen) { if (buf[0] == 0xbe && buf[1] == 0xde && num_bytes > 4) { uint64_t offset = 4 + 4 * ((buf[2] << 8) | buf[3]); outlen = num_bytes - offset; return buf + offset; } outlen = num_bytes; return buf; } void data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount) { AudioManager *mgr = reinterpret_cast(pDevice->pUserData); if (mgr == nullptr) return; std::lock_guard _(mgr->m_dumb_mutex); const auto buffered_frames = std::min(static_cast(mgr->m_dumb.size() / 2), frameCount); auto *pOutputCast = static_cast(pOutput); for (ma_uint32 i = 0; i < buffered_frames * 2; i++) { pOutputCast[i] = mgr->m_dumb.front(); mgr->m_dumb.pop(); } } AudioManager::AudioManager() { m_ok = true; m_device_config = ma_device_config_init(ma_device_type_playback); m_device_config.playback.format = ma_format_s16; m_device_config.playback.channels = 2; m_device_config.sampleRate = 48000; m_device_config.dataCallback = data_callback; m_device_config.pUserData = this; if (ma_device_init(nullptr, &m_device_config, &m_device) != MA_SUCCESS) { puts("open playabck fail"); m_ok = false; return; } if (ma_device_start(&m_device) != MA_SUCCESS) { puts("failed to start playback"); ma_device_uninit(&m_device); m_ok = false; return; } int err; m_opus_decoder = opus_decoder_create(48000, 2, &err); m_active = true; // m_thread = std::thread(&AudioManager::testthread, this); } AudioManager::~AudioManager() { m_active = false; ma_device_uninit(&m_device); } void AudioManager::FeedMeOpus(const std::vector &data) { size_t payload_size = 0; const auto *opus_encoded = StripRTPExtensionHeader(data.data(), static_cast(data.size()), payload_size); static std::array pcm; int decoded = opus_decode(m_opus_decoder, opus_encoded, static_cast(payload_size), pcm.data(), 120 * 48, 0); if (decoded <= 0) { printf("failed decode: %d\n", decoded); } else { m_dumb_mutex.lock(); for (size_t i = 0; i < decoded * 2; i++) { m_dumb.push(pcm[i]); } m_dumb_mutex.unlock(); } } void AudioManager::testthread() { } bool AudioManager::OK() const { return m_ok; }