Procházet zdrojové kódy

Add proper settings for SoundEngine auto-restart

kiwec před 4 měsíci
rodič
revize
73bb4ec63f

+ 1 - 0
src/App/Osu/Changelog.cpp

@@ -29,6 +29,7 @@ Changelog::Changelog() : ScreenBackable() {
     CHANGELOG latest;
     latest.title =
         UString::format("%.2f (%s, %s)", convar->getConVarByName("osu_version")->getFloat(), __DATE__, __TIME__);
+    latest.changes.push_back("- Added SoundEngine auto-restart settings");
     latest.changes.push_back("- Disabled FPoSu noclip by default");
     latest.changes.push_back("- Fixed auto mod staying on after Ctrl+clicking a map");
     latest.changes.push_back("- Fixed downloads sometimes failing on Windows");

+ 13 - 21
src/App/Osu/MainMenu.cpp

@@ -1,10 +1,3 @@
-//================ Copyright (c) 2015, PG, All rights reserved. =================//
-//
-// Purpose:		main menu
-//
-// $NoKeywords: $osumain
-//===============================================================================//
-
 #include "MainMenu.h"
 
 #include "AnimationHandler.h"
@@ -130,8 +123,6 @@ void MainMenuPauseButton::draw(Graphics *g) {
     if(m_bActive && m_bEnabled) drawHoverRect(g, 6);
 }
 
-ConVar osu_toggle_preview_music("osu_toggle_preview_music");
-
 ConVar osu_draw_menu_background("osu_draw_menu_background", false, FCVAR_DEFAULT);
 ConVar osu_main_menu_startup_anim_duration("osu_main_menu_startup_anim_duration", 0.25f, FCVAR_DEFAULT);
 ConVar osu_main_menu_alpha("osu_main_menu_alpha", 0.8f, FCVAR_DEFAULT);
@@ -166,8 +157,6 @@ MainMenu::MainMenu() : OsuScreen() {
         m_osu_songbrowser_background_fade_in_duration_ref =
             convar->getConVarByName("osu_songbrowser_background_fade_in_duration");
 
-    osu_toggle_preview_music.setCallback(fastdelegate::MakeDelegate(this, &MainMenu::onPausePressed));
-
     // engine settings
     engine->getMouse()->addListener(this);
 
@@ -1004,17 +993,20 @@ void MainMenu::mouse_update(bool *propagate_clicks) {
 
     // Update pause button and shuffle songs
     m_pauseButton->setPaused(true);
-    auto music = osu->getSelectedBeatmap()->getMusic();
-    if(music == NULL) {
-        selectRandomBeatmap();
-    } else {
-        if(music->isFinished()) {
-            selectRandomBeatmap();
-        } else if(music->isPlaying()) {
-            m_pauseButton->setPaused(false);
 
-            // NOTE: We set this every frame, because music loading isn't instant
-            music->setLoop(false);
+    if(engine->getSound()->isReady()) {
+        auto music = osu->getSelectedBeatmap()->getMusic();
+        if(music == NULL) {
+            selectRandomBeatmap();
+        } else {
+            if(music->isFinished()) {
+                selectRandomBeatmap();
+            } else if(music->isPlaying()) {
+                m_pauseButton->setPaused(false);
+
+                // NOTE: We set this every frame, because music loading isn't instant
+                music->setLoop(false);
+            }
         }
     }
 }

+ 8 - 0
src/App/Osu/OptionsMenu.cpp

@@ -752,6 +752,13 @@ OptionsMenu::OptionsMenu() : ScreenBackable() {
         for(auto i = asio_idx; i < asio_end_idx; i++) {
             m_elements[i].render_condition = RenderCondition::ASIO_ENABLED;
         }
+
+        // Jank
+        addCheckbox("Restart SoundEngine before every song",
+            "Useful if music or sounds start lagging/glitching after a while.\n"
+            "You probably also want to set a start delay, to make sure SoundEngine had time to reinitialize fully.",
+            convar->getConVarByName("restart_sound_engine_before_playing"));
+        addSlider("Song start delay:", 0.0f, 5.0f, convar->getConVarByName("snd_ready_delay"))->setKeyDelta(0.5f);
     }
 
     addSubSection("Volume");
@@ -3572,6 +3579,7 @@ void OptionsMenu::save() {
 
     removeConCommands.push_back(convar->getConVarByName("monitor"));
     removeConCommands.push_back(convar->getConVarByName("windowed"));
+    removeConCommands.push_back(convar->getConVarByName("snd_output_device"));
     removeConCommands.push_back(m_osu_skin_ref);
 
     if(m_fullscreenCheckbox != NULL) {

+ 0 - 2
src/App/Osu/Osu.cpp

@@ -489,8 +489,6 @@ Osu::Osu() {
     }
 
     m_mainMenu->setVisible(true);
-    m_mainMenu->selectRandomBeatmap();
-
     m_updateHandler->checkForUpdates();
 
     // memory/performance optimization; if osu_mod_mafham is not enabled, reduce the two rendertarget sizes to 64x64,

+ 23 - 19
src/Engine/SoundEngine.cpp

@@ -25,6 +25,7 @@ void _volume(UString oldValue, UString newValue) {
 
 ConVar _volume_("volume", 1.0f, FCVAR_DEFAULT | FCVAR_PRIVATE, _volume);
 
+ConVar snd_ready_delay("snd_ready_delay", 0.0f, FCVAR_DEFAULT | FCVAR_PRIVATE, "after a sound engine restart, wait this many seconds before marking it as ready");
 ConVar snd_output_device("snd_output_device", "Default", FCVAR_DEFAULT | FCVAR_PRIVATE);
 ConVar snd_restart("snd_restart");
 
@@ -459,7 +460,7 @@ bool SoundEngine::init_bass_mixer(OUTPUT_DEVICE device) {
     if(!BASS_Init(0, freq, bass_flags | BASS_DEVICE_SOFTWARE, NULL, NULL)) {
         auto code = BASS_ErrorGetCode();
         if(code != BASS_ERROR_ALREADY) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_Init(0) failed.\n");
             display_bass_error();
             return false;
@@ -468,7 +469,7 @@ bool SoundEngine::init_bass_mixer(OUTPUT_DEVICE device) {
 
     if(device.driver == OutputDriver::BASS) {
         if(!BASS_Init(device.id, freq, bass_flags, NULL, NULL)) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_Init(%d) errored out.\n", device.id);
             display_bass_error();
             return false;
@@ -481,7 +482,7 @@ bool SoundEngine::init_bass_mixer(OUTPUT_DEVICE device) {
     if(device.driver != OutputDriver::BASS) mixer_flags |= BASS_STREAM_DECODE;
     g_bassOutputMixer = BASS_Mixer_StreamCreate(freq, 2, mixer_flags);
     if(g_bassOutputMixer == 0) {
-        m_bReady = false;
+        ready_since = -1.0;
         debugLog("BASS_Mixer_StreamCreate() failed.\n");
         display_bass_error();
         return false;
@@ -499,7 +500,7 @@ bool SoundEngine::initializeOutputDevice(OUTPUT_DEVICE device) {
     shutdown();
 
     if(device.driver == OutputDriver::NONE || (device.driver == OutputDriver::BASS && device.id == 0)) {
-        m_bReady = true;
+        ready_since = -1.0;
         m_currentOutputDevice = device;
         snd_output_device.setValue(m_currentOutputDevice.name);
         debugLog("SoundEngine: Output Device = \"%s\"\n", m_currentOutputDevice.name.toUtf8());
@@ -546,7 +547,7 @@ bool SoundEngine::initializeOutputDevice(OUTPUT_DEVICE device) {
 #ifdef _WIN32
     if(device.driver == OutputDriver::BASS_ASIO) {
         if(!BASS_ASIO_Init(device.id, 0)) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_ASIO_Init() failed.\n");
             display_bass_error();
             return false;
@@ -575,14 +576,14 @@ bool SoundEngine::initializeOutputDevice(OUTPUT_DEVICE device) {
         }
 
         if(!BASS_ASIO_ChannelEnableBASS(false, 0, g_bassOutputMixer, true)) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_ASIO_ChannelEnableBASS() failed.\n");
             display_bass_error();
             return false;
         }
 
         if(!BASS_ASIO_Start(bufsize, 0)) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_ASIO_Start() failed.\n");
             display_bass_error();
             return false;
@@ -621,14 +622,14 @@ bool SoundEngine::initializeOutputDevice(OUTPUT_DEVICE device) {
 
         if(!BASS_WASAPI_Init(device.id, 0, 0, flags, bufferSize, updatePeriod, WASAPIPROC_BASS, (void *)g_bassOutputMixer)) {
             const int errorCode = BASS_ErrorGetCode();
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_WASAPI_Init() failed.\n");
             display_bass_error();
             return false;
         }
 
         if(!BASS_WASAPI_Start()) {
-            m_bReady = false;
+            ready_since = -1.0;
             debugLog("BASS_WASAPI_Start() failed.\n");
             display_bass_error();
             return false;
@@ -638,7 +639,7 @@ bool SoundEngine::initializeOutputDevice(OUTPUT_DEVICE device) {
     }
 #endif
 
-    m_bReady = true;
+    ready_since = engine->getTime();
     m_currentOutputDevice = device;
     snd_output_device.setValue(m_currentOutputDevice.name);
     debugLog("SoundEngine: Output Device = \"%s\"\n", m_currentOutputDevice.name.toUtf8());
@@ -667,7 +668,7 @@ void SoundEngine::shutdown() {
     }
 #endif
 
-    m_bReady = false;
+    ready_since = -1.0;
     g_bassOutputMixer = 0;
     BASS_Free();  // free "No sound" device
 }
@@ -675,7 +676,7 @@ void SoundEngine::shutdown() {
 void SoundEngine::update() {}
 
 bool SoundEngine::play(Sound *snd, float pan, float pitch) {
-    if(!m_bReady || snd == NULL || !snd->isReady()) return false;
+    if(!isReady() || snd == NULL || !snd->isReady()) return false;
 
     if(!snd->isOverlayable() && snd->isPlaying()) {
         return false;
@@ -735,7 +736,7 @@ bool SoundEngine::play(Sound *snd, float pan, float pitch) {
 }
 
 void SoundEngine::pause(Sound *snd) {
-    if(!m_bReady || snd == NULL || !snd->isReady()) return;
+    if(!isReady() || snd == NULL || !snd->isReady()) return;
     if(!snd->isStream()) {
         engine->showMessageError("Programmer Error", "Called pause on a sample!");
         return;
@@ -759,12 +760,17 @@ void SoundEngine::pause(Sound *snd) {
 }
 
 void SoundEngine::stop(Sound *snd) {
-    if(!m_bReady || snd == NULL || !snd->isReady()) return;
+    if(!isReady() || snd == NULL || !snd->isReady()) return;
 
     // This will stop all samples, then re-init to be ready for a play()
     snd->reload();
 }
 
+bool SoundEngine::isReady() {
+    if(ready_since == -1.0) return false;
+    return ready_since + (double)convar->getConVarByName("snd_ready_delay")->getFloat() < engine->getTime();
+}
+
 bool SoundEngine::hasExclusiveOutput() {
     return isASIO() || (isWASAPI() && convar->getConVarByName("win_snd_wasapi_exclusive")->getBool());
 }
@@ -780,7 +786,7 @@ void SoundEngine::setOutputDevice(OUTPUT_DEVICE device) {
     // TODO: This is blocking main thread, can freeze for a long time on some sound cards
     auto previous = m_currentOutputDevice;
     if(!initializeOutputDevice(device)) {
-        if(device.id == previous.id && device.driver == previous.driver) {
+        if((device.id == previous.id && device.driver == previous.driver) || !initializeOutputDevice(previous)) {
             // We failed to reinitialize the device, don't start an infinite loop, just give up
             m_currentOutputDevice = {
                 .id = 0,
@@ -789,8 +795,6 @@ void SoundEngine::setOutputDevice(OUTPUT_DEVICE device) {
                 .name = "No sound",
                 .driver = OutputDriver::NONE,
             };
-        } else {
-            initializeOutputDevice(previous);
         }
     }
 
@@ -816,7 +820,7 @@ void SoundEngine::setOutputDevice(OUTPUT_DEVICE device) {
 }
 
 void SoundEngine::setVolume(float volume) {
-    if(!m_bReady) return;
+    if(!isReady()) return;
 
     m_fVolume = clamp<float>(volume, 0.0f, 1.0f);
     if(m_currentOutputDevice.driver == OutputDriver::BASS_ASIO) {
@@ -839,7 +843,7 @@ void SoundEngine::setVolume(float volume) {
 void SoundEngine::onFreqChanged(UString oldValue, UString newValue) {
     (void)oldValue;
     (void)newValue;
-    if(!m_bReady) return;
+    if(!isReady()) return;
     restart();
 }
 

+ 3 - 13
src/Engine/SoundEngine.h

@@ -1,12 +1,4 @@
-//================ Copyright (c) 2014, PG, All rights reserved. =================//
-//
-// Purpose:		handles sounds, bass library wrapper atm
-//
-// $NoKeywords: $snd
-//===============================================================================//
-
-#ifndef SOUNDENGINE_H
-#define SOUNDENGINE_H
+#pragma once
 
 #include "cbase.h"
 // ^ needs to be before Sound.h on windows
@@ -40,7 +32,7 @@ class SoundEngine {
     void pause(Sound *snd);
     void stop(Sound *snd);
 
-    bool isReady() { return m_bReady; }
+    bool isReady();
     bool isASIO() { return m_currentOutputDevice.driver == OutputDriver::BASS_ASIO; }
     bool isWASAPI() { return m_currentOutputDevice.driver == OutputDriver::BASS_WASAPI; }
     bool hasExclusiveOutput();
@@ -67,12 +59,10 @@ class SoundEngine {
 
     OUTPUT_DEVICE m_currentOutputDevice;
 
-    bool m_bReady = false;
+    double ready_since = -1.0;
     float m_fVolume = 1.0f;
 };
 
 DWORD ASIO_clamp(BASS_ASIO_INFO info, DWORD buflen);
 
 void _RESTART_SOUND_ENGINE_ON_CHANGE(UString oldValue, UString newValue);
-
-#endif