From 214a7861f928dcc53b4f1853f1fcafc775b80e3e Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Mon, 21 Dec 2020 00:23:22 +0100 Subject: [PATCH] Modernized the audio handling code a bit. --- es-app/src/VolumeControl.cpp | 6 +-- es-app/src/guis/GuiMenu.cpp | 4 +- es-app/src/main.cpp | 2 + es-core/src/AudioManager.cpp | 77 ++++++++++++++++++++++++------------ es-core/src/AudioManager.h | 1 + es-core/src/Sound.cpp | 18 ++++----- 6 files changed, 68 insertions(+), 40 deletions(-) diff --git a/es-app/src/VolumeControl.cpp b/es-app/src/VolumeControl.cpp index a1c4e4bfd..05c70c69c 100644 --- a/es-app/src/VolumeControl.cpp +++ b/es-app/src/VolumeControl.cpp @@ -57,7 +57,7 @@ VolumeControl::VolumeControl() } VolumeControl::VolumeControl( - const VolumeControl & right): + const VolumeControl& right): originalVolume(0), internalVolume(0) #if defined(__APPLE__) @@ -72,7 +72,7 @@ VolumeControl::VolumeControl( endpointVolume(nullptr) #endif { - (void)right; + static_cast(right); sInstance = right.sInstance; } @@ -92,7 +92,7 @@ VolumeControl::~VolumeControl() deinit(); } -std::shared_ptr & VolumeControl::getInstance() +std::shared_ptr& VolumeControl::getInstance() { // Check if an VolumeControl instance is already created, if not create one. static std::shared_ptr sharedInstance = sInstance.lock(); diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index c706b7216..722e1689f 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -444,7 +444,7 @@ void GuiMenu::openSoundSettings() std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); sound_volume_navigation->setValue(static_cast(Settings::getInstance()-> getInt("SoundVolumeNavigation"))); - s->addWithLabel("NAVIGATION VOLUME", sound_volume_navigation); + s->addWithLabel("NAVIGATION SOUNDS VOLUME", sound_volume_navigation); s->addSaveFunc([sound_volume_navigation, s] { if (sound_volume_navigation->getValue() != static_cast(Settings::getInstance()->getInt("SoundVolumeNavigation"))) { @@ -459,7 +459,7 @@ void GuiMenu::openSoundSettings() std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); sound_volume_videos->setValue(static_cast(Settings::getInstance()-> getInt("SoundVolumeVideos"))); - s->addWithLabel("VIDEO VOLUME", sound_volume_videos); + s->addWithLabel("VIDEO PLAYER VOLUME", sound_volume_videos); s->addSaveFunc([sound_volume_videos, s] { if (sound_volume_videos->getValue() != static_cast(Settings::getInstance()->getInt("SoundVolumeVideos"))) { diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 818087993..7cb498d22 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -24,6 +24,7 @@ #include "utils/FileSystemUtil.h" #include "utils/StringUtil.h" #include "views/ViewController.h" +#include "AudioManager.h" #include "CollectionSystemManager.h" #include "EmulationStation.h" #include "InputManager.h" @@ -466,6 +467,7 @@ int main(int argc, char* argv[]) if (event.type == SDL_QUIT) return 1; + AudioManager::getInstance(); MameNames::init(); if (splashScreen) { diff --git a/es-core/src/AudioManager.cpp b/es-core/src/AudioManager.cpp index 59611d98e..31328c6dc 100644 --- a/es-core/src/AudioManager.cpp +++ b/es-core/src/AudioManager.cpp @@ -14,9 +14,10 @@ #include -std::vector> AudioManager::sSoundVector; -SDL_AudioSpec AudioManager::sAudioFormat; std::shared_ptr AudioManager::sInstance; +std::vector> AudioManager::sSoundVector; +SDL_AudioDeviceID AudioManager::sAudioDevice = 0; +SDL_AudioSpec AudioManager::sAudioFormat; void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len) { @@ -37,7 +38,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len) restLength = len; } // Mix sample into stream. - SDL_MixAudio(stream, &(sound->getData()[sound->getPosition()]), + SDL_MixAudioFormat(stream, &(sound->getData()[sound->getPosition()]), AUDIO_S16, restLength, Settings::getInstance()->getInt("SoundVolumeNavigation") * 1.28); if (sound->getPosition() + restLength < sound->getLength()) { //sample hasn't ended yet @@ -53,8 +54,8 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len) // We have processed all samples. check if some will still be playing. if (!stillPlaying) { - // No. pause audio till a Sound::play() wakes us up. - SDL_PauseAudio(1); + // Nothing is playing, pause the audio until Sound::play() wakes us up. + SDL_PauseAudioDevice(sAudioDevice, 1); } } @@ -70,15 +71,17 @@ AudioManager::~AudioManager() std::shared_ptr& AudioManager::getInstance() { - // Check if an AudioManager instance is already created, if not create one. - if (sInstance == nullptr && Settings::getInstance()->getBool("NavigationSounds")) { + // Check if an AudioManager instance is already created, if not create it. + if (sInstance == nullptr) sInstance = std::shared_ptr(new AudioManager); - } + return sInstance; } void AudioManager::init() { + LOG(LogInfo) << "Setting up AudioManager..."; + if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError(); return; @@ -90,18 +93,46 @@ void AudioManager::init() sSoundVector[i]->stop(); } - // Set up format and callback. Play 16-bit stereo audio at 44.1Khz. - sAudioFormat.freq = 44100; - sAudioFormat.format = AUDIO_S16; - sAudioFormat.channels = 2; - sAudioFormat.samples = 4096; - sAudioFormat.callback = mixAudio; - sAudioFormat.userdata = nullptr; + SDL_AudioSpec sRequestedAudioFormat; - // Open the audio device and pause. - if (SDL_OpenAudio(&sAudioFormat, nullptr) < 0) { - LOG(LogError) << "AudioManager - Unable to open SDL audio: " << - SDL_GetError() << std::endl; + SDL_memset(&sRequestedAudioFormat, 0, sizeof(sRequestedAudioFormat)); + SDL_memset(&sAudioFormat, 0, sizeof(sAudioFormat)); + + // Set up format and callback. Play 16-bit stereo audio at 44.1Khz. + sRequestedAudioFormat.freq = 44100; + sRequestedAudioFormat.format = AUDIO_S16; + sRequestedAudioFormat.channels = 2; + sRequestedAudioFormat.samples = 4096; + sRequestedAudioFormat.callback = mixAudio; + sRequestedAudioFormat.userdata = nullptr; + + for (unsigned int i = 0; i < SDL_GetNumAudioDevices(0); i++) { + LOG(LogDebug) << "Detected playback device '" << SDL_GetAudioDeviceName(i, 0) << "'."; + } + + sAudioDevice = SDL_OpenAudioDevice(0, 0, &sRequestedAudioFormat, &sAudioFormat, + SDL_AUDIO_ALLOW_ANY_CHANGE); + + if (sAudioDevice == 0) { + LOG(LogError) << "Unable to open audio device: " << SDL_GetError() << std::endl; + return; + } + + if (sAudioFormat.freq != sRequestedAudioFormat.freq) { + LOG(LogDebug) << "AudioManager::init(): Requested frequency 44100 could not be " + "set, obtained " << std::to_string(sAudioFormat.freq) << "."; + } + if (sAudioFormat.format != sRequestedAudioFormat.format) { + LOG(LogDebug) << "AudioManager::init(): Requested format " << AUDIO_S16 << " could not be " + "set, obtained " << std::to_string(sAudioFormat.format) << "."; + } + if (sAudioFormat.channels != sRequestedAudioFormat.channels) { + LOG(LogDebug) << "AudioManager::init(): Requested channel count 2 could not be " + "set, obtained " << std::to_string(sAudioFormat.channels) << "."; + } + if (sAudioFormat.samples != sRequestedAudioFormat.samples) { + LOG(LogDebug) << "AudioManager::init(): Requested sample buffer size 4096 could not be " + "set, obtained " << std::to_string(sAudioFormat.samples) << "."; } // Just in case someone changed the es_settings.cfg file manually to invalid values. @@ -128,13 +159,11 @@ void AudioManager::deinit() void AudioManager::registerSound(std::shared_ptr& sound) { - getInstance(); sSoundVector.push_back(sound); } void AudioManager::unregisterSound(std::shared_ptr& sound) { - getInstance(); for (unsigned int i = 0; i < sSoundVector.size(); i++) { if (sSoundVector.at(i) == sound) { sSoundVector[i]->stop(); @@ -147,10 +176,8 @@ void AudioManager::unregisterSound(std::shared_ptr& sound) void AudioManager::play() { - getInstance(); - // Unpause audio, the mixer will figure out if samples need to be played... - SDL_PauseAudio(0); + SDL_PauseAudioDevice(sAudioDevice, 0); } void AudioManager::stop() @@ -161,5 +188,5 @@ void AudioManager::stop() sSoundVector[i]->stop(); } // Pause audio. - SDL_PauseAudio(1); + SDL_PauseAudioDevice(sAudioDevice, 1); } diff --git a/es-core/src/AudioManager.h b/es-core/src/AudioManager.h index f792e209d..c25495400 100644 --- a/es-core/src/AudioManager.h +++ b/es-core/src/AudioManager.h @@ -26,6 +26,7 @@ class AudioManager AudioManager(); public: + static SDL_AudioDeviceID sAudioDevice; static std::shared_ptr& getInstance(); void init(); diff --git a/es-core/src/Sound.cpp b/es-core/src/Sound.cpp index 283884326..4793035cb 100644 --- a/es-core/src/Sound.cpp +++ b/es-core/src/Sound.cpp @@ -138,14 +138,14 @@ void Sound::init() } else { // Worked. set up member data. - SDL_LockAudio(); + SDL_LockAudioDevice(AudioManager::sAudioDevice); mSampleData = cvt.buf; mSampleLength = cvt.len_cvt; mSamplePos = 0; mSampleFormat.channels = 2; mSampleFormat.freq = 44100; mSampleFormat.format = AUDIO_S16; - SDL_UnlockAudio(); + SDL_UnlockAudioDevice(AudioManager::sAudioDevice); } // Free WAV data now. SDL_FreeWAV(data); @@ -156,12 +156,12 @@ void Sound::deinit() playing = false; if (mSampleData != nullptr) { - SDL_LockAudio(); + SDL_LockAudioDevice(AudioManager::sAudioDevice); delete[] mSampleData; mSampleData = nullptr; mSampleLength = 0; mSamplePos = 0; - SDL_UnlockAudio(); + SDL_UnlockAudioDevice(AudioManager::sAudioDevice); } } @@ -173,9 +173,7 @@ void Sound::play() if (!Settings::getInstance()->getBool("NavigationSounds")) return; - AudioManager::getInstance(); - - SDL_LockAudio(); + SDL_LockAudioDevice(AudioManager::sAudioDevice); if (playing) // Replay from start. rewind the sample to the beginning. @@ -184,7 +182,7 @@ void Sound::play() // Flag our sample as playing. playing = true; - SDL_UnlockAudio(); + SDL_UnlockAudioDevice(AudioManager::sAudioDevice); // Tell the AudioManager to start playing samples. AudioManager::getInstance()->play(); } @@ -197,10 +195,10 @@ bool Sound::isPlaying() const void Sound::stop() { // Flag our sample as not playing and rewind its position. - SDL_LockAudio(); + SDL_LockAudioDevice(AudioManager::sAudioDevice); playing = false; mSamplePos = 0; - SDL_UnlockAudio(); + SDL_UnlockAudioDevice(AudioManager::sAudioDevice); } const Uint8* Sound::getData() const