From 38423341c27061f2aa23355edf5e3b632fb4723b Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 29 Dec 2023 20:49:53 +0100 Subject: [PATCH] Add option to use db value as input for audio action --- data/locale/de-DE.ini | 1 - data/locale/en-US.ini | 2 +- data/locale/es-ES.ini | 1 - data/locale/ru-RU.ini | 1 - data/locale/tr-TR.ini | 1 - data/locale/zh-CN.ini | 1 - src/macro-core/macro-action-audio.cpp | 86 +++++++++++++++++++++++---- src/macro-core/macro-action-audio.hpp | 9 ++- 8 files changed, 85 insertions(+), 17 deletions(-) diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index 50b51c60..c959b7c6 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -414,7 +414,6 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Blende {{fadeTypes}} {{dura AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Blende {{fadeTypes}} {{rate}}pro Sekunde." AdvSceneSwitcher.action.audio.fade.wait="Warten, bis die Blende abgeschlossen ist." AdvSceneSwitcher.action.audio.fade.abort="Abbruch einer bereits aktiven Blende." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Aufnahme" AdvSceneSwitcher.action.recording.type.stop="Aufnahme stoppen" AdvSceneSwitcher.action.recording.type.start="Aufnahme starten" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index e0fd6ffa..478ffced 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -586,7 +586,7 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade{{fadeTypes}}{{duration AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade{{fadeTypes}}{{rate}}per second." AdvSceneSwitcher.action.audio.fade.wait="Wait for fade to complete." AdvSceneSwitcher.action.audio.fade.abort="Abort already active fade." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{volumeDB}}{{percentDBToggle}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Recording" AdvSceneSwitcher.action.recording.type.stop="Stop recording" AdvSceneSwitcher.action.recording.type.start="Start recording" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index aa0f85a6..928a82be 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -339,7 +339,6 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade {{fadeTypes}} {{durati AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade {{fadeTypes}} {{rate}}por segundo." AdvSceneSwitcher.action.audio.fade.wait="Espere a que se complete el desvanecimiento". AdvSceneSwitcher.action.audio.fade.abort="Cancelar atenuación ya activa." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Grabando" AdvSceneSwitcher.action.recording.type.stop="Detener grabación" AdvSceneSwitcher.action.recording.type.start="Iniciar grabación" diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini index dcb6dd55..645ea4a0 100644 --- a/data/locale/ru-RU.ini +++ b/data/locale/ru-RU.ini @@ -127,7 +127,6 @@ AdvSceneSwitcher.action.audio.type.mute="Замьютить" AdvSceneSwitcher.action.audio.type.unmute="Размьютить" AdvSceneSwitcher.action.audio.type.sourceVolume="Установить громкость источника" AdvSceneSwitcher.action.audio.type.masterVolume="Установить главную громкость" -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Запись" AdvSceneSwitcher.action.recording.type.stop="Остановить запись" AdvSceneSwitcher.action.recording.type.start="Начать запись" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 5f84f6a2..83f6f133 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -270,7 +270,6 @@ AdvSceneSwitcher.action.audio.type.mute="Sessiz" AdvSceneSwitcher.action.audio.type.unmute="Ses açmak" AdvSceneSwitcher.action.audio.type.sourceVolume="Kaynak ses seviyesini ayarla" AdvSceneSwitcher.action.audio.type.masterVolume="Ana ses seviyesini ayarla" -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Kayıt" AdvSceneSwitcher.action.recording.type.stop="Kayıt Durdur" AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index ee5dbfe5..c04a5aa5 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -469,7 +469,6 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{dura AdvSceneSwitcher.action.audio.fade.rate="{{fade}}淡出 {{fadeTypes}} {{rate}}每秒." AdvSceneSwitcher.action.audio.fade.wait="等待淡入淡出完成." AdvSceneSwitcher.action.audio.fade.abort="中止已处于活动状态的淡入淡出." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="录制" AdvSceneSwitcher.action.recording.type.stop="停止录制" AdvSceneSwitcher.action.recording.type.start="开始录制" diff --git a/src/macro-core/macro-action-audio.cpp b/src/macro-core/macro-action-audio.cpp index 7f33065e..95a251e0 100644 --- a/src/macro-core/macro-action-audio.cpp +++ b/src/macro-core/macro-action-audio.cpp @@ -2,6 +2,8 @@ #include "macro.hpp" #include "utility.hpp" +#include + namespace advss { constexpr int64_t nsPerMs = 1000000; @@ -49,6 +51,11 @@ static std::unordered_map audioFades; constexpr auto fadeInterval = std::chrono::milliseconds(100); constexpr float minFade = 0.000001f; +static float decibelToPercent(float db) +{ + return pow(10, (db / 20)); +} + // For backwards compatibility #if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(29, 0, 0) static float get_master_volume() @@ -103,6 +110,11 @@ std::atomic_int *MacroActionAudio::GetFadeIdPtr() return &masterAudioFade.id; } +float MacroActionAudio::GetVolume() +{ + return _useDb ? decibelToPercent(_volumeDB) : (float)_volume / 100.0f; +} + void MacroActionAudio::SetVolume(float vol) { if (_action == Action::SOURCE_VOLUME) { @@ -114,7 +126,7 @@ void MacroActionAudio::SetVolume(float vol) } } -float MacroActionAudio::GetVolume() +float MacroActionAudio::GetCurrentVolume() { float curVol; if (_action == Action::SOURCE_VOLUME) { @@ -132,8 +144,8 @@ float MacroActionAudio::GetVolume() void MacroActionAudio::FadeVolume() { - float vol = (float)_volume / 100.0f; - float curVol = GetVolume(); + float vol = GetVolume(); + float curVol = GetCurrentVolume(); bool volIncrease = curVol <= vol; float volDiff = (volIncrease) ? vol - curVol : curVol - vol; int nrSteps = 0; @@ -211,7 +223,7 @@ bool MacroActionAudio::PerformAction() if (_fade) { StartFade(); } else { - SetVolume((float)_volume / 100.0f); + SetVolume(GetVolume()); } break; case Action::SYNC_OFFSET: @@ -234,10 +246,11 @@ void MacroActionAudio::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { + auto &[_, action] = *it; vblog(LOG_INFO, - "performed action \"%s\" for source \"%s\" with volume %d with fade %d %f", - it->second.c_str(), _audioSource.ToString(true).c_str(), - _volume.GetValue(), _fade, _duration.Seconds()); + "performed action \"%s\" for source \"%s\" with volume %f with fade %d %f", + action.c_str(), _audioSource.ToString(true).c_str(), + GetVolume(), _fade, _duration.Seconds()); } else { blog(LOG_WARNING, "ignored unknown audio action %d", static_cast(_action)); @@ -259,7 +272,9 @@ bool MacroActionAudio::Save(obs_data_t *obj) const obs_data_set_int(obj, "fadeType", static_cast(_fadeType)); obs_data_set_bool(obj, "wait", _wait); obs_data_set_bool(obj, "abortActiveFade", _abortActiveFade); - obs_data_set_int(obj, "version", 1); + obs_data_set_bool(obj, "useDb", _useDb); + _volumeDB.Save(obj, "volumeDB"); + obs_data_set_int(obj, "version", 2); return true; } @@ -299,6 +314,15 @@ bool MacroActionAudio::Load(obs_data_t *obj) } else { _abortActiveFade = false; } + + if (obs_data_get_int(obj, "version") != 2) { + _useDb = false; + _volumeDB = 0.0; + } else { + _useDb = obs_data_get_bool(obj, "useDb"); + _volumeDB.Load(obj, "volumeDB"); + } + return true; } @@ -322,7 +346,7 @@ static inline void populateActionSelection(QComboBox *list) static inline void populateFadeTypeSelection(QComboBox *list) { - for (auto entry : fadeTypes) { + for (const auto &entry : fadeTypes) { list->addItem(obs_module_text(entry.second.c_str())); } } @@ -340,6 +364,8 @@ MacroActionAudioEdit::MacroActionAudioEdit( obs_module_text( "AdvSceneSwitcher.action.audio.balance.description"))), _volumePercent(new VariableSpinBox), + _volumeDB(new VariableDoubleSpinBox), + _percentDBToggle(new QPushButton), _fade(new QCheckBox), _duration(new DurationSelection(parent, false)), _rate(new VariableDoubleSpinBox), @@ -358,6 +384,11 @@ MacroActionAudioEdit::MacroActionAudioEdit( _volumePercent->setMaximum(2000); _volumePercent->setSuffix("%"); + _volumeDB->setMinimum(-60); + _volumeDB->setMaximum(0); + _volumeDB->setSuffix("db"); + _volumeDB->specialValueText("-inf"); + _rate->setMinimum(0.01); _rate->setMaximum(999.); _rate->setSuffix("%"); @@ -388,6 +419,12 @@ MacroActionAudioEdit::MacroActionAudioEdit( _volumePercent, SIGNAL(NumberVariableChanged(const NumberVariable &)), this, SLOT(VolumeChanged(const NumberVariable &))); + QWidget::connect( + _volumeDB, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, SLOT(VolumeDBChanged(const NumberVariable &))); + QWidget::connect(_percentDBToggle, SIGNAL(clicked()), this, + SLOT(PercentDBClicked())); QWidget::connect(_fade, SIGNAL(stateChanged(int)), this, SLOT(FadeChanged(int))); QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)), @@ -410,6 +447,8 @@ MacroActionAudioEdit::MacroActionAudioEdit( {"{{monitorTypes}}", _monitorTypes}, {"{{balance}}", _balance}, {"{{volume}}", _volumePercent}, + {"{{volumeDB}}", _volumeDB}, + {"{{percentDBToggle}}", _percentDBToggle}, {"{{fade}}", _fade}, {"{{duration}}", _duration}, {"{{rate}}", _rate}, @@ -448,7 +487,12 @@ static bool hasVolumeControl(MacroActionAudio::Action action) void MacroActionAudioEdit::SetWidgetVisibility() { - _volumePercent->setVisible(hasVolumeControl(_entryData->_action)); + _volumePercent->setVisible(hasVolumeControl(_entryData->_action) && + !_entryData->_useDb); + _volumeDB->setVisible(hasVolumeControl(_entryData->_action) && + _entryData->_useDb); + _percentDBToggle->setText(_entryData->_useDb ? "db" : "%"); + _percentDBToggle->setVisible(hasVolumeControl(_entryData->_action)); _sources->setVisible(_entryData->_action != MacroActionAudio::Action::MASTER_VOLUME); _syncOffset->setVisible(_entryData->_action == @@ -519,6 +563,7 @@ void MacroActionAudioEdit::UpdateEntryData() _monitorTypes->setCurrentIndex(_entryData->_monitorType); _balance->SetDoubleValue(_entryData->_balance); _volumePercent->SetValue(_entryData->_volume); + _volumeDB->SetValue(_entryData->_volumeDB); _fade->setChecked(_entryData->_fade); _duration->SetDuration(_entryData->_duration); _rate->SetValue(_entryData->_rate); @@ -582,6 +627,27 @@ void MacroActionAudioEdit::BalanceChanged(const NumberVariable &value) _entryData->_balance = value; } +void MacroActionAudioEdit::VolumeDBChanged(const NumberVariable &value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_volumeDB = value; +} + +void MacroActionAudioEdit::PercentDBClicked() +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_useDb = !_entryData->_useDb; + SetWidgetVisibility(); +} + void MacroActionAudioEdit::VolumeChanged(const NumberVariable &value) { if (_loading || !_entryData) { diff --git a/src/macro-core/macro-action-audio.hpp b/src/macro-core/macro-action-audio.hpp index a0809ca3..bc1d0e9f 100644 --- a/src/macro-core/macro-action-audio.hpp +++ b/src/macro-core/macro-action-audio.hpp @@ -47,7 +47,9 @@ public: NumberVariable _syncOffset = 0; obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; NumberVariable _balance = 0.5; + bool _useDb = false; NumberVariable _volume = 0; + NumberVariable _volumeDB = 0.0; bool _fade = false; Duration _duration; NumberVariable _rate = 100.; @@ -58,10 +60,11 @@ private: void StartFade(); void FadeVolume(); void SetVolume(float vol); - float GetVolume(); + float GetCurrentVolume(); void SetFadeActive(bool value); bool FadeActive(); std::atomic_int *GetFadeIdPtr(); + float GetVolume(); static bool _registered; static const std::string id; @@ -90,6 +93,8 @@ private slots: void MonitorTypeChanged(int value); void BalanceChanged(const NumberVariable &value); void VolumeChanged(const NumberVariable &value); + void VolumeDBChanged(const NumberVariable &value); + void PercentDBClicked(); void FadeChanged(int value); void DurationChanged(const Duration &seconds); void RateChanged(const NumberVariable &value); @@ -107,6 +112,8 @@ protected: QComboBox *_monitorTypes; SliderSpinBox *_balance; VariableSpinBox *_volumePercent; + VariableDoubleSpinBox *_volumeDB; + QPushButton *_percentDBToggle; QCheckBox *_fade; DurationSelection *_duration; VariableDoubleSpinBox *_rate;