Modernized the audio handling code a bit.

This commit is contained in:
Leon Styhre 2020-12-21 00:23:22 +01:00
parent cfff577549
commit 214a7861f9
6 changed files with 68 additions and 40 deletions

View file

@ -57,7 +57,7 @@ VolumeControl::VolumeControl()
} }
VolumeControl::VolumeControl( VolumeControl::VolumeControl(
const VolumeControl & right): const VolumeControl& right):
originalVolume(0), originalVolume(0),
internalVolume(0) internalVolume(0)
#if defined(__APPLE__) #if defined(__APPLE__)
@ -72,7 +72,7 @@ VolumeControl::VolumeControl(
endpointVolume(nullptr) endpointVolume(nullptr)
#endif #endif
{ {
(void)right; static_cast<void>(right);
sInstance = right.sInstance; sInstance = right.sInstance;
} }
@ -92,7 +92,7 @@ VolumeControl::~VolumeControl()
deinit(); deinit();
} }
std::shared_ptr<VolumeControl> & VolumeControl::getInstance() std::shared_ptr<VolumeControl>& VolumeControl::getInstance()
{ {
// Check if an VolumeControl instance is already created, if not create one. // Check if an VolumeControl instance is already created, if not create one.
static std::shared_ptr<VolumeControl> sharedInstance = sInstance.lock(); static std::shared_ptr<VolumeControl> sharedInstance = sInstance.lock();

View file

@ -444,7 +444,7 @@ void GuiMenu::openSoundSettings()
std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%"); std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
sound_volume_navigation->setValue(static_cast<float>(Settings::getInstance()-> sound_volume_navigation->setValue(static_cast<float>(Settings::getInstance()->
getInt("SoundVolumeNavigation"))); getInt("SoundVolumeNavigation")));
s->addWithLabel("NAVIGATION VOLUME", sound_volume_navigation); s->addWithLabel("NAVIGATION SOUNDS VOLUME", sound_volume_navigation);
s->addSaveFunc([sound_volume_navigation, s] { s->addSaveFunc([sound_volume_navigation, s] {
if (sound_volume_navigation->getValue() != if (sound_volume_navigation->getValue() !=
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeNavigation"))) { static_cast<float>(Settings::getInstance()->getInt("SoundVolumeNavigation"))) {
@ -459,7 +459,7 @@ void GuiMenu::openSoundSettings()
std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%"); std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
sound_volume_videos->setValue(static_cast<float>(Settings::getInstance()-> sound_volume_videos->setValue(static_cast<float>(Settings::getInstance()->
getInt("SoundVolumeVideos"))); getInt("SoundVolumeVideos")));
s->addWithLabel("VIDEO VOLUME", sound_volume_videos); s->addWithLabel("VIDEO PLAYER VOLUME", sound_volume_videos);
s->addSaveFunc([sound_volume_videos, s] { s->addSaveFunc([sound_volume_videos, s] {
if (sound_volume_videos->getValue() != if (sound_volume_videos->getValue() !=
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeVideos"))) { static_cast<float>(Settings::getInstance()->getInt("SoundVolumeVideos"))) {

View file

@ -24,6 +24,7 @@
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "views/ViewController.h" #include "views/ViewController.h"
#include "AudioManager.h"
#include "CollectionSystemManager.h" #include "CollectionSystemManager.h"
#include "EmulationStation.h" #include "EmulationStation.h"
#include "InputManager.h" #include "InputManager.h"
@ -466,6 +467,7 @@ int main(int argc, char* argv[])
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
return 1; return 1;
AudioManager::getInstance();
MameNames::init(); MameNames::init();
if (splashScreen) { if (splashScreen) {

View file

@ -14,9 +14,10 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
std::vector<std::shared_ptr<Sound>> AudioManager::sSoundVector;
SDL_AudioSpec AudioManager::sAudioFormat;
std::shared_ptr<AudioManager> AudioManager::sInstance; std::shared_ptr<AudioManager> AudioManager::sInstance;
std::vector<std::shared_ptr<Sound>> AudioManager::sSoundVector;
SDL_AudioDeviceID AudioManager::sAudioDevice = 0;
SDL_AudioSpec AudioManager::sAudioFormat;
void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len) void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
{ {
@ -37,7 +38,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
restLength = len; restLength = len;
} }
// Mix sample into stream. // 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); restLength, Settings::getInstance()->getInt("SoundVolumeNavigation") * 1.28);
if (sound->getPosition() + restLength < sound->getLength()) { if (sound->getPosition() + restLength < sound->getLength()) {
//sample hasn't ended yet //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. // We have processed all samples. check if some will still be playing.
if (!stillPlaying) { if (!stillPlaying) {
// No. pause audio till a Sound::play() wakes us up. // Nothing is playing, pause the audio until Sound::play() wakes us up.
SDL_PauseAudio(1); SDL_PauseAudioDevice(sAudioDevice, 1);
} }
} }
@ -70,15 +71,17 @@ AudioManager::~AudioManager()
std::shared_ptr<AudioManager>& AudioManager::getInstance() std::shared_ptr<AudioManager>& AudioManager::getInstance()
{ {
// Check if an AudioManager instance is already created, if not create one. // Check if an AudioManager instance is already created, if not create it.
if (sInstance == nullptr && Settings::getInstance()->getBool("NavigationSounds")) { if (sInstance == nullptr)
sInstance = std::shared_ptr<AudioManager>(new AudioManager); sInstance = std::shared_ptr<AudioManager>(new AudioManager);
}
return sInstance; return sInstance;
} }
void AudioManager::init() void AudioManager::init()
{ {
LOG(LogInfo) << "Setting up AudioManager...";
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError(); LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError();
return; return;
@ -90,18 +93,46 @@ void AudioManager::init()
sSoundVector[i]->stop(); sSoundVector[i]->stop();
} }
// Set up format and callback. Play 16-bit stereo audio at 44.1Khz. SDL_AudioSpec sRequestedAudioFormat;
sAudioFormat.freq = 44100;
sAudioFormat.format = AUDIO_S16;
sAudioFormat.channels = 2;
sAudioFormat.samples = 4096;
sAudioFormat.callback = mixAudio;
sAudioFormat.userdata = nullptr;
// Open the audio device and pause. SDL_memset(&sRequestedAudioFormat, 0, sizeof(sRequestedAudioFormat));
if (SDL_OpenAudio(&sAudioFormat, nullptr) < 0) { SDL_memset(&sAudioFormat, 0, sizeof(sAudioFormat));
LOG(LogError) << "AudioManager - Unable to open SDL audio: " <<
SDL_GetError() << std::endl; // 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. // 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>& sound) void AudioManager::registerSound(std::shared_ptr<Sound>& sound)
{ {
getInstance();
sSoundVector.push_back(sound); sSoundVector.push_back(sound);
} }
void AudioManager::unregisterSound(std::shared_ptr<Sound>& sound) void AudioManager::unregisterSound(std::shared_ptr<Sound>& sound)
{ {
getInstance();
for (unsigned int i = 0; i < sSoundVector.size(); i++) { for (unsigned int i = 0; i < sSoundVector.size(); i++) {
if (sSoundVector.at(i) == sound) { if (sSoundVector.at(i) == sound) {
sSoundVector[i]->stop(); sSoundVector[i]->stop();
@ -147,10 +176,8 @@ void AudioManager::unregisterSound(std::shared_ptr<Sound>& sound)
void AudioManager::play() void AudioManager::play()
{ {
getInstance();
// Unpause audio, the mixer will figure out if samples need to be played... // Unpause audio, the mixer will figure out if samples need to be played...
SDL_PauseAudio(0); SDL_PauseAudioDevice(sAudioDevice, 0);
} }
void AudioManager::stop() void AudioManager::stop()
@ -161,5 +188,5 @@ void AudioManager::stop()
sSoundVector[i]->stop(); sSoundVector[i]->stop();
} }
// Pause audio. // Pause audio.
SDL_PauseAudio(1); SDL_PauseAudioDevice(sAudioDevice, 1);
} }

View file

@ -26,6 +26,7 @@ class AudioManager
AudioManager(); AudioManager();
public: public:
static SDL_AudioDeviceID sAudioDevice;
static std::shared_ptr<AudioManager>& getInstance(); static std::shared_ptr<AudioManager>& getInstance();
void init(); void init();

View file

@ -138,14 +138,14 @@ void Sound::init()
} }
else { else {
// Worked. set up member data. // Worked. set up member data.
SDL_LockAudio(); SDL_LockAudioDevice(AudioManager::sAudioDevice);
mSampleData = cvt.buf; mSampleData = cvt.buf;
mSampleLength = cvt.len_cvt; mSampleLength = cvt.len_cvt;
mSamplePos = 0; mSamplePos = 0;
mSampleFormat.channels = 2; mSampleFormat.channels = 2;
mSampleFormat.freq = 44100; mSampleFormat.freq = 44100;
mSampleFormat.format = AUDIO_S16; mSampleFormat.format = AUDIO_S16;
SDL_UnlockAudio(); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
} }
// Free WAV data now. // Free WAV data now.
SDL_FreeWAV(data); SDL_FreeWAV(data);
@ -156,12 +156,12 @@ void Sound::deinit()
playing = false; playing = false;
if (mSampleData != nullptr) { if (mSampleData != nullptr) {
SDL_LockAudio(); SDL_LockAudioDevice(AudioManager::sAudioDevice);
delete[] mSampleData; delete[] mSampleData;
mSampleData = nullptr; mSampleData = nullptr;
mSampleLength = 0; mSampleLength = 0;
mSamplePos = 0; mSamplePos = 0;
SDL_UnlockAudio(); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
} }
} }
@ -173,9 +173,7 @@ void Sound::play()
if (!Settings::getInstance()->getBool("NavigationSounds")) if (!Settings::getInstance()->getBool("NavigationSounds"))
return; return;
AudioManager::getInstance(); SDL_LockAudioDevice(AudioManager::sAudioDevice);
SDL_LockAudio();
if (playing) if (playing)
// Replay from start. rewind the sample to the beginning. // Replay from start. rewind the sample to the beginning.
@ -184,7 +182,7 @@ void Sound::play()
// Flag our sample as playing. // Flag our sample as playing.
playing = true; playing = true;
SDL_UnlockAudio(); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
// Tell the AudioManager to start playing samples. // Tell the AudioManager to start playing samples.
AudioManager::getInstance()->play(); AudioManager::getInstance()->play();
} }
@ -197,10 +195,10 @@ bool Sound::isPlaying() const
void Sound::stop() void Sound::stop()
{ {
// Flag our sample as not playing and rewind its position. // Flag our sample as not playing and rewind its position.
SDL_LockAudio(); SDL_LockAudioDevice(AudioManager::sAudioDevice);
playing = false; playing = false;
mSamplePos = 0; mSamplePos = 0;
SDL_UnlockAudio(); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
} }
const Uint8* Sound::getData() const const Uint8* Sound::getData() const