made atomic lock optional

fixed an incorrect merge to nativeApp.cpp

made atomic locks init correctly

reintroduced atomic locks in audio as an optional setting

converted global pointers to global objects on stack

moved all mixing code into PSPMixer

internaized all code into __sceAudio.cpp

cleaned up rebase

cleaned up rebase
This commit is contained in:
Siddharth 2013-10-15 11:36:37 +05:30
parent 66e210315b
commit 06c13926ee
4 changed files with 88 additions and 6 deletions

View File

@ -118,6 +118,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
cpu->Get("Jit", &bJit, true);
#endif
cpu->Get("SeparateCPUThread", &bSeparateCPUThread, false);
cpu->Get("AtomicAudioLocks", &bAtomicAudioLocks, false);
#ifdef __SYMBIAN32__
cpu->Get("SeparateIOThread", &bSeparateIOThread, false);
#else
@ -314,6 +316,7 @@ void Config::Save() {
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
cpu->Set("Jit", bJit);
cpu->Set("SeparateCPUThread", bSeparateCPUThread);
cpu->Set("AtomicAudioLocks", bAtomicAudioLocks);
cpu->Set("SeparateIOThread", bSeparateIOThread);
cpu->Set("FastMemory", bFastMemory);
cpu->Set("CPUSpeed", iLockedCPUSpeed);

View File

@ -52,6 +52,7 @@ public:
// Definitely cannot be changed while game is running.
bool bSeparateCPUThread;
bool bSeparateIOThread;
bool bAtomicAudioLocks;
int iLockedCPUSpeed;
bool bAutoSaveSymbolMap;
std::string sReportHost;

View File

@ -28,12 +28,16 @@
#include "ChunkFile.h"
#include "FixedSizeQueue.h"
#include "Common/Thread.h"
#include "Common/Atomics.h"
#include "../../native/base/mutex.h"
// 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 atomicLock_;
recursive_mutex mutex_;
int eventAudioUpdate = -1;
int eventHostAudioUpdate = -1;
int eventHostAudioUpdate = -1;
int mixFrequency = 44100;
const int hwSampleRate = 44100;
@ -55,6 +59,11 @@ static int chanQueueMinSizeFactor;
// is bad mojo.
FixedSizeQueue<s16, 512 * 16> outAudioQueue;
bool __gainAudioQueueLock();
void __releaseAcquiredLock();
void __blockForAudioQueueLock();
static inline s16 clamp_s16(int i) {
if (i > 32767)
return 32767;
@ -108,6 +117,8 @@ void __AudioInit() {
mixBuffer = new s32[hwBlockSize * 2];
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
}
void __AudioDoState(PointerWrap &p) {
@ -122,9 +133,16 @@ void __AudioDoState(PointerWrap &p) {
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...
__blockForAudioQueueLock();
outAudioQueue.DoState(p);
//release the atomic lock
__releaseAcquiredLock();
}
int chanCount = ARRAY_SIZE(chans);
@ -140,6 +158,7 @@ void __AudioDoState(PointerWrap &p) {
void __AudioShutdown() {
delete [] mixBuffer;
mixBuffer = 0;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
chans[i].clear();
@ -322,11 +341,19 @@ void __AudioUpdate() {
}
if (g_Config.bEnableSound) {
lock_guard guard(section);
__blockForAudioQueueLock();
/*
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 +364,8 @@ void __AudioUpdate() {
// This happens quite a lot. There's still something slightly off
// about the amount of audio we produce.
}
//release the atomic lock
__releaseAcquiredLock();
}
}
@ -344,6 +373,7 @@ void __AudioUpdate() {
// This is called from *outside* the emulator thread.
int __AudioMix(short *outstereo, int numFrames)
{
// TODO: if mixFrequency != the actual output frequency, resample!
int underrun = -1;
s16 sampleL = 0;
@ -352,12 +382,22 @@ int __AudioMix(short *outstereo, int numFrames)
const s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
{
lock_guard guard(section);
//TODO: do rigorous testing to see whether just blind locking will improve speed.
if (!__gainAudioQueueLock()){
memset(outstereo, 0, numFrames * 2 * sizeof(short));
return 0;
}
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
__releaseAcquiredLock();
}
int remains = (int)(numFrames * 2 - sz1 - sz2);
@ -370,3 +410,39 @@ int __AudioMix(short *outstereo, int 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 (g_Config.bAtomicAudioLocks){
/*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 atomicLock_.test_and_set() == 0;
} else {
mutex_.lock();
return true;
}
};
inline void __releaseAcquiredLock(){
if (g_Config.bAtomicAudioLocks){
atomicLock_.clear();
} else {
mutex_.unlock();
}
}
inline void __blockForAudioQueueLock(){
if (g_Config.bAtomicAudioLocks){
while ((atomicLock_.test_and_set() == 0)){ }
} else {
mutex_.lock();
}
}

View File

@ -246,6 +246,8 @@ void GameSettingsScreen::CreateViews() {
#endif
systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, s->T("Change CPU Clock", "Change CPU Clock (0 = default)"), screenManager()));
systemSettings->Add(new CheckBox(&g_Config.bAtomicAudioLocks, s->T("Atomic Audio locks (experimental)")))->SetEnabled(!PSP_IsInited());
enableReports_ = Reporting::IsEnabled();
//#ifndef ANDROID
systemSettings->Add(new ItemHeader(s->T("Cheats", "Cheats (experimental, see forums)")));