mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #4021 from bollu/master
Audio Processor now uses atomics rather than mutex
This commit is contained in:
commit
c84a9daa40
2 changed files with 61 additions and 7 deletions
|
@ -28,12 +28,15 @@
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
#include "FixedSizeQueue.h"
|
#include "FixedSizeQueue.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
|
#include "Common/Atomics.h"
|
||||||
|
#include "../../native/base/mutex.h"
|
||||||
|
|
||||||
// Should be used to lock anything related to the outAudioQueue.
|
// Should be used to lock anything related to the outAudioQueue.
|
||||||
recursive_mutex section;
|
//atomic locks are used on the lock. TODO: make this lock-free
|
||||||
|
atomic_flag audioQueueLock(NATIVE_ATOMIC_FLAG_INIT);
|
||||||
|
|
||||||
int eventAudioUpdate = -1;
|
int eventAudioUpdate = -1;
|
||||||
int eventHostAudioUpdate = -1;
|
int eventHostAudioUpdate = -1;
|
||||||
int mixFrequency = 44100;
|
int mixFrequency = 44100;
|
||||||
|
|
||||||
const int hwSampleRate = 44100;
|
const int hwSampleRate = 44100;
|
||||||
|
@ -55,6 +58,9 @@ static int chanQueueMinSizeFactor;
|
||||||
// is bad mojo.
|
// is bad mojo.
|
||||||
FixedSizeQueue<s16, 512 * 16> outAudioQueue;
|
FixedSizeQueue<s16, 512 * 16> outAudioQueue;
|
||||||
|
|
||||||
|
bool __gainAudioQueueLock();
|
||||||
|
void __releaseAcquiredLock();
|
||||||
|
|
||||||
static inline s16 clamp_s16(int i) {
|
static inline s16 clamp_s16(int i) {
|
||||||
if (i > 32767)
|
if (i > 32767)
|
||||||
return 32767;
|
return 32767;
|
||||||
|
@ -108,6 +114,8 @@ void __AudioInit() {
|
||||||
|
|
||||||
mixBuffer = new s32[hwBlockSize * 2];
|
mixBuffer = new s32[hwBlockSize * 2];
|
||||||
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
|
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __AudioDoState(PointerWrap &p) {
|
void __AudioDoState(PointerWrap &p) {
|
||||||
|
@ -122,9 +130,18 @@ void __AudioDoState(PointerWrap &p) {
|
||||||
|
|
||||||
p.Do(mixFrequency);
|
p.Do(mixFrequency);
|
||||||
|
|
||||||
{
|
{
|
||||||
lock_guard guard(section);
|
//block until a lock is achieved. Not a good idea at all, but
|
||||||
|
//can't think of a better one...
|
||||||
|
while(!__gainAudioQueueLock()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
outAudioQueue.DoState(p);
|
outAudioQueue.DoState(p);
|
||||||
|
|
||||||
|
//release the atomic lock
|
||||||
|
__releaseAcquiredLock();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int chanCount = ARRAY_SIZE(chans);
|
int chanCount = ARRAY_SIZE(chans);
|
||||||
|
@ -322,11 +339,18 @@ void __AudioUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_Config.bEnableSound) {
|
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) {
|
if (outAudioQueue.room() >= hwBlockSize * 2) {
|
||||||
s16 *buf1 = 0, *buf2 = 0;
|
s16 *buf1 = 0, *buf2 = 0;
|
||||||
size_t sz1, sz2;
|
size_t sz1, sz2;
|
||||||
outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
|
outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
|
||||||
|
|
||||||
for (size_t s = 0; s < sz1; s++)
|
for (size_t s = 0; s < sz1; s++)
|
||||||
buf1[s] = clamp_s16(mixBuffer[s]);
|
buf1[s] = clamp_s16(mixBuffer[s]);
|
||||||
if (buf2) {
|
if (buf2) {
|
||||||
|
@ -337,6 +361,9 @@ void __AudioUpdate() {
|
||||||
// This happens quite a lot. There's still something slightly off
|
// This happens quite a lot. There's still something slightly off
|
||||||
// about the amount of audio we produce.
|
// about the amount of audio we produce.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//release the atomic lock
|
||||||
|
__releaseAcquiredLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,12 +379,21 @@ int __AudioMix(short *outstereo, int numFrames)
|
||||||
const s16 *buf1 = 0, *buf2 = 0;
|
const s16 *buf1 = 0, *buf2 = 0;
|
||||||
size_t sz1, sz2;
|
size_t sz1, sz2;
|
||||||
{
|
{
|
||||||
lock_guard guard(section);
|
|
||||||
|
if(!__gainAudioQueueLock()){
|
||||||
|
return numFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2);
|
outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2);
|
||||||
|
|
||||||
memcpy(outstereo, buf1, sz1 * sizeof(s16));
|
memcpy(outstereo, buf1, sz1 * sizeof(s16));
|
||||||
if (buf2) {
|
if (buf2) {
|
||||||
memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16));
|
memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//release the atomic lock
|
||||||
|
__releaseAcquiredLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int remains = (int)(numFrames * 2 - sz1 - sz2);
|
int remains = (int)(numFrames * 2 - sz1 - sz2);
|
||||||
|
@ -370,3 +406,21 @@ int __AudioMix(short *outstereo, int numFrames)
|
||||||
}
|
}
|
||||||
return underrun >= 0 ? underrun : numFrames;
|
return underrun >= 0 ? underrun : numFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*returns whether the lock was successfully gained or not.
|
||||||
|
i.e - whether the lock belongs to you
|
||||||
|
*/
|
||||||
|
inline bool __gainAudioQueueLock(){
|
||||||
|
/*if the previous state was 0, that means the lock was "unlocked". So,
|
||||||
|
we return !0, which is true thanks to C's int to bool conversion
|
||||||
|
|
||||||
|
One the other hand, if it was locked, then the lock would return 1.
|
||||||
|
so, !1 = 0 = false.
|
||||||
|
*/
|
||||||
|
return !audioQueueLock.test_and_set();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void __releaseAcquiredLock(){
|
||||||
|
audioQueueLock.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sceAudio.h"
|
#include "sceAudio.h"
|
||||||
|
|
||||||
|
|
||||||
// Easy interface for sceAudio to write to, to keep the complexity in check.
|
// Easy interface for sceAudio to write to, to keep the complexity in check.
|
||||||
|
|
||||||
void __AudioInit();
|
void __AudioInit();
|
||||||
|
|
Loading…
Add table
Reference in a new issue