diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 10f05c7519..3faec635ae 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -29,8 +29,9 @@ #include "FixedSizeQueue.h" #include "Common/Thread.h" + // Should be used to lock anything related to the outAudioQueue. -recursive_mutex section; +std::atomic audioQueueLock; int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; @@ -55,6 +56,10 @@ static int chanQueueMinSizeFactor; // is bad mojo. FixedSizeQueue outAudioQueue; + +bool __gainAudioQueueLock(); + + static inline s16 clamp_s16(int i) { if (i > 32767) return 32767; @@ -108,6 +113,8 @@ void __AudioInit() { mixBuffer = new s32[hwBlockSize * 2]; memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32)); + + audioQueueLock.store(false); } void __AudioDoState(PointerWrap &p) { @@ -123,8 +130,15 @@ void __AudioDoState(PointerWrap &p) { p.Do(mixFrequency); { - lock_guard guard(section); + if(!__gainAudioQueueLock()){ + return; + } + outAudioQueue.DoState(p); + + //release the atomic lock + audioQueueLock.store(false); + } int chanCount = ARRAY_SIZE(chans); @@ -322,11 +336,18 @@ void __AudioUpdate() { } if (g_Config.bEnableSound) { - lock_guard guard(section); + + //looks like the heavy lifting is done here. + //we have to optimize this some more. + if(!__gainAudioQueueLock()){ + return; + } + if (outAudioQueue.room() >= hwBlockSize * 2) { s16 *buf1 = 0, *buf2 = 0; size_t sz1, sz2; outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2); + for (size_t s = 0; s < sz1; s++) buf1[s] = clamp_s16(mixBuffer[s]); if (buf2) { @@ -337,6 +358,9 @@ void __AudioUpdate() { // This happens quite a lot. There's still something slightly off // about the amount of audio we produce. } + + //release the atomic lock + audioQueueLock.store(false); } } @@ -352,12 +376,21 @@ int __AudioMix(short *outstereo, int numFrames) const s16 *buf1 = 0, *buf2 = 0; size_t sz1, sz2; { - lock_guard guard(section); + + if(!__gainAudioQueueLock()){ + return numFrames; + } + + outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2); + memcpy(outstereo, buf1, sz1 * sizeof(s16)); if (buf2) { memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16)); } + + //release the atomic lock + audioQueueLock.store(false); } int remains = (int)(numFrames * 2 - sz1 - sz2); @@ -370,3 +403,13 @@ int __AudioMix(short *outstereo, int numFrames) } return underrun >= 0 ? underrun : numFrames; } + + +bool __gainAudioQueueLock(){ + if(audioQueueLock.load(std::memory_order::memory_order_relaxed) == true){ + return false; + } + + audioQueueLock.store(true, std::memory_order::memory_order_relaxed ); + return true; +}; diff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h index 403c2f961f..3178b51f5e 100644 --- a/Core/HLE/__sceAudio.h +++ b/Core/HLE/__sceAudio.h @@ -16,8 +16,10 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once - #include "sceAudio.h" +#include + + // Easy interface for sceAudio to write to, to keep the complexity in check.