From 7bc6116e213ae128fc403d8f28862513f00a2276 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 18 Jul 2023 01:47:46 -0400 Subject: add ability to change vad method --- src/windows/voicewindow.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 829a1b8..f09d019 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -134,6 +134,21 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_signal_gain.emit(val / 100.0); }); + m_vad_combo.set_valign(Gtk::ALIGN_END); + m_vad_combo.set_hexpand(true); + m_vad_combo.set_halign(Gtk::ALIGN_FILL); + m_vad_combo.append("gate", "Gate"); + m_vad_combo.append("rnnoise", "RNNoise"); + m_vad_combo.set_active_id("rnnoise"); + m_vad_combo.signal_changed().connect([this]() { + const auto id = m_vad_combo.get_active_id(); + if (id == "gate") { + Abaddon::Get().GetAudio().SetVADMethod(AudioManager::VADMethod::Gate); + } else if (id == "rnnoise") { + Abaddon::Get().GetAudio().SetVADMethod(AudioManager::VADMethod::RNNoise); + } + }); + auto *playback_renderer = Gtk::make_managed(); m_playback_combo.set_valign(Gtk::ALIGN_END); m_playback_combo.set_hexpand(true); @@ -184,6 +199,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_main.add(m_capture_gate); m_main.add(m_capture_gain); m_main.add(m_scroll); + m_main.add(m_vad_combo); m_main.add(m_playback_combo); m_main.add(m_capture_combo); add(m_main); -- cgit v1.2.3 From be2ab2ef3122dd78cbbce835d056ca59f5042cd4 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 18 Jul 2023 02:02:39 -0400 Subject: support mindeps build without rnnoise --- .clang-format | 2 +- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 2 ++ src/audio/manager.cpp | 14 ++++++++++++++ src/audio/manager.hpp | 8 ++++++++ src/windows/voicewindow.cpp | 4 ++++ 6 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/.clang-format b/.clang-format index 074ecf0..6bd8ca0 100644 --- a/.clang-format +++ b/.clang-format @@ -35,7 +35,7 @@ DerivePointerAlignment: 'false' FixNamespaceComments: 'true' IncludeBlocks: Merge IndentCaseLabels: 'true' -IndentPPDirectives: BeforeHash +IndentPPDirectives: None IndentWidth: '4' IndentWrappedFunctionNames: 'false' JavaScriptQuotes: Double diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cfb8b7..0f20cb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: with: cond: ${{ matrix.mindeps == true }} if_true: | - cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }} -DUSE_LIBHANDY=OFF -DENABLE_VOICE=OFF -DENABLE_NOTIFICATION_SOUNDS=OFF -DENABLE_QRCODE_LOGIN=OFF + cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }} -DUSE_LIBHANDY=OFF -DENABLE_VOICE=OFF -DENABLE_NOTIFICATION_SOUNDS=OFF -DENABLE_QRCODE_LOGIN=OFF -DENABLE_RNNOISE=OFF cmake --build build if_false: | cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }} -DCMAKE_CXX_FLAGS="-Wl,--default-image-base-low" diff --git a/CMakeLists.txt b/CMakeLists.txt index ab51f67..37ea1e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,6 +163,8 @@ if (ENABLE_VOICE) target_link_libraries(abaddon ${CMAKE_DL_LIBS}) if (ENABLE_RNNOISE) + target_compile_definitions(abaddon PRIVATE WITH_RNNOISE) + find_package(rnnoise QUIET) if (NOT rnnoise_FOUND) message("rnnoise was not found and will be included as a submodule") diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index 84e1fcf..75d8f95 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -82,7 +82,12 @@ AudioManager::AudioManager() { spdlog::get("audio")->info("Audio backend: {}", ma_get_backend_name(m_context.backend)); Enumerate(); + +#ifdef WITH_RNNOISE SetVADMethod(VADMethod::RNNoise); +#else + SetVADMethod(VADMethod::Gate); +#endif m_playback_config = ma_device_config_init(ma_device_type_playback); m_playback_config.playback.format = ma_format_f32; @@ -144,7 +149,10 @@ AudioManager::~AudioManager() { ma_device_uninit(&m_capture_device); ma_context_uninit(&m_context); RemoveAllSSRCs(); + +#ifdef WITH_RNNOISE RNNoiseUninitialize(); +#endif } void AudioManager::AddSSRC(uint32_t ssrc) { @@ -425,9 +433,11 @@ void AudioManager::OnCapturedPCM(const int16_t *pcm, ma_uint32 frames) { case VADMethod::Gate: if (!CheckVADVoiceGate()) return; break; +#ifdef WITH_RNNOISE case VADMethod::RNNoise: if (!CheckVADRNNoise(pcm)) return; break; +#endif } m_enc_mutex.lock(); @@ -475,6 +485,7 @@ bool AudioManager::CheckVADVoiceGate() { return m_capture_peak_meter / 32768.0 > m_capture_gate; } +#ifdef WITH_RNNOISE bool AudioManager::CheckVADRNNoise(const int16_t *pcm) { static float denoised[480]; static float rnnoise_input[480]; @@ -503,6 +514,7 @@ void AudioManager::RNNoiseUninitialize() { m_rnnoise = nullptr; } } +#endif bool AudioManager::OK() const { return m_ok; @@ -531,11 +543,13 @@ uint32_t AudioManager::GetRTPTimestamp() const noexcept { void AudioManager::SetVADMethod(VADMethod method) { m_vad_method = method; +#ifdef WITH_RNNOISE if (method == VADMethod::RNNoise) { RNNoiseInitialize(); } else { RNNoiseUninitialize(); } +#endif } AudioManager::type_signal_opus_packet AudioManager::signal_opus_packet() { diff --git a/src/audio/manager.hpp b/src/audio/manager.hpp index c3867df..ec62fed 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -14,7 +14,10 @@ #include #include #include + +#ifdef WITH_RNNOISE #include +#endif #include "devices.hpp" // clang-format on @@ -84,10 +87,13 @@ private: bool DecayVolumeMeters(); bool CheckVADVoiceGate(); + +#ifdef WITH_RNNOISE bool CheckVADRNNoise(const int16_t *pcm); void RNNoiseInitialize(); void RNNoiseUninitialize(); +#endif friend void data_callback(ma_device *, void *, const void *, ma_uint32); friend void capture_data_callback(ma_device *, void *, const void *, ma_uint32); @@ -132,7 +138,9 @@ private: AudioDevices m_devices; VADMethod m_vad_method; +#ifdef WITH_RNNOISE DenoiseState *m_rnnoise; +#endif std::atomic m_rtp_timestamp = 0; public: diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index f09d019..f411f80 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -138,8 +138,12 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_vad_combo.set_hexpand(true); m_vad_combo.set_halign(Gtk::ALIGN_FILL); m_vad_combo.append("gate", "Gate"); +#ifdef WITH_RNNOISE m_vad_combo.append("rnnoise", "RNNoise"); m_vad_combo.set_active_id("rnnoise"); +#else + m_vad_combo.set_active_id("gate"); +#endif m_vad_combo.signal_changed().connect([this]() { const auto id = m_vad_combo.get_active_id(); if (id == "gate") { -- cgit v1.2.3 From 60e3f733241a5524610450adee897c6aca02da42 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 23 Jul 2023 01:01:45 -0400 Subject: make vad method a setting and tie it to combobox --- src/abaddon.cpp | 9 ++++++--- src/audio/manager.cpp | 24 ++++++++++++++++++------ src/audio/manager.hpp | 1 + src/settings.cpp | 4 +++- src/settings.hpp | 7 +++++++ src/windows/voicewindow.cpp | 15 ++++++++------- 6 files changed, 43 insertions(+), 17 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/abaddon.cpp b/src/abaddon.cpp index 2be54ba..fdc4023 100644 --- a/src/abaddon.cpp +++ b/src/abaddon.cpp @@ -23,11 +23,11 @@ #include "remoteauth/remoteauthdialog.hpp" #ifdef WITH_LIBHANDY - #include +#include #endif #ifdef _WIN32 - #pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "crypt32.lib") #endif Abaddon::Abaddon() @@ -67,7 +67,7 @@ Abaddon::Abaddon() if (!accessible) m_channels_requested.erase(id); }); - if (GetSettings().Prefetch) + if (GetSettings().Prefetch) { m_discord.signal_message_create().connect([this](const Message &message) { if (message.Author.HasAvatar()) m_img_mgr.Prefetch(message.Author.GetAvatarURL()); @@ -76,6 +76,9 @@ Abaddon::Abaddon() m_img_mgr.Prefetch(attachment.ProxyURL); } }); + } + + m_audio.SetVADMethod(GetSettings().VAD); } Abaddon &Abaddon::Get() { diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index 48df603..bdb7922 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -83,12 +83,6 @@ AudioManager::AudioManager() { Enumerate(); -#ifdef WITH_RNNOISE - SetVADMethod(VADMethod::RNNoise); -#else - SetVADMethod(VADMethod::Gate); -#endif - m_playback_config = ma_device_config_init(ma_device_type_playback); m_playback_config.playback.format = ma_format_f32; m_playback_config.playback.channels = 2; @@ -540,7 +534,25 @@ uint32_t AudioManager::GetRTPTimestamp() const noexcept { return m_rtp_timestamp; } +void AudioManager::SetVADMethod(const std::string &method) { + spdlog::get("audio")->debug("Setting VAD method to {}", method); + if (method == "gate") { + SetVADMethod(VADMethod::Gate); + } else if (method == "rnnoise") { +#ifdef WITH_RNNOISE + SetVADMethod(VADMethod::RNNoise); +#else + SetVADMethod(VADMethod::Gate); + spdlog::get("audio")->error("Tried to set RNNoise VAD method with support disabled"); +#endif + } else { + SetVADMethod(VADMethod::Gate); + spdlog::get("audio")->error("Tried to set unknown VAD method {}", method); + } +} + void AudioManager::SetVADMethod(VADMethod method) { + spdlog::get("audio")->debug("Setting VAD method to enum {}", static_cast(method)); m_vad_method = method; #ifdef WITH_RNNOISE diff --git a/src/audio/manager.hpp b/src/audio/manager.hpp index ec62fed..2e7d087 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -75,6 +75,7 @@ public: RNNoise, }; + void SetVADMethod(const std::string &method); void SetVADMethod(VADMethod method); private: diff --git a/src/settings.cpp b/src/settings.cpp index 0b868da..601205a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -4,7 +4,7 @@ #include #ifdef WITH_KEYCHAIN - #include +#include #endif const std::string KeychainPackage = "com.github.uowuo.abaddon"; @@ -70,6 +70,7 @@ void SettingsManager::ReadSettings() { SMSTR("style", "unreadcolor", UnreadIndicatorColor); SMBOOL("notifications", "enabled", NotificationsEnabled); SMBOOL("notifications", "playsound", NotificationsPlaySound); + SMSTR("voice", "vad", VAD); SMBOOL("windows", "hideconsole", HideConsole); #ifdef WITH_KEYCHAIN @@ -154,6 +155,7 @@ void SettingsManager::Close() { SMSTR("style", "unreadcolor", UnreadIndicatorColor); SMBOOL("notifications", "enabled", NotificationsEnabled); SMBOOL("notifications", "playsound", NotificationsPlaySound); + SMSTR("voice", "vad", VAD); SMBOOL("windows", "hideconsole", HideConsole); #ifdef WITH_KEYCHAIN diff --git a/src/settings.hpp b/src/settings.hpp index 40cb1d3..0d2e68b 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -53,6 +53,13 @@ public: #endif bool NotificationsPlaySound { true }; + // [voice] +#ifdef WITH_RNNOISE + std::string VAD { "rnnoise" }; +#else + std::string VAD { "gate" }; +#endif + // [windows] bool HideConsole { false }; }; diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index f411f80..01e7b9b 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -140,17 +140,18 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_vad_combo.append("gate", "Gate"); #ifdef WITH_RNNOISE m_vad_combo.append("rnnoise", "RNNoise"); - m_vad_combo.set_active_id("rnnoise"); +#endif + if (!m_vad_combo.set_active_id(Abaddon::Get().GetSettings().VAD)) { +#ifdef WITH_RNNOISE + m_vad_combo.set_active_id("rnnoise"); #else - m_vad_combo.set_active_id("gate"); + m_vad_combo.set_active_id("gate"); #endif + } m_vad_combo.signal_changed().connect([this]() { const auto id = m_vad_combo.get_active_id(); - if (id == "gate") { - Abaddon::Get().GetAudio().SetVADMethod(AudioManager::VADMethod::Gate); - } else if (id == "rnnoise") { - Abaddon::Get().GetAudio().SetVADMethod(AudioManager::VADMethod::RNNoise); - } + Abaddon::Get().GetAudio().SetVADMethod(id); + Abaddon::Get().GetSettings().VAD = id; }); auto *playback_renderer = Gtk::make_managed(); -- cgit v1.2.3 From 07fc439eb78c9ba7bb3acc448ea7e471e15f7e4f Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 23 Jul 2023 01:41:30 -0400 Subject: add tooltip to vad combobox --- src/windows/voicewindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 01e7b9b..b828650 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -137,6 +137,10 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_vad_combo.set_valign(Gtk::ALIGN_END); m_vad_combo.set_hexpand(true); m_vad_combo.set_halign(Gtk::ALIGN_FILL); + m_vad_combo.set_tooltip_text( + "Voice Activation Detection method\n" + "Gate - Simple volume threshold. Slider changes threshold\n" + "RNNoise - Heavier on CPU. Slider changes probability threshold"); m_vad_combo.append("gate", "Gate"); #ifdef WITH_RNNOISE m_vad_combo.append("rnnoise", "RNNoise"); -- cgit v1.2.3 From dc92fef708b668cab31b4a39f425a126e620c2cb Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 23 Jul 2023 01:44:36 -0400 Subject: slight refactor, show rnnoise vad prob in meter when selected --- src/audio/manager.cpp | 12 ++++++++++-- src/audio/manager.hpp | 3 +++ src/windows/voicewindow.cpp | 45 ++++++++++++++++++++++++++++++++------------- src/windows/voicewindow.hpp | 8 ++++++-- 4 files changed, 51 insertions(+), 17 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index bdb7922..f9250c1 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -487,8 +487,8 @@ bool AudioManager::CheckVADRNNoise(const int16_t *pcm) { for (size_t i = 0; i < 480; i++) { rnnoise_input[i] = static_cast(pcm[i * 2]); } - float vad_prob = rnnoise_process_frame(m_rnnoise, denoised, rnnoise_input); - return vad_prob > m_prob_threshold; + m_vad_prob = rnnoise_process_frame(m_rnnoise, denoised, rnnoise_input); + return m_vad_prob > m_prob_threshold; } void AudioManager::RNNoiseInitialize() { @@ -564,6 +564,14 @@ void AudioManager::SetVADMethod(VADMethod method) { #endif } +AudioManager::VADMethod AudioManager::GetVADMethod() const { + return m_vad_method; +} + +float AudioManager::GetCurrentVADProbability() const { + return m_vad_prob; +} + 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 2e7d087..a39532b 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -77,6 +77,8 @@ public: void SetVADMethod(const std::string &method); void SetVADMethod(VADMethod method); + VADMethod GetVADMethod() const; + float GetCurrentVADProbability() const; private: void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames); @@ -129,6 +131,7 @@ private: std::atomic m_capture_gate = 0.0; std::atomic m_capture_gain = 1.0; std::atomic m_prob_threshold = 0.5; + std::atomic m_vad_prob = 0.0; std::unordered_set m_muted_ssrcs; std::unordered_map m_volume_ssrc; diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index b828650..3d67d8d 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -115,15 +115,23 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_scroll.set_hexpand(true); m_scroll.set_vexpand(true); - m_capture_volume.SetShowTick(true); - - m_capture_gate.set_range(0.0, 100.0); - m_capture_gate.set_value_pos(Gtk::POS_LEFT); - m_capture_gate.set_value(audio.GetCaptureGate() * 100.0); - m_capture_gate.signal_value_changed().connect([this]() { - const double val = m_capture_gate.get_value() * 0.01; - m_signal_gate.emit(val); - m_capture_volume.SetTick(val); + m_vad_value.SetShowTick(true); + + m_vad_param.set_range(0.0, 100.0); + m_vad_param.set_value_pos(Gtk::POS_LEFT); + m_vad_param.set_value(audio.GetCaptureGate() * 100.0); + m_vad_param.signal_value_changed().connect([this]() { + const double val = m_vad_param.get_value() * 0.01; + switch (Abaddon::Get().GetAudio().GetVADMethod()) { + case AudioManager::VADMethod::Gate: + m_signal_gate.emit(val); + m_vad_value.SetTick(val); + break; +#ifdef WITH_RNNOISE + case AudioManager::VADMethod::RNNoise: + break; +#endif + }; }); m_capture_gain.set_range(0.0, 200.0); @@ -204,8 +212,8 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_controls.add(m_deafen); m_main.add(m_menu_bar); m_main.add(m_controls); - m_main.add(m_capture_volume); - m_main.add(m_capture_gate); + m_main.add(m_vad_value); + m_main.add(m_vad_param); m_main.add(m_capture_gain); m_main.add(m_scroll); m_main.add(m_vad_combo); @@ -249,11 +257,22 @@ void VoiceWindow::OnDeafenChanged() { } bool VoiceWindow::UpdateVoiceMeters() { - m_capture_volume.SetVolume(Abaddon::Get().GetAudio().GetCaptureVolumeLevel()); + auto &audio = Abaddon::Get().GetAudio(); + switch (audio.GetVADMethod()) { + case AudioManager::VADMethod::Gate: + m_vad_value.SetVolume(audio.GetCaptureVolumeLevel()); + break; +#ifdef WITH_RNNOISE + case AudioManager::VADMethod::RNNoise: + m_vad_value.SetVolume(audio.GetCurrentVADProbability()); + break; +#endif + } + for (auto [id, row] : m_rows) { const auto ssrc = Abaddon::Get().GetDiscordClient().GetSSRCOfUser(id); if (ssrc.has_value()) { - row->SetVolumeMeter(Abaddon::Get().GetAudio().GetSSRCVolumeLevel(*ssrc)); + row->SetVolumeMeter(audio.GetSSRCVolumeLevel(*ssrc)); } } return true; diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp index 927d9fb..d0f6c2d 100644 --- a/src/windows/voicewindow.hpp +++ b/src/windows/voicewindow.hpp @@ -43,8 +43,12 @@ private: Gtk::ScrolledWindow m_scroll; Gtk::ListBox m_user_list; - VolumeMeter m_capture_volume; - Gtk::Scale m_capture_gate; + // Shows volume for gate VAD method + // Shows probability for RNNoise VAD method + VolumeMeter m_vad_value; + // Volume threshold for gate VAD method + // VAD probability threshold for RNNoise VAD method + Gtk::Scale m_vad_param; Gtk::Scale m_capture_gain; Gtk::ComboBoxText m_vad_combo; -- cgit v1.2.3 From 18172a88901c866a52dd3d0fd6ee3409b12061f7 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 23 Jul 2023 02:08:26 -0400 Subject: update vad param value on combobox change --- src/audio/manager.cpp | 4 ++++ src/audio/manager.hpp | 2 ++ src/windows/voicewindow.cpp | 21 +++++++++++++++++++-- src/windows/voicewindow.hpp | 2 ++ 4 files changed, 27 insertions(+), 2 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index f9250c1..53eff54 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -572,6 +572,10 @@ float AudioManager::GetCurrentVADProbability() const { return m_vad_prob; } +double AudioManager::GetRNNProbThreshold() const { + return m_prob_threshold; +} + 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 a39532b..dac9738 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -78,7 +78,9 @@ public: void SetVADMethod(const std::string &method); void SetVADMethod(VADMethod method); VADMethod GetVADMethod() const; + float GetCurrentVADProbability() const; + double GetRNNProbThreshold() const; private: void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames); diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 3d67d8d..eb8802b 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -119,7 +119,6 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_vad_param.set_range(0.0, 100.0); m_vad_param.set_value_pos(Gtk::POS_LEFT); - m_vad_param.set_value(audio.GetCaptureGate() * 100.0); m_vad_param.signal_value_changed().connect([this]() { const double val = m_vad_param.get_value() * 0.01; switch (Abaddon::Get().GetAudio().GetVADMethod()) { @@ -133,6 +132,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) #endif }; }); + UpdateVADParamValue(); m_capture_gain.set_range(0.0, 200.0); m_capture_gain.set_value_pos(Gtk::POS_LEFT); @@ -161,9 +161,12 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) #endif } m_vad_combo.signal_changed().connect([this]() { + auto &audio = Abaddon::Get().GetAudio(); const auto id = m_vad_combo.get_active_id(); - Abaddon::Get().GetAudio().SetVADMethod(id); + + audio.SetVADMethod(id); Abaddon::Get().GetSettings().VAD = id; + UpdateVADParamValue(); }); auto *playback_renderer = Gtk::make_managed(); @@ -278,6 +281,20 @@ bool VoiceWindow::UpdateVoiceMeters() { return true; } +void VoiceWindow::UpdateVADParamValue() { + auto &audio = Abaddon::Get().GetAudio(); + switch (audio.GetVADMethod()) { + case AudioManager::VADMethod::Gate: + m_vad_param.set_value(audio.GetCaptureGate() * 100.0); + break; +#ifdef WITH_RNNOISE + case AudioManager::VADMethod::RNNoise: + m_vad_param.set_value(audio.GetRNNProbThreshold() * 100.0); + break; +#endif + } +} + void VoiceWindow::OnUserConnect(Snowflake user_id, Snowflake to_channel_id) { if (m_channel_id == to_channel_id) { if (auto it = m_rows.find(user_id); it == m_rows.end()) { diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp index d0f6c2d..f4f3549 100644 --- a/src/windows/voicewindow.hpp +++ b/src/windows/voicewindow.hpp @@ -34,6 +34,8 @@ private: bool UpdateVoiceMeters(); + void UpdateVADParamValue(); + Gtk::Box m_main; Gtk::Box m_controls; -- cgit v1.2.3 From f696ecb5c38d792f236a2439d67197462aa82510 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 23 Jul 2023 02:27:53 -0400 Subject: get rid of signals for setting gate and gain --- src/abaddon.cpp | 8 -------- src/windows/voicewindow.cpp | 19 ++++++------------- src/windows/voicewindow.hpp | 6 ------ 3 files changed, 6 insertions(+), 27 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/abaddon.cpp b/src/abaddon.cpp index fdc4023..0f670d6 100644 --- a/src/abaddon.cpp +++ b/src/abaddon.cpp @@ -478,14 +478,6 @@ void Abaddon::ShowVoiceWindow() { m_audio.SetPlayback(!is_deaf); }); - wnd->signal_gate().connect([this](double gate) { - m_audio.SetCaptureGate(gate); - }); - - wnd->signal_gain().connect([this](double gain) { - m_audio.SetCaptureGain(gain); - }); - wnd->signal_mute_user_cs().connect([this](Snowflake id, bool is_mute) { if (const auto ssrc = m_discord.GetSSRCOfUser(id); ssrc.has_value()) { m_audio.SetMuteSSRC(*ssrc, is_mute); diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index eb8802b..4ab9864 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -120,10 +120,11 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_vad_param.set_range(0.0, 100.0); m_vad_param.set_value_pos(Gtk::POS_LEFT); m_vad_param.signal_value_changed().connect([this]() { + auto &audio = Abaddon::Get().GetAudio(); const double val = m_vad_param.get_value() * 0.01; - switch (Abaddon::Get().GetAudio().GetVADMethod()) { + switch (audio.GetVADMethod()) { case AudioManager::VADMethod::Gate: - m_signal_gate.emit(val); + audio.SetCaptureGate(val); m_vad_value.SetTick(val); break; #ifdef WITH_RNNOISE @@ -138,8 +139,8 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_capture_gain.set_value_pos(Gtk::POS_LEFT); m_capture_gain.set_value(audio.GetCaptureGain() * 100.0); m_capture_gain.signal_value_changed().connect([this]() { - const double val = m_capture_gain.get_value(); - m_signal_gain.emit(val / 100.0); + const double val = m_capture_gain.get_value() / 100.0; + Abaddon::Get().GetAudio().SetCaptureGain(val); }); m_vad_combo.set_valign(Gtk::ALIGN_END); @@ -204,7 +205,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) auto *window = new VoiceSettingsWindow; const auto cb = [this](double gain) { m_capture_gain.set_value(gain * 100.0); - m_signal_gain.emit(gain); + Abaddon::Get().GetAudio().SetCaptureGain(gain); }; window->signal_gain().connect(sigc::track_obj(cb, *this)); window->show(); @@ -320,14 +321,6 @@ VoiceWindow::type_signal_deafen VoiceWindow::signal_deafen() { return m_signal_deafen; } -VoiceWindow::type_signal_gate VoiceWindow::signal_gate() { - return m_signal_gate; -} - -VoiceWindow::type_signal_gate VoiceWindow::signal_gain() { - return m_signal_gain; -} - VoiceWindow::type_signal_mute_user_cs VoiceWindow::signal_mute_user_cs() { return m_signal_mute_user_cs; } diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp index f4f3549..7116f06 100644 --- a/src/windows/voicewindow.hpp +++ b/src/windows/voicewindow.hpp @@ -69,23 +69,17 @@ private: public: using type_signal_mute = sigc::signal; using type_signal_deafen = sigc::signal; - using type_signal_gate = sigc::signal; - using type_signal_gain = sigc::signal; using type_signal_mute_user_cs = sigc::signal; using type_signal_user_volume_changed = sigc::signal; type_signal_mute signal_mute(); type_signal_deafen signal_deafen(); - type_signal_gate signal_gate(); - type_signal_gain signal_gain(); type_signal_mute_user_cs signal_mute_user_cs(); type_signal_user_volume_changed signal_user_volume_changed(); private: type_signal_mute m_signal_mute; type_signal_deafen m_signal_deafen; - type_signal_gate m_signal_gate; - type_signal_gain m_signal_gain; type_signal_mute_user_cs m_signal_mute_user_cs; type_signal_user_volume_changed m_signal_user_volume_changed; }; -- cgit v1.2.3 From d208c64be1e19d85882ccafc74a8cd4a8e648e84 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Wed, 2 Aug 2023 02:34:23 -0400 Subject: tie slider to rnnoise probability threshold --- src/audio/manager.cpp | 4 ++++ src/audio/manager.hpp | 1 + src/windows/voicewindow.cpp | 2 ++ 3 files changed, 7 insertions(+) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index 4f3555b..e47b220 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -579,6 +579,10 @@ double AudioManager::GetRNNProbThreshold() const { return m_prob_threshold; } +void AudioManager::SetRNNProbThreshold(double value) { + m_prob_threshold = value; +} + 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 6b67719..d37a281 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -81,6 +81,7 @@ public: float GetCurrentVADProbability() const; double GetRNNProbThreshold() const; + void SetRNNProbThreshold(double value); private: void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames); diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 4ab9864..d9e3336 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -129,6 +129,8 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) break; #ifdef WITH_RNNOISE case AudioManager::VADMethod::RNNoise: + audio.SetRNNProbThreshold(val); + m_vad_value.SetTick(val); break; #endif }; -- cgit v1.2.3 From 3dd192eed2f706df7581b6655dc4b1843d4df4d8 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sat, 19 Aug 2023 21:21:39 -0400 Subject: add noise suppression --- src/audio/manager.cpp | 60 ++++++++++++++++++++++++++++++++++++--------- src/audio/manager.hpp | 9 +++++-- src/windows/voicewindow.cpp | 11 +++++++-- src/windows/voicewindow.hpp | 2 ++ 4 files changed, 67 insertions(+), 15 deletions(-) (limited to 'src/windows/voicewindow.cpp') diff --git a/src/audio/manager.cpp b/src/audio/manager.cpp index e47b220..dc3e7e9 100644 --- a/src/audio/manager.cpp +++ b/src/audio/manager.cpp @@ -423,19 +423,36 @@ void AudioManager::OnCapturedPCM(const int16_t *pcm, ma_uint32 frames) { UpdateCaptureVolume(new_pcm.data(), frames); + static std::array denoised_L; + static std::array denoised_R; + switch (m_vad_method) { case VADMethod::Gate: if (!CheckVADVoiceGate()) return; break; #ifdef WITH_RNNOISE case VADMethod::RNNoise: - if (!CheckVADRNNoise(pcm)) return; + if (!CheckVADRNNoise(new_pcm.data(), denoised_L.data(), denoised_R.data())) return; break; #endif } m_enc_mutex.lock(); - int payload_len = opus_encode(m_encoder, new_pcm.data(), 480, static_cast(m_opus_buffer), 1275); + int payload_len = -1; + + if (m_enable_noise_suppression) { + static std::array denoised_interleaved; + for (size_t i = 0; i < 480; i++) { + denoised_interleaved[i * 2] = static_cast(denoised_L[i]); + } + for (size_t i = 0; i < 480; i++) { + denoised_interleaved[i * 2 + 1] = static_cast(denoised_R[i]); + } + payload_len = opus_encode(m_encoder, denoised_interleaved.data(), 480, static_cast(m_opus_buffer), 1275); + } else { + payload_len = opus_encode(m_encoder, new_pcm.data(), 480, static_cast(m_opus_buffer), 1275); + } + m_enc_mutex.unlock(); if (payload_len < 0) { spdlog::get("audio")->error("encoding error: {}", payload_len); @@ -480,15 +497,23 @@ bool AudioManager::CheckVADVoiceGate() { } #ifdef WITH_RNNOISE -bool AudioManager::CheckVADRNNoise(const int16_t *pcm) { - static float denoised[480]; +bool AudioManager::CheckVADRNNoise(const int16_t *pcm, float *denoised_left, float *denoised_right) { + // use left channel for vad, only denoise right if noise suppression enabled + std::unique_lock _(m_rnn_mutex); + static float rnnoise_input[480]; - // take left channel for (size_t i = 0; i < 480; i++) { rnnoise_input[i] = static_cast(pcm[i * 2]); } - std::unique_lock _(m_rnn_mutex); - m_vad_prob = rnnoise_process_frame(m_rnnoise, denoised, rnnoise_input); + m_vad_prob = rnnoise_process_frame(m_rnnoise[0], denoised_left, rnnoise_input); + + if (m_enable_noise_suppression) { + for (size_t i = 0; i < 480; i++) { + rnnoise_input[i] = static_cast(pcm[i * 2 + 1]); + } + m_vad_prob = rnnoise_process_frame(m_rnnoise[1], denoised_right, rnnoise_input); + } + return m_vad_prob > m_prob_threshold; } @@ -496,7 +521,8 @@ void AudioManager::RNNoiseInitialize() { spdlog::get("audio")->debug("Initializing RNNoise"); RNNoiseUninitialize(); std::unique_lock _(m_rnn_mutex); - m_rnnoise = rnnoise_create(nullptr); + m_rnnoise[0] = rnnoise_create(nullptr); + m_rnnoise[1] = rnnoise_create(nullptr); const auto expected = rnnoise_get_frame_size(); if (expected != 480) { spdlog::get("audio")->warn("RNNoise expects a frame count other than 480"); @@ -504,11 +530,13 @@ void AudioManager::RNNoiseInitialize() { } void AudioManager::RNNoiseUninitialize() { - if (m_rnnoise != nullptr) { + if (m_rnnoise[0] != nullptr) { spdlog::get("audio")->debug("Uninitializing RNNoise"); std::unique_lock _(m_rnn_mutex); - rnnoise_destroy(m_rnnoise); - m_rnnoise = nullptr; + rnnoise_destroy(m_rnnoise[0]); + rnnoise_destroy(m_rnnoise[1]); + m_rnnoise[0] = nullptr; + m_rnnoise[1] = nullptr; } } #endif @@ -571,6 +599,7 @@ AudioManager::VADMethod AudioManager::GetVADMethod() const { return m_vad_method; } +#ifdef WITH_RNNOISE float AudioManager::GetCurrentVADProbability() const { return m_vad_prob; } @@ -583,6 +612,15 @@ void AudioManager::SetRNNProbThreshold(double value) { m_prob_threshold = value; } +void AudioManager::SetSuppressNoise(bool value) { + m_enable_noise_suppression = value; +} + +bool AudioManager::GetSuppressNoise() const { + return m_enable_noise_suppression; +} +#endif + 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 d37a281..80a2542 100644 --- a/src/audio/manager.hpp +++ b/src/audio/manager.hpp @@ -79,9 +79,13 @@ public: void SetVADMethod(VADMethod method); VADMethod GetVADMethod() const; +#ifdef WITH_RNNOISE float GetCurrentVADProbability() const; double GetRNNProbThreshold() const; void SetRNNProbThreshold(double value); + void SetSuppressNoise(bool value); + bool GetSuppressNoise() const; +#endif private: void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames); @@ -95,7 +99,7 @@ private: bool CheckVADVoiceGate(); #ifdef WITH_RNNOISE - bool CheckVADRNNoise(const int16_t *pcm); + bool CheckVADRNNoise(const int16_t *pcm, float *denoised_left, float *denoised_right); void RNNoiseInitialize(); void RNNoiseUninitialize(); @@ -139,6 +143,7 @@ private: std::atomic m_capture_gain = 1.0; std::atomic m_prob_threshold = 0.5; std::atomic m_vad_prob = 0.0; + std::atomic m_enable_noise_suppression = false; std::unordered_set m_muted_ssrcs; std::unordered_map m_volume_ssrc; @@ -150,7 +155,7 @@ private: VADMethod m_vad_method; #ifdef WITH_RNNOISE - DenoiseState *m_rnnoise; + DenoiseState *m_rnnoise[2]; #endif std::atomic m_rtp_timestamp = 0; diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index d9e3336..73a09c2 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -88,6 +88,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) , m_controls(Gtk::ORIENTATION_HORIZONTAL) , m_mute("Mute") , m_deafen("Deafen") + , m_noise_suppression("Suppress Noise") , m_channel_id(channel_id) , m_menu_view("View") , m_menu_view_settings("More _Settings", true) { @@ -172,12 +173,17 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) UpdateVADParamValue(); }); + m_noise_suppression.set_active(audio.GetSuppressNoise()); + m_noise_suppression.signal_toggled().connect([this]() { + Abaddon::Get().GetAudio().SetSuppressNoise(m_noise_suppression.get_active()); + }); + auto *playback_renderer = Gtk::make_managed(); m_playback_combo.set_valign(Gtk::ALIGN_END); m_playback_combo.set_hexpand(true); m_playback_combo.set_halign(Gtk::ALIGN_FILL); - m_playback_combo.set_model(Abaddon::Get().GetAudio().GetDevices().GetPlaybackDeviceModel()); - if (const auto iter = Abaddon::Get().GetAudio().GetDevices().GetActivePlaybackDevice()) { + m_playback_combo.set_model(audio.GetDevices().GetPlaybackDeviceModel()); + if (const auto iter = audio.GetDevices().GetActivePlaybackDevice()) { m_playback_combo.set_active(iter); } m_playback_combo.pack_start(*playback_renderer); @@ -216,6 +222,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_scroll.add(m_user_list); m_controls.add(m_mute); m_controls.add(m_deafen); + m_controls.add(m_noise_suppression); m_main.add(m_menu_bar); m_main.add(m_controls); m_main.add(m_vad_value); diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp index 7116f06..6db2563 100644 --- a/src/windows/voicewindow.hpp +++ b/src/windows/voicewindow.hpp @@ -53,6 +53,8 @@ private: Gtk::Scale m_vad_param; Gtk::Scale m_capture_gain; + Gtk::CheckButton m_noise_suppression; + Gtk::ComboBoxText m_vad_combo; Gtk::ComboBox m_playback_combo; Gtk::ComboBox m_capture_combo; -- cgit v1.2.3