From 4920dbed13b0bef0e17fe0ad9d73b9f702a5e523 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 9 May 2015 23:48:22 -0400 Subject: [PATCH 1/4] AudioCommon: Migrate threadData to OpenALStream and AOSoundStream This is only ever used in these two sound streams. Seems silly to have it as a class member. Converted it to an atomic as well. --- Source/Core/AudioCommon/AOSoundStream.cpp | 5 +++-- Source/Core/AudioCommon/AOSoundStream.h | 2 ++ Source/Core/AudioCommon/OpenALStream.cpp | 5 +++-- Source/Core/AudioCommon/OpenALStream.h | 3 +++ Source/Core/AudioCommon/SoundStream.h | 6 +----- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Source/Core/AudioCommon/AOSoundStream.cpp b/Source/Core/AudioCommon/AOSoundStream.cpp index 7def6331a3..7aa9de9ac4 100644 --- a/Source/Core/AudioCommon/AOSoundStream.cpp +++ b/Source/Core/AudioCommon/AOSoundStream.cpp @@ -32,7 +32,7 @@ void AOSound::SoundLoop() buf_size = format.bits/8 * format.channels * format.rate; - while (!threadData) + while (m_run_thread.load()) { m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); @@ -47,6 +47,7 @@ void AOSound::SoundLoop() bool AOSound::Start() { + m_run_thread.store(true); memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); thread = std::thread(&AOSound::SoundLoop, this); @@ -60,7 +61,7 @@ void AOSound::Update() void AOSound::Stop() { - threadData = 1; + m_run_thread.store(false); soundSyncEvent.Set(); { diff --git a/Source/Core/AudioCommon/AOSoundStream.h b/Source/Core/AudioCommon/AOSoundStream.h index 23799f7627..26f618aa44 100644 --- a/Source/Core/AudioCommon/AOSoundStream.h +++ b/Source/Core/AudioCommon/AOSoundStream.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -19,6 +20,7 @@ class AOSound final : public SoundStream { #if defined(HAVE_AO) && HAVE_AO std::thread thread; + std::atomic m_run_thread; std::mutex soundCriticalSection; Common::Event soundSyncEvent; diff --git a/Source/Core/AudioCommon/OpenALStream.cpp b/Source/Core/AudioCommon/OpenALStream.cpp index 57c2e286d6..c8cb9d23eb 100644 --- a/Source/Core/AudioCommon/OpenALStream.cpp +++ b/Source/Core/AudioCommon/OpenALStream.cpp @@ -23,6 +23,7 @@ static soundtouch::SoundTouch soundTouch; // bool OpenALStream::Start() { + m_run_thread.store(true); bool bReturn = false; ALDeviceList pDeviceList; @@ -72,7 +73,7 @@ bool OpenALStream::Start() void OpenALStream::Stop() { - threadData = 1; + m_run_thread.store(false); // kick the thread if it's waiting soundSyncEvent.Set(); @@ -183,7 +184,7 @@ void OpenALStream::SoundLoop() soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); soundTouch.setSetting(SETTING_OVERLAP_MS, 12); - while (!threadData) + while (m_run_thread.load()) { // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. const u32 stereo_16_bit_size = 4; diff --git a/Source/Core/AudioCommon/OpenALStream.h b/Source/Core/AudioCommon/OpenALStream.h index a8fbd8a1f2..d43fcdec19 100644 --- a/Source/Core/AudioCommon/OpenALStream.h +++ b/Source/Core/AudioCommon/OpenALStream.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "AudioCommon/SoundStream.h" @@ -72,6 +73,8 @@ public: private: std::thread thread; + std::atomic m_run_thread; + Common::Event soundSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS]; diff --git a/Source/Core/AudioCommon/SoundStream.h b/Source/Core/AudioCommon/SoundStream.h index ff30f36f37..94541c3b90 100644 --- a/Source/Core/AudioCommon/SoundStream.h +++ b/Source/Core/AudioCommon/SoundStream.h @@ -11,17 +11,13 @@ class SoundStream { protected: - CMixer* m_mixer; - // We set this to shut down the sound thread. - // 0=keep playing, 1=stop playing NOW. - volatile int threadData; bool m_logAudio; WaveFileWriter g_wave_writer; bool m_muted; public: - SoundStream(CMixer* mixer) : m_mixer(mixer), threadData(0), m_logAudio(false), m_muted(false) {} + SoundStream(CMixer* mixer) : m_mixer(mixer), m_logAudio(false), m_muted(false) {} virtual ~SoundStream() { delete m_mixer; } static bool isValid() { return false; } From 7b376abd3bd59eeeeddb3cdb6f0000e8c901ba1e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 9 May 2015 23:50:45 -0400 Subject: [PATCH 2/4] Mixer: Convert volatile variables to atomics. --- Source/Core/AudioCommon/Mixer.cpp | 23 ++++++++++------------- Source/Core/AudioCommon/Mixer.h | 15 ++++++++------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index 90f771d3fa..90fcbd06ae 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -4,7 +4,6 @@ #include "AudioCommon/AudioCommon.h" #include "AudioCommon/Mixer.h" -#include "Common/Atomic.h" #include "Common/CPUDetect.h" #include "Common/MathUtil.h" #include "Core/ConfigManager.h" @@ -31,8 +30,8 @@ unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples, boo // so we will just ignore new written data while interpolating. // Without this cache, the compiler wouldn't be allowed to optimize the // interpolation loop. - u32 indexR = Common::AtomicLoad(m_indexR); - u32 indexW = Common::AtomicLoad(m_indexW); + u32 indexR = m_indexR.load(); + u32 indexW = m_indexW.load(); float numLeft = (float)(((indexW - indexR) & INDEX_MASK) / 2); m_numLeftI = (numLeft + m_numLeftI*(CONTROL_AVG-1)) / CONTROL_AVG; @@ -53,8 +52,8 @@ unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples, boo const u32 ratio = (u32)(65536.0f * aid_sample_rate / (float)m_mixer->m_sampleRate); - s32 lvolume = m_LVolume; - s32 rvolume = m_RVolume; + s32 lvolume = m_LVolume.load(); + s32 rvolume = m_RVolume.load(); // TODO: consider a higher-quality resampling algorithm. for (; currentSample < numSamples * 2 && ((indexW-indexR) & INDEX_MASK) > 2; currentSample += 2) @@ -99,7 +98,7 @@ unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples, boo } // Flush cached variable - Common::AtomicStore(m_indexR, indexR); + m_indexR.store(indexR); return numSamples; } @@ -130,11 +129,11 @@ void CMixer::MixerFifo::PushSamples(const short *samples, unsigned int num_sampl // Cache access in non-volatile variable // indexR isn't allowed to cache in the audio throttling loop as it // needs to get updates to not deadlock. - u32 indexW = Common::AtomicLoad(m_indexW); + u32 indexW = m_indexW.load(); // Check if we have enough free space // indexW == m_indexR results in empty buffer, so indexR must always be smaller than indexW - if (num_samples * 2 + ((indexW - Common::AtomicLoad(m_indexR)) & INDEX_MASK) >= MAX_SAMPLES * 2) + if (num_samples * 2 + ((indexW - m_indexR.load()) & INDEX_MASK) >= MAX_SAMPLES * 2) return; // AyuanX: Actual re-sampling work has been moved to sound thread @@ -151,9 +150,7 @@ void CMixer::MixerFifo::PushSamples(const short *samples, unsigned int num_sampl memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4); } - Common::AtomicAdd(m_indexW, num_samples * 2); - - return; + m_indexW.fetch_add(num_samples * 2); } void CMixer::PushSamples(const short *samples, unsigned int num_samples) @@ -215,6 +212,6 @@ void CMixer::MixerFifo::SetInputSampleRate(unsigned int rate) void CMixer::MixerFifo::SetVolume(unsigned int lvolume, unsigned int rvolume) { - m_LVolume = lvolume + (lvolume >> 7); - m_RVolume = rvolume + (rvolume >> 7); + m_LVolume.store(lvolume + (lvolume >> 7)); + m_RVolume.store(rvolume + (rvolume >> 7)); } diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index ba9809d5bc..cc73b95406 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -109,8 +110,8 @@ public: std::mutex& MixerCritical() { return m_csMixing; } - float GetCurrentSpeed() const { return m_speed; } - void UpdateSpeed(volatile float val) { m_speed = val; } + float GetCurrentSpeed() const { return m_speed.load(); } + void UpdateSpeed(float val) { m_speed.store(val); } protected: class MixerFifo { @@ -135,11 +136,11 @@ protected: CMixer *m_mixer; unsigned m_input_sample_rate; short m_buffer[MAX_SAMPLES * 2]; - volatile u32 m_indexW; - volatile u32 m_indexR; + std::atomic m_indexW; + std::atomic m_indexR; // Volume ranges from 0-256 - volatile s32 m_LVolume; - volatile s32 m_RVolume; + std::atomic m_LVolume; + std::atomic m_RVolume; float m_numLeftI; u32 m_frac; }; @@ -156,5 +157,5 @@ protected: std::mutex m_csMixing; - volatile float m_speed; // Current rate of the emulation (1.0 = 100% speed) + std::atomic m_speed; // Current rate of the emulation (1.0 = 100% speed) }; From 353205132c6fa5da8edbe1a4097cef2fad872794 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 10 May 2015 00:20:27 -0400 Subject: [PATCH 3/4] AlsaSoundStream: Convert volatile variables to atomics --- Source/Core/AudioCommon/AlsaSoundStream.cpp | 10 +++++----- Source/Core/AudioCommon/AlsaSoundStream.h | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index 5f76c60de7..099a3dee35 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -23,13 +23,13 @@ AlsaSound::~AlsaSound() bool AlsaSound::Start() { thread = std::thread(&AlsaSound::SoundLoop, this); - thread_data = 0; + thread_data.store(0); return true; } void AlsaSound::Stop() { - thread_data = 1; + thread_data.store(1); thread.join(); } @@ -42,11 +42,11 @@ void AlsaSound::Update() void AlsaSound::SoundLoop() { if (!AlsaInit()) { - thread_data = 2; + thread_data.store(2); return; } Common::SetCurrentThreadName("Audio thread - alsa"); - while (!thread_data) + while (thread_data.load() == 0) { m_mixer->Mix(reinterpret_cast(mix_buffer), frames_to_deliver); int rc = m_muted ? 1337 : snd_pcm_writei(handle, mix_buffer, frames_to_deliver); @@ -61,7 +61,7 @@ void AlsaSound::SoundLoop() } } AlsaShutdown(); - thread_data = 2; + thread_data.store(2); } bool AlsaSound::AlsaInit() diff --git a/Source/Core/AudioCommon/AlsaSoundStream.h b/Source/Core/AudioCommon/AlsaSoundStream.h index 65173351f8..63b61fba90 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.h +++ b/Source/Core/AudioCommon/AlsaSoundStream.h @@ -4,13 +4,15 @@ #pragma once +#include +#include + #if defined(HAVE_ALSA) && HAVE_ALSA #include #endif #include "AudioCommon/SoundStream.h" #include "Common/CommonTypes.h" -#include "Common/Thread.h" class AlsaSound final : public SoundStream { @@ -39,7 +41,7 @@ private: // 0 = continue // 1 = shutdown // 2 = done shutting down. - volatile int thread_data; + std::atomic thread_data; snd_pcm_t *handle; int frames_to_deliver; From f907e5cacee4f0a6c250f0d640eb11d006475f6b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 10 May 2015 02:30:24 -0400 Subject: [PATCH 4/4] AlsaSoundStream: Use an enum class for signifying ALSA thread state --- Source/Core/AudioCommon/AlsaSoundStream.cpp | 16 ++++++++++------ Source/Core/AudioCommon/AlsaSoundStream.h | 12 ++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index 099a3dee35..2bcb4ddbfb 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -10,7 +10,11 @@ #define BUFFER_SIZE_MAX 8192 #define BUFFER_SIZE_BYTES (BUFFER_SIZE_MAX*2*2) -AlsaSound::AlsaSound(CMixer *mixer) : SoundStream(mixer), thread_data(0), handle(nullptr), frames_to_deliver(FRAME_COUNT_MIN) +AlsaSound::AlsaSound(CMixer *mixer) + : SoundStream(mixer) + , m_thread_status(ALSAThreadStatus::STOPPED) + , handle(nullptr) + , frames_to_deliver(FRAME_COUNT_MIN) { mix_buffer = new u8[BUFFER_SIZE_BYTES]; } @@ -22,14 +26,14 @@ AlsaSound::~AlsaSound() bool AlsaSound::Start() { + m_thread_status.store(ALSAThreadStatus::RUNNING); thread = std::thread(&AlsaSound::SoundLoop, this); - thread_data.store(0); return true; } void AlsaSound::Stop() { - thread_data.store(1); + m_thread_status.store(ALSAThreadStatus::STOPPING); thread.join(); } @@ -42,11 +46,11 @@ void AlsaSound::Update() void AlsaSound::SoundLoop() { if (!AlsaInit()) { - thread_data.store(2); + m_thread_status.store(ALSAThreadStatus::STOPPED); return; } Common::SetCurrentThreadName("Audio thread - alsa"); - while (thread_data.load() == 0) + while (m_thread_status.load() == ALSAThreadStatus::RUNNING) { m_mixer->Mix(reinterpret_cast(mix_buffer), frames_to_deliver); int rc = m_muted ? 1337 : snd_pcm_writei(handle, mix_buffer, frames_to_deliver); @@ -61,7 +65,7 @@ void AlsaSound::SoundLoop() } } AlsaShutdown(); - thread_data.store(2); + m_thread_status.store(ALSAThreadStatus::STOPPED); } bool AlsaSound::AlsaInit() diff --git a/Source/Core/AudioCommon/AlsaSoundStream.h b/Source/Core/AudioCommon/AlsaSoundStream.h index 63b61fba90..bb317c26aa 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.h +++ b/Source/Core/AudioCommon/AlsaSoundStream.h @@ -33,15 +33,19 @@ public: virtual void Update() override; private: + enum class ALSAThreadStatus + { + RUNNING, + STOPPING, + STOPPED, + }; + bool AlsaInit(); void AlsaShutdown(); u8 *mix_buffer; std::thread thread; - // 0 = continue - // 1 = shutdown - // 2 = done shutting down. - std::atomic thread_data; + std::atomic m_thread_status; snd_pcm_t *handle; int frames_to_deliver;