diff --git a/src/NDS.cpp b/src/NDS.cpp index 340cd020..5fd65bea 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1045,7 +1045,6 @@ u32 NDS::RunFrame() ARM7Timestamp-SysTimestamp, GPU.GPU3D.Timestamp-SysTimestamp); #endif - SPU.TransferOutput(); break; } diff --git a/src/SPU.cpp b/src/SPU.cpp index 0f0c286d..b3688793 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -207,11 +207,10 @@ SPU::SPU(melonDS::NDS& nds, AudioBitDepth bitdepth, AudioInterpolation interpola ApplyBias = true; Degrade10Bit = false; - memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2); + memset(OutputBuffer, 0, 2*OutputBufferSize*2); - OutputBackbufferWritePosition = 0; - OutputFrontBufferReadPosition = 0; - OutputFrontBufferWritePosition = 0; + OutputBufferReadPos = 0; + OutputBufferWritePos = 0; } SPU::~SPU() @@ -242,11 +241,10 @@ void SPU::Reset() void SPU::Stop() { Platform::Mutex_Lock(AudioLock); - memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2); + memset(OutputBuffer, 0, 2*OutputBufferSize*2); - OutputBackbufferWritePosition = 0; - OutputFrontBufferReadPosition = 0; - OutputFrontBufferWritePosition = 0; + OutputBufferReadPos = 0; + OutputBufferWritePos = 0; Platform::Mutex_Unlock(AudioLock); } @@ -942,67 +940,49 @@ void SPU::Mix(u32 dummy) rightoutput &= 0xFFFFFFC0; } - // OutputBufferFrame can never get full because it's - // transfered to OutputBuffer at the end of the frame - // FIXME: apparently this does happen!!! - if (OutputBackbufferWritePosition * 2 < OutputBufferSize - 1) + Platform::Mutex_Lock(AudioLock); + OutputBuffer[OutputBufferWritePos++] = leftoutput >> 1; + OutputBuffer[OutputBufferWritePos++] = rightoutput >> 1; + + OutputBufferWritePos &= ((2*OutputBufferSize)-1); + + if (OutputBufferWritePos == OutputBufferReadPos) { - OutputBackbuffer[OutputBackbufferWritePosition ] = leftoutput >> 1; - OutputBackbuffer[OutputBackbufferWritePosition + 1] = rightoutput >> 1; - OutputBackbufferWritePosition += 2; + // advance the read position too, to avoid losing the entire FIFO + OutputBufferReadPos += 2; + OutputBufferReadPos &= ((2*OutputBufferSize)-1); } + Platform::Mutex_Unlock(AudioLock); NDS.ScheduleEvent(Event_SPU, true, 1024, 0, 0); } -void SPU::TransferOutput() -{ - Platform::Mutex_Lock(AudioLock); - for (u32 i = 0; i < OutputBackbufferWritePosition; i += 2) - { - OutputFrontBuffer[OutputFrontBufferWritePosition ] = OutputBackbuffer[i ]; - OutputFrontBuffer[OutputFrontBufferWritePosition + 1] = OutputBackbuffer[i + 1]; - - OutputFrontBufferWritePosition += 2; - OutputFrontBufferWritePosition &= OutputBufferSize*2-1; - if (OutputFrontBufferWritePosition == OutputFrontBufferReadPosition) - { - // advance the read position too, to avoid losing the entire FIFO - OutputFrontBufferReadPosition += 2; - OutputFrontBufferReadPosition &= OutputBufferSize*2-1; - } - } - OutputBackbufferWritePosition = 0; - Platform::Mutex_Unlock(AudioLock);; -} - void SPU::TrimOutput() { Platform::Mutex_Lock(AudioLock); const int halflimit = (OutputBufferSize / 2); - int readpos = OutputFrontBufferWritePosition - (halflimit*2); + int readpos = OutputBufferWritePos - (halflimit*2); if (readpos < 0) readpos += (OutputBufferSize*2); - OutputFrontBufferReadPosition = readpos; + OutputBufferReadPos = readpos; Platform::Mutex_Unlock(AudioLock); } void SPU::DrainOutput() { Platform::Mutex_Lock(AudioLock); - OutputFrontBufferWritePosition = 0; - OutputFrontBufferReadPosition = 0; + OutputBufferReadPos = 0; + OutputBufferWritePos = 0; Platform::Mutex_Unlock(AudioLock); } void SPU::InitOutput() { Platform::Mutex_Lock(AudioLock); - memset(OutputBackbuffer, 0, 2*OutputBufferSize*2); - memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2); - OutputFrontBufferReadPosition = 0; - OutputFrontBufferWritePosition = 0; + memset(OutputBuffer, 0, 2*OutputBufferSize*2); + OutputBufferReadPos = 0; + OutputBufferWritePos = 0; Platform::Mutex_Unlock(AudioLock); } @@ -1011,10 +991,10 @@ int SPU::GetOutputSize() const Platform::Mutex_Lock(AudioLock); int ret; - if (OutputFrontBufferWritePosition >= OutputFrontBufferReadPosition) - ret = OutputFrontBufferWritePosition - OutputFrontBufferReadPosition; + if (OutputBufferWritePos >= OutputBufferReadPos) + ret = OutputBufferWritePos - OutputBufferReadPos; else - ret = (OutputBufferSize*2) - OutputFrontBufferReadPosition + OutputFrontBufferWritePosition; + ret = (OutputBufferSize*2) - OutputBufferReadPos + OutputBufferWritePos; ret >>= 1; @@ -1043,10 +1023,10 @@ void SPU::Sync(bool wait) { Platform::Mutex_Lock(AudioLock); - int readpos = OutputFrontBufferWritePosition - (halflimit*2); + int readpos = OutputBufferWritePos - (halflimit*2); if (readpos < 0) readpos += (OutputBufferSize*2); - OutputFrontBufferReadPosition = readpos; + OutputBufferReadPos = readpos; Platform::Mutex_Unlock(AudioLock); } @@ -1055,7 +1035,7 @@ void SPU::Sync(bool wait) int SPU::ReadOutput(s16* data, int samples) { Platform::Mutex_Lock(AudioLock); - if (OutputFrontBufferReadPosition == OutputFrontBufferWritePosition) + if (OutputBufferReadPos == OutputBufferWritePos) { Platform::Mutex_Unlock(AudioLock); return 0; @@ -1063,13 +1043,11 @@ int SPU::ReadOutput(s16* data, int samples) for (int i = 0; i < samples; i++) { - *data++ = OutputFrontBuffer[OutputFrontBufferReadPosition]; - *data++ = OutputFrontBuffer[OutputFrontBufferReadPosition + 1]; + *data++ = OutputBuffer[OutputBufferReadPos++]; + *data++ = OutputBuffer[OutputBufferReadPos++]; + OutputBufferReadPos &= ((2*OutputBufferSize)-1); - OutputFrontBufferReadPosition += 2; - OutputFrontBufferReadPosition &= ((2*OutputBufferSize)-1); - - if (OutputFrontBufferWritePosition == OutputFrontBufferReadPosition) + if (OutputBufferWritePos == OutputBufferReadPos) { Platform::Mutex_Unlock(AudioLock); return i+1; diff --git a/src/SPU.h b/src/SPU.h index fa93273d..85921a5b 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -241,7 +241,6 @@ public: int GetOutputSize() const; void Sync(bool wait); int ReadOutput(s16* data, int samples); - void TransferOutput(); u8 Read8(u32 addr); u16 Read16(u32 addr); @@ -251,14 +250,11 @@ public: void Write32(u32 addr, u32 val); private: - static const u32 OutputBufferSize = 2*2048; + static const u32 OutputBufferSize = 2*1024; // TODO: configurable audio buffer sizes? melonDS::NDS& NDS; - s16 OutputBackbuffer[2 * OutputBufferSize] {}; - u32 OutputBackbufferWritePosition = 0; - - s16 OutputFrontBuffer[2 * OutputBufferSize] {}; - u32 OutputFrontBufferWritePosition = 0; - u32 OutputFrontBufferReadPosition = 0; + s16 OutputBuffer[2 * OutputBufferSize] {}; + u32 OutputBufferWritePos = 0; + u32 OutputBufferReadPos = 0; Platform::Mutex* AudioLock; diff --git a/src/frontend/qt_sdl/EmuInstance.h b/src/frontend/qt_sdl/EmuInstance.h index 295e9bf6..b77ee917 100755 --- a/src/frontend/qt_sdl/EmuInstance.h +++ b/src/frontend/qt_sdl/EmuInstance.h @@ -305,6 +305,7 @@ private: SDL_AudioDeviceID audioDevice; int audioFreq; + int audioBufSize; float audioSampleFrac; bool audioMuted; SDL_cond* audioSyncCond; diff --git a/src/frontend/qt_sdl/EmuInstanceAudio.cpp b/src/frontend/qt_sdl/EmuInstanceAudio.cpp index 2c925801..c8bb8913 100644 --- a/src/frontend/qt_sdl/EmuInstanceAudio.cpp +++ b/src/frontend/qt_sdl/EmuInstanceAudio.cpp @@ -73,8 +73,8 @@ void EmuInstance::audioCallback(void* data, Uint8* stream, int len) // resample incoming audio to match the output sample rate int len_in = inst->audioGetNumSamplesOut(len); - if (len_in > 1024) len_in = 1024; - s16 buf_in[1024*2]; + if (len_in > inst->audioBufSize) len_in = inst->audioBufSize; + s16 buf_in[inst->audioBufSize*2]; int num_in; SDL_LockMutex(inst->audioSyncLock); @@ -416,16 +416,17 @@ void EmuInstance::audioInit() audioSyncCond = SDL_CreateCond(); audioSyncLock = SDL_CreateMutex(); - audioFreq = 48000; // TODO: make configurable? + audioFreq = 48000; // TODO: make both of these configurable? + audioBufSize = 1024; SDL_AudioSpec whatIwant, whatIget; memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); whatIwant.freq = audioFreq; whatIwant.format = AUDIO_S16LSB; whatIwant.channels = 2; - whatIwant.samples = 1024; + whatIwant.samples = audioBufSize; whatIwant.callback = audioCallback; whatIwant.userdata = this; - audioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + audioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE); if (!audioDevice) { Platform::Log(Platform::LogLevel::Error, "Audio init failed: %s\n", SDL_GetError()); @@ -433,7 +434,9 @@ void EmuInstance::audioInit() else { audioFreq = whatIget.freq; + audioBufSize = whatIget.samples; Platform::Log(Platform::LogLevel::Info, "Audio output frequency: %d Hz\n", audioFreq); + Platform::Log(Platform::LogLevel::Info, "Audio output buffer size: %d samples\n", audioBufSize); SDL_PauseAudioDevice(audioDevice, 1); } @@ -479,7 +482,7 @@ void EmuInstance::audioSync() if (audioDevice) { SDL_LockMutex(audioSyncLock); - while (nds->SPU.GetOutputSize() > 1024) + while (nds->SPU.GetOutputSize() > audioBufSize) { int ret = SDL_CondWaitTimeout(audioSyncCond, audioSyncLock, 500); if (ret == SDL_MUTEX_TIMEDOUT) break;