From 0fa33915da6255cf7460758197eaea7e43353543 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Wed, 31 Aug 2022 01:51:02 -0400 Subject: rudimentary voice implementation --- src/audio/manager.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/audio/manager.cpp (limited to 'src/audio/manager.cpp') diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp new file mode 100644 index 0000000..af36327 --- /dev/null +++ b/src/audio/manager.cpp @@ -0,0 +1,92 @@ +#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; +} -- cgit v1.2.3