Merge pull request #6134 from ligfx/soundstreamlifecycle

SoundStream: change Start/Stop lifecycle to Init/SetRunning/destruct
This commit is contained in:
Markus Wick 2018-01-02 09:58:36 +01:00 committed by GitHub
commit cb168b1843
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 113 additions and 115 deletions

View File

@ -15,9 +15,19 @@ AlsaSound::AlsaSound()
{ {
} }
bool AlsaSound::Start() AlsaSound::~AlsaSound()
{ {
m_thread_status.store(ALSAThreadStatus::RUNNING); m_thread_status.store(ALSAThreadStatus::STOPPING);
// Give the opportunity to the audio thread
// to realize we are stopping the emulation
cv.notify_one();
thread.join();
}
bool AlsaSound::Init()
{
m_thread_status.store(ALSAThreadStatus::PAUSED);
if (!AlsaInit()) if (!AlsaInit())
{ {
m_thread_status.store(ALSAThreadStatus::STOPPED); m_thread_status.store(ALSAThreadStatus::STOPPED);
@ -28,16 +38,6 @@ bool AlsaSound::Start()
return true; return true;
} }
void AlsaSound::Stop()
{
m_thread_status.store(ALSAThreadStatus::STOPPING);
// Give the opportunity to the audio thread
// to realize we are stopping the emulation
cv.notify_one();
thread.join();
}
void AlsaSound::Update() void AlsaSound::Update()
{ {
// don't need to do anything here. // don't need to do anything here.
@ -78,10 +78,11 @@ void AlsaSound::SoundLoop()
m_thread_status.store(ALSAThreadStatus::STOPPED); m_thread_status.store(ALSAThreadStatus::STOPPED);
} }
void AlsaSound::SetRunning(bool running) bool AlsaSound::SetRunning(bool running)
{ {
m_thread_status.store(running ? ALSAThreadStatus::RUNNING : ALSAThreadStatus::PAUSED); m_thread_status.store(running ? ALSAThreadStatus::RUNNING : ALSAThreadStatus::PAUSED);
cv.notify_one(); // Notify thread that status has changed cv.notify_one(); // Notify thread that status has changed
return true;
} }
bool AlsaSound::AlsaInit() bool AlsaSound::AlsaInit()

View File

@ -21,12 +21,12 @@ class AlsaSound final : public SoundStream
#if defined(HAVE_ALSA) && HAVE_ALSA #if defined(HAVE_ALSA) && HAVE_ALSA
public: public:
AlsaSound(); AlsaSound();
~AlsaSound() override;
bool Start() override; bool Init() override;
void SoundLoop() override; void SoundLoop() override;
void Stop() override;
void Update() override; void Update() override;
void SetRunning(bool running) override; bool SetRunning(bool running) override;
static bool isValid() { return true; } static bool isValid() { return true; }
private: private:

View File

@ -21,6 +21,7 @@
std::unique_ptr<SoundStream> g_sound_stream; std::unique_ptr<SoundStream> g_sound_stream;
static bool s_audio_dump_start = false; static bool s_audio_dump_start = false;
static bool s_sound_stream_running = false;
namespace AudioCommon namespace AudioCommon
{ {
@ -50,23 +51,15 @@ void InitSoundStream()
else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid())
g_sound_stream = std::make_unique<OpenSLESStream>(); g_sound_stream = std::make_unique<OpenSLESStream>();
if (!g_sound_stream) if (!g_sound_stream || !g_sound_stream->Init())
{ {
WARN_LOG(AUDIO, "Could not initialize backend %s, using %s instead.", backend.c_str(), WARN_LOG(AUDIO, "Could not initialize backend %s, using %s instead.", backend.c_str(),
BACKEND_NULLSOUND); BACKEND_NULLSOUND);
g_sound_stream = std::make_unique<NullSound>(); g_sound_stream = std::make_unique<NullSound>();
} }
if (!g_sound_stream->Start())
{
ERROR_LOG(AUDIO, "Could not start backend %s, using %s instead", backend.c_str(),
BACKEND_NULLSOUND);
g_sound_stream = std::make_unique<NullSound>();
g_sound_stream->Start();
}
UpdateSoundStream(); UpdateSoundStream();
SetSoundStreamRunning(true);
if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start)
StartAudioDump(); StartAudioDump();
@ -76,15 +69,11 @@ void ShutdownSoundStream()
{ {
INFO_LOG(AUDIO, "Shutting down sound stream"); INFO_LOG(AUDIO, "Shutting down sound stream");
if (g_sound_stream) if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start)
{ StopAudioDump();
g_sound_stream->Stop();
if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) SetSoundStreamRunning(false);
StopAudioDump(); g_sound_stream.reset();
g_sound_stream.reset();
}
INFO_LOG(AUDIO, "Done shutting down sound stream"); INFO_LOG(AUDIO, "Done shutting down sound stream");
} }
@ -161,8 +150,19 @@ void UpdateSoundStream()
void SetSoundStreamRunning(bool running) void SetSoundStreamRunning(bool running)
{ {
if (g_sound_stream) if (!g_sound_stream)
g_sound_stream->SetRunning(running); return;
if (s_sound_stream_running == running)
return;
s_sound_stream_running = running;
if (g_sound_stream->SetRunning(running))
return;
if (running)
ERROR_LOG(AUDIO, "Error starting stream.");
else
ERROR_LOG(AUDIO, "Error stopping stream.");
} }
void SendAIBuffer(const short* samples, unsigned int num_samples) void SendAIBuffer(const short* samples, unsigned int num_samples)
@ -198,6 +198,8 @@ void StartAudioDump()
void StopAudioDump() void StopAudioDump()
{ {
if (!g_sound_stream)
return;
g_sound_stream->GetMixer()->StopLogDTKAudio(); g_sound_stream->GetMixer()->StopLogDTKAudio();
g_sound_stream->GetMixer()->StopLogDSPAudio(); g_sound_stream->GetMixer()->StopLogDSPAudio();
s_audio_dump_start = false; s_audio_dump_start = false;

View File

@ -32,7 +32,7 @@ void CubebStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_sta
{ {
} }
bool CubebStream::Start() bool CubebStream::Init()
{ {
m_ctx = CubebUtils::GetContext(); m_ctx = CubebUtils::GetContext();
if (!m_ctx) if (!m_ctx)
@ -60,28 +60,22 @@ bool CubebStream::Start()
ERROR_LOG(AUDIO, "Error getting minimum latency"); ERROR_LOG(AUDIO, "Error getting minimum latency");
INFO_LOG(AUDIO, "Minimum latency: %i frames", minimum_latency); INFO_LOG(AUDIO, "Minimum latency: %i frames", minimum_latency);
if (cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr, nullptr, return cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr,
&params, std::max(BUFFER_SAMPLES, minimum_latency), DataCallback, nullptr, &params, std::max(BUFFER_SAMPLES, minimum_latency),
StateCallback, this) != CUBEB_OK) DataCallback, StateCallback, this) == CUBEB_OK;
{
ERROR_LOG(AUDIO, "Error initializing cubeb stream");
return false;
}
if (cubeb_stream_start(m_stream) != CUBEB_OK)
{
ERROR_LOG(AUDIO, "Error starting cubeb stream");
return false;
}
return true;
} }
void CubebStream::Stop() bool CubebStream::SetRunning(bool running)
{ {
if (cubeb_stream_stop(m_stream) != CUBEB_OK) if (running)
{ return cubeb_stream_start(m_stream) == CUBEB_OK;
ERROR_LOG(AUDIO, "Error stopping cubeb stream"); else
} return cubeb_stream_stop(m_stream) == CUBEB_OK;
}
CubebStream::~CubebStream()
{
SetRunning(false);
cubeb_stream_destroy(m_stream); cubeb_stream_destroy(m_stream);
m_ctx.reset(); m_ctx.reset();
} }

View File

@ -15,8 +15,9 @@
class CubebStream final : public SoundStream class CubebStream final : public SoundStream
{ {
public: public:
bool Start() override; ~CubebStream() override;
void Stop() override; bool Init() override;
bool SetRunning(bool running) override;
void SetVolume(int) override; void SetVolume(int) override;
private: private:

View File

@ -8,7 +8,12 @@ void NullSound::SoundLoop()
{ {
} }
bool NullSound::Start() bool NullSound::Init()
{
return true;
}
bool NullSound::SetRunning(bool running)
{ {
return true; return true;
} }
@ -20,7 +25,3 @@ void NullSound::SetVolume(int volume)
void NullSound::Update() void NullSound::Update()
{ {
} }
void NullSound::Stop()
{
}

View File

@ -9,10 +9,10 @@
class NullSound final : public SoundStream class NullSound final : public SoundStream
{ {
public: public:
bool Start() override; bool Init() override;
void SoundLoop() override; void SoundLoop() override;
bool SetRunning(bool running) override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
void Stop() override;
void Update() override; void Update() override;
static bool isValid() { return true; } static bool isValid() { return true; }

View File

@ -92,7 +92,7 @@ bool OpenALStream::isValid()
// //
// AyuanX: Spec says OpenAL1.1 is thread safe already // AyuanX: Spec says OpenAL1.1 is thread safe already
// //
bool OpenALStream::Start() bool OpenALStream::Init()
{ {
if (!palcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT")) if (!palcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
{ {
@ -124,7 +124,7 @@ bool OpenALStream::Start()
return true; return true;
} }
void OpenALStream::Stop() OpenALStream::~OpenALStream()
{ {
m_run_thread.Clear(); m_run_thread.Clear();
// kick the thread if it's waiting // kick the thread if it's waiting
@ -161,7 +161,7 @@ void OpenALStream::Update()
m_sound_sync_event.Set(); m_sound_sync_event.Set();
} }
void OpenALStream::SetRunning(bool running) bool OpenALStream::SetRunning(bool running)
{ {
if (running) if (running)
{ {
@ -171,6 +171,7 @@ void OpenALStream::SetRunning(bool running)
{ {
palSourceStop(m_source); palSourceStop(m_source);
} }
return true;
} }
static ALenum CheckALError(const char* desc) static ALenum CheckALError(const char* desc)

View File

@ -55,11 +55,11 @@ class OpenALStream final : public SoundStream
#ifdef _WIN32 #ifdef _WIN32
public: public:
OpenALStream() : m_source(0) {} OpenALStream() : m_source(0) {}
bool Start() override; ~OpenALStream() override;
bool Init() override;
void SoundLoop() override; void SoundLoop() override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
void Stop() override; bool SetRunning(bool running) override;
void SetRunning(bool running) override;
void Update() override; void Update() override;
static bool isValid(); static bool isValid();

View File

@ -49,7 +49,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
_assert_msg_(AUDIO, SL_RESULT_SUCCESS == result, "Couldn't enqueue audio stream."); _assert_msg_(AUDIO, SL_RESULT_SUCCESS == result, "Couldn't enqueue audio stream.");
} }
bool OpenSLESStream::Start() bool OpenSLESStream::Init()
{ {
SLresult result; SLresult result;
// create engine // create engine
@ -110,7 +110,7 @@ bool OpenSLESStream::Start()
return true; return true;
} }
void OpenSLESStream::Stop() OpenSLESStream::~OpenSLESStream()
{ {
if (bqPlayerObject != nullptr) if (bqPlayerObject != nullptr)
{ {

View File

@ -13,8 +13,9 @@ class OpenSLESStream final : public SoundStream
{ {
#ifdef ANDROID #ifdef ANDROID
public: public:
bool Start() override; ~OpenSLESStream() override;
void Stop() override; bool Init() override;
bool SetRunning(bool running) override { return running; }
static bool isValid() { return true; } static bool isValid() { return true; }
private: private:
std::thread thread; std::thread thread;

View File

@ -19,7 +19,7 @@ PulseAudio::PulseAudio() : m_thread(), m_run_thread()
{ {
} }
bool PulseAudio::Start() bool PulseAudio::Init()
{ {
m_stereo = !SConfig::GetInstance().bDPL2Decoder; m_stereo = !SConfig::GetInstance().bDPL2Decoder;
m_channels = m_stereo ? 2 : 5; // will tell PA we use a Stereo or 5.0 channel setup m_channels = m_stereo ? 2 : 5; // will tell PA we use a Stereo or 5.0 channel setup
@ -32,17 +32,12 @@ bool PulseAudio::Start()
return true; return true;
} }
void PulseAudio::Stop() PulseAudio::~PulseAudio()
{ {
m_run_thread.Clear(); m_run_thread.Clear();
m_thread.join(); m_thread.join();
} }
void PulseAudio::Update()
{
// don't need to do anything here.
}
// Called on audio thread. // Called on audio thread.
void PulseAudio::SoundLoop() void PulseAudio::SoundLoop()
{ {

View File

@ -18,11 +18,10 @@ class PulseAudio final : public SoundStream
#if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO
public: public:
PulseAudio(); PulseAudio();
~PulseAudio() override;
bool Start() override; bool Init() override;
void Stop() override; bool SetRunning(bool running) override { return running; }
void Update() override;
static bool isValid() { return true; } static bool isValid() { return true; }
void StateCallback(pa_context* c); void StateCallback(pa_context* c);
void WriteCallback(pa_stream* s, size_t length); void WriteCallback(pa_stream* s, size_t length);

View File

@ -19,10 +19,9 @@ public:
virtual ~SoundStream() {} virtual ~SoundStream() {}
static bool isValid() { return false; } static bool isValid() { return false; }
Mixer* GetMixer() const { return m_mixer.get(); } Mixer* GetMixer() const { return m_mixer.get(); }
virtual bool Start() { return false; } virtual bool Init() { return false; }
virtual void SetVolume(int) {} virtual void SetVolume(int) {}
virtual void SoundLoop() {} virtual void SoundLoop() {}
virtual void Stop() {}
virtual void Update() {} virtual void Update() {}
virtual void SetRunning(bool running) {} virtual bool SetRunning(bool running) { return false; }
}; };

View File

@ -169,7 +169,7 @@ XAudio2::~XAudio2()
CoUninitialize(); CoUninitialize();
} }
bool XAudio2::Start() bool XAudio2::Init()
{ {
HRESULT hr; HRESULT hr;
@ -210,15 +210,17 @@ void XAudio2::SetVolume(int volume)
m_mastering_voice->SetVolume(m_volume); m_mastering_voice->SetVolume(m_volume);
} }
void XAudio2::SetRunning(bool running) bool XAudio2::SetRunning(bool running)
{ {
if (m_voice_context) if (!m_voice_context)
{ return false;
if (running)
m_voice_context->Play(); if (running)
else m_voice_context->Play();
m_voice_context->Stop(); else
} m_voice_context->Stop();
return true;
} }
void XAudio2::Stop() void XAudio2::Stop()

View File

@ -51,15 +51,15 @@ private:
static void* PXAudio2Create; static void* PXAudio2Create;
static bool InitLibrary(); static bool InitLibrary();
void Stop();
public: public:
XAudio2(); XAudio2();
virtual ~XAudio2(); ~XAudio2() override;
bool Start() override; bool Init() override;
void Stop() override;
void SetRunning(bool running) override; bool SetRunning(bool running) override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
static bool isValid() { return InitLibrary(); } static bool isValid() { return InitLibrary(); }

View File

@ -157,7 +157,7 @@ XAudio2_7::~XAudio2_7()
CoUninitialize(); CoUninitialize();
} }
bool XAudio2_7::Start() bool XAudio2_7::Init()
{ {
HRESULT hr; HRESULT hr;
@ -198,15 +198,17 @@ void XAudio2_7::SetVolume(int volume)
m_mastering_voice->SetVolume(m_volume); m_mastering_voice->SetVolume(m_volume);
} }
void XAudio2_7::SetRunning(bool running) bool XAudio2_7::SetRunning(bool running)
{ {
if (m_voice_context) if (!m_voice_context)
{ return false;
if (running)
m_voice_context->Play(); if (running)
else m_voice_context->Play();
m_voice_context->Stop(); else
} m_voice_context->Stop();
return true;
} }
void XAudio2_7::Stop() void XAudio2_7::Stop()

View File

@ -56,15 +56,15 @@ private:
static HMODULE m_xaudio2_dll; static HMODULE m_xaudio2_dll;
static bool InitLibrary(); static bool InitLibrary();
void Stop();
public: public:
XAudio2_7(); XAudio2_7();
virtual ~XAudio2_7(); ~XAudio2_7() override;
bool Start() override; bool Init() override;
void Stop() override;
void SetRunning(bool running) override; bool SetRunning(bool running) override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
static bool isValid() { return InitLibrary(); } static bool isValid() { return InitLibrary(); }