From d20cdac5e4f412a3e65395ddbfdf8a28a6158991 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 28 Dec 2020 17:06:30 +0100 Subject: [PATCH] add duration and 'below' condition type options to audio tab (#85) --- data/locale/en-US.ini | 4 +- data/locale/zh-CN.ini | 2 +- src/headers/switch-audio.hpp | 13 ++++++ src/switch-audio.cpp | 83 +++++++++++++++++++++++++++++++++--- 4 files changed, 93 insertions(+), 9 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index bd32921f..80e470e3 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -175,7 +175,9 @@ AdvSceneSwitcher.sceneSequenceTab.entry="When {{startScenes}} is active switch t ; Audio Tab AdvSceneSwitcher.audioTab.title="Audio" -AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is above {{volumeWidget}} switch to {{scenes}} using {{transitions}}" +AdvSceneSwitcher.audioTab.condition.above="above" +AdvSceneSwitcher.audioTab.condition.below="below" +AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} switch to {{scenes}} using {{transitions}}" ; Hotkey AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index 4d1f3550..bb6f4546 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -175,7 +175,7 @@ AdvSceneSwitcher.sceneSequenceTab.entry="当场景 {{startScenes}} 被激活 {{d ; Audio Tab AdvSceneSwitcher.audioTab.title="音频" -AdvSceneSwitcher.audioTab.entry="当{{audioSources}} 的音量高于 {{volumeWidget}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}}" +AdvSceneSwitcher.audioTab.entry="当{{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}}" ; Hotkey AdvSceneSwitcher.hotkey.startSwitcherHotkey="启动高级场景切换器" diff --git a/src/headers/switch-audio.hpp b/src/headers/switch-audio.hpp index 408717e9..e920787b 100644 --- a/src/headers/switch-audio.hpp +++ b/src/headers/switch-audio.hpp @@ -7,9 +7,17 @@ constexpr auto audio_func = 8; constexpr auto default_priority_8 = audio_func; +typedef enum { + ABOVE, + BELOW, +} audioCondition; + struct AudioSwitch : virtual SceneSwitcherEntry { OBSWeakSource audioSource = nullptr; int volumeThreshold = 0; + audioCondition condition = ABOVE; + double duration = 0; + unsigned int matchCount = 0; float peak = -1; obs_volmeter_t *volmeter = nullptr; @@ -25,6 +33,7 @@ struct AudioSwitch : virtual SceneSwitcherEntry { AudioSwitch(){}; AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_, OBSWeakSource audioSource_, int volumeThreshold_, + audioCondition condition_, double duration_, bool usePreviousScene_); AudioSwitch(const AudioSwitch &other); AudioSwitch(AudioSwitch &&other); @@ -49,10 +58,14 @@ public: private slots: void SourceChanged(const QString &text); void VolumeThresholdChanged(int vol); + void ConditionChanged(int cond); + void DurationChanged(double dur); private: QComboBox *audioSources; + QComboBox *condition; QSpinBox *audioVolumeThreshold; + QDoubleSpinBox *duration; VolControl *volMeter; AudioSwitch *switchData; diff --git a/src/switch-audio.cpp b/src/switch-audio.cpp index f8a6e3d5..4a1a8810 100644 --- a/src/switch-audio.cpp +++ b/src/switch-audio.cpp @@ -86,10 +86,26 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene, obs_source_release(as); // peak will have a value from -60 db to 0 db - bool volumeThresholdreached = ((double)s.peak + 60) * 1.7 > - s.volumeThreshold; + bool volumeThresholdreached = false; - if (volumeThresholdreached && audioActive) { + if (s.condition == ABOVE) + volumeThresholdreached = ((double)s.peak + 60) * 1.7 > + s.volumeThreshold; + else + volumeThresholdreached = ((double)s.peak + 60) * 1.7 < + s.volumeThreshold; + + if (volumeThresholdreached) { + s.matchCount++; + } else { + s.matchCount = 0; + } + + bool durationReached = + (s.matchCount * (unsigned int)interval) / 1000.0 >= + s.duration; + + if (durationReached && audioActive) { scene = (s.usePreviousScene) ? previousScene : s.scene; transition = s.transition; match = true; @@ -130,6 +146,8 @@ void SwitcherData::saveAudioSwitches(obs_data_t *obj) audioSourceName); obs_data_set_int(array_obj, "volume", s.volumeThreshold); + obs_data_set_int(array_obj, "condition", s.condition); + obs_data_set_double(array_obj, "duration", s.duration); obs_data_array_push_back(audioArray, array_obj); } obs_source_release(sceneSource); @@ -158,12 +176,15 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj) const char *audioSource = obs_data_get_string(array_obj, "audioSource"); int vol = obs_data_get_int(array_obj, "volume"); + audioCondition condition = (audioCondition)obs_data_get_int( + array_obj, "condition"); + double duration = obs_data_get_double(array_obj, "duration"); switcher->audioSwitches.emplace_back( GetWeakSourceByName(scene), GetWeakTransitionByName(transition), - GetWeakSourceByName(audioSource), vol, - (strcmp(scene, previous_scene_name) == 0)); + GetWeakSourceByName(audioSource), vol, condition, + duration, (strcmp(scene, previous_scene_name) == 0)); obs_data_release(array_obj); } @@ -229,10 +250,13 @@ bool AudioSwitch::valid() AudioSwitch::AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_, OBSWeakSource audioSource_, int volumeThreshold_, + audioCondition condition_, double duration_, bool usePreviousScene_) : SceneSwitcherEntry(scene_, transition_, usePreviousScene_), audioSource(audioSource_), - volumeThreshold(volumeThreshold_) + volumeThreshold(volumeThreshold_), + condition(condition_), + duration(duration_) { volmeter = obs_volmeter_create(OBS_FADER_LOG); obs_volmeter_add_callback(volmeter, setVolumeLevel, this); @@ -249,7 +273,9 @@ AudioSwitch::AudioSwitch(const AudioSwitch &other) : SceneSwitcherEntry(other.scene, other.transition, other.usePreviousScene), audioSource(other.audioSource), - volumeThreshold(other.volumeThreshold) + volumeThreshold(other.volumeThreshold), + condition(other.condition), + duration(other.duration) { volmeter = obs_volmeter_create(OBS_FADER_LOG); obs_volmeter_add_callback(volmeter, setVolumeLevel, this); @@ -267,6 +293,8 @@ AudioSwitch::AudioSwitch(AudioSwitch &&other) other.usePreviousScene), audioSource(other.audioSource), volumeThreshold(other.volumeThreshold), + condition(other.condition), + duration(other.duration), volmeter(other.volmeter) { other.volmeter = nullptr; @@ -307,16 +335,28 @@ void swap(AudioSwitch &first, AudioSwitch &second) std::swap(first.usePreviousScene, second.usePreviousScene); std::swap(first.audioSource, second.audioSource); std::swap(first.volumeThreshold, second.volumeThreshold); + std::swap(first.condition, second.condition); + std::swap(first.duration, second.duration); std::swap(first.peak, second.peak); std::swap(first.volmeter, second.volmeter); first.resetVolmeter(); second.resetVolmeter(); } +void populateConditionSelection(QComboBox *list) +{ + list->addItem( + obs_module_text("AdvSceneSwitcher.audioTab.condition.above")); + list->addItem( + obs_module_text("AdvSceneSwitcher.audioTab.condition.below")); +} + AudioSwitchWidget::AudioSwitchWidget(AudioSwitch *s) : SwitchWidget(s) { audioSources = new QComboBox(); + condition = new QComboBox(); audioVolumeThreshold = new QSpinBox(); + duration = new QDoubleSpinBox(); obs_source_t *soruce = nullptr; if (s) @@ -328,28 +368,41 @@ AudioSwitchWidget::AudioSwitchWidget(AudioSwitch *s) : SwitchWidget(s) audioVolumeThreshold->setMaximum(100); audioVolumeThreshold->setMinimum(0); + duration->setMinimum(0.0); + duration->setMaximum(99.000000); + duration->setSuffix("s"); + QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)), audioVolumeThreshold, SLOT(setValue(int))); QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)), volMeter->GetSlider(), SLOT(setValue(int))); QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)), this, SLOT(VolumeThresholdChanged(int))); + QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this, + SLOT(ConditionChanged(int))); + QWidget::connect(duration, SIGNAL(valueChanged(double)), this, + SLOT(DurationChanged(double))); QWidget::connect(audioSources, SIGNAL(currentTextChanged(const QString &)), this, SLOT(SourceChanged(const QString &))); AdvSceneSwitcher::populateAudioSelection(audioSources); + populateConditionSelection(condition); if (s) { audioSources->setCurrentText( GetWeakSourceName(s->audioSource).c_str()); audioVolumeThreshold->setValue(s->volumeThreshold); + condition->setCurrentIndex(s->condition); + duration->setValue(s->duration); } QHBoxLayout *switchLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { {"{{audioSources}}", audioSources}, {"{{volumeWidget}}", audioVolumeThreshold}, + {"{{condition}}", condition}, + {"{{duration}}", duration}, {"{{scenes}}", scenes}, {"{{transitions}}", transitions}}; placeWidgets(obs_module_text("AdvSceneSwitcher.audioTab.entry"), @@ -424,3 +477,19 @@ void AudioSwitchWidget::VolumeThresholdChanged(int vol) std::lock_guard lock(switcher->m); switchData->volumeThreshold = vol; } + +void AudioSwitchWidget::ConditionChanged(int cond) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->condition = (audioCondition)cond; +} + +void AudioSwitchWidget::DurationChanged(double dur) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->duration = dur; +}