diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2022-10-16 23:12:26 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2022-10-16 23:12:26 -0400 |
commit | 621beb13444eb3ca16a756bfb8fdc6b4f79723f5 (patch) | |
tree | 041586c38fa8d2664a4a063e3a2ef85405f0fde6 /src/audio | |
parent | 17e7478bb4827e094a06faca6c5f2d5f4e5a45cc (diff) | |
download | abaddon-portaudio-621beb13444eb3ca16a756bfb8fdc6b4f79723f5.tar.gz abaddon-portaudio-621beb13444eb3ca16a756bfb8fdc6b4f79723f5.zip |
basic volume meters
Diffstat (limited to 'src/audio')
-rw-r--r-- | src/audio/manager.cpp | 49 | ||||
-rw-r--r-- | src/audio/manager.hpp | 14 |
2 files changed, 62 insertions, 1 deletions
diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index cf6b545..5bcc3bb 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -7,6 +7,7 @@ #include "manager.hpp" #include <array> +#include <glibmm/main.h> #define MINIAUDIO_IMPLEMENTATION #include <miniaudio.h> #include <opus.h> @@ -107,6 +108,8 @@ AudioManager::AudioManager() { char device_name[MA_MAX_DEVICE_NAME_LENGTH + 1]; ma_device_get_name(&m_capture_device, ma_device_type_capture, device_name, sizeof(device_name), nullptr); printf("using %s for capture\n", device_name); + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &AudioManager::DecayVolumeMeters), 40); } AudioManager::~AudioManager() { @@ -158,6 +161,7 @@ void AudioManager::FeedMeOpus(uint32_t ssrc, const std::vector<uint8_t> &data) { int decoded = opus_decode(it->second.second, opus_encoded, static_cast<opus_int32>(payload_size), pcm.data(), 120 * 48, 0); if (decoded <= 0) { } else { + UpdateReceiveVolume(ssrc, pcm.data(), decoded); auto &buf = it->second.first; buf.insert(buf.end(), pcm.begin(), pcm.begin() + decoded * 2); } @@ -191,6 +195,8 @@ void AudioManager::SetVolumeSSRC(uint32_t ssrc, double volume) { void AudioManager::OnCapturedPCM(const int16_t *pcm, ma_uint32 frames) { if (m_opus_buffer == nullptr || !m_should_capture) return; + UpdateCaptureVolume(pcm, frames); + int payload_len = opus_encode(m_encoder, pcm, 480, static_cast<unsigned char *>(m_opus_buffer), 1275); if (payload_len < 0) { printf("encoding error: %d\n", payload_len); @@ -199,10 +205,53 @@ void AudioManager::OnCapturedPCM(const int16_t *pcm, ma_uint32 frames) { } } +void AudioManager::UpdateReceiveVolume(uint32_t ssrc, const int16_t *pcm, int frames) { + std::lock_guard<std::mutex> _(m_vol_mtx); + + auto &meter = m_volumes[ssrc]; + for (int i = 0; i < frames * 2; i += 2) { + const int amp = std::abs(pcm[i]); + meter = std::max(meter, std::abs(amp) / 32768.0); + } +} + +void AudioManager::UpdateCaptureVolume(const int16_t *pcm, ma_uint32 frames) { + for (ma_uint32 i = 0; i < frames * 2; i += 2) { + const int amp = std::abs(pcm[i]); + m_capture_peak_meter = std::max(m_capture_peak_meter.load(std::memory_order_relaxed), amp); + } +} + +bool AudioManager::DecayVolumeMeters() { + m_capture_peak_meter -= 300; + if (m_capture_peak_meter < 0) m_capture_peak_meter = 0; + + std::lock_guard<std::mutex> _(m_vol_mtx); + + for (auto &[ssrc, meter] : m_volumes) { + meter -= 0.01; + if (meter < 0.0) meter = 0.0; + } + + return true; +} + bool AudioManager::OK() const { return m_ok; } +double AudioManager::GetCaptureVolumeLevel() const noexcept { + return m_capture_peak_meter / 32768.0; +} + +double AudioManager::GetSSRCVolumeLevel(uint32_t ssrc) const noexcept { + std::lock_guard<std::mutex> _(m_vol_mtx); + if (const auto it = m_volumes.find(ssrc); it != m_volumes.end()) { + return it->second; + } + return 0.0; +} + AudioManager::type_signal_opus_packet AudioManager::signal_opus_packet() { return m_signal_opus_packet; } diff --git a/src/audio/manager.hpp b/src/audio/manager.hpp index 9d270fa..43d8a1e 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -35,9 +35,18 @@ public: [[nodiscard]] bool OK() const; + [[nodiscard]] double GetCaptureVolumeLevel() const noexcept; + [[nodiscard]] double GetSSRCVolumeLevel(uint32_t ssrc) const noexcept; + private: void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames); + void UpdateReceiveVolume(uint32_t ssrc, const int16_t *pcm, int frames); + void UpdateCaptureVolume(const int16_t *pcm, ma_uint32 frames); + std::atomic<int> m_capture_peak_meter = 0; + + bool DecayVolumeMeters(); + friend void data_callback(ma_device *, void *, const void *, ma_uint32); friend void capture_data_callback(ma_device *, void *, const void *, ma_uint32); @@ -52,7 +61,7 @@ private: ma_device m_capture_device; ma_device_config m_capture_config; - std::mutex m_mutex; + mutable std::mutex m_mutex; std::unordered_map<uint32_t, std::pair<std::deque<int16_t>, OpusDecoder *>> m_sources; OpusEncoder *m_encoder; @@ -65,6 +74,9 @@ private: std::unordered_set<uint32_t> m_muted_ssrcs; std::unordered_map<uint32_t, double> m_volume_ssrc; + mutable std::mutex m_vol_mtx; + std::unordered_map<uint32_t, double> m_volumes; + public: using type_signal_opus_packet = sigc::signal<void(int payload_size)>; type_signal_opus_packet signal_opus_packet(); |