This commit is contained in:
Sparronator 2025-04-10 01:40:28 +09:00 committed by GitHub
commit 2fa421d4ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 71 deletions

View File

@ -1045,7 +1045,6 @@ u32 NDS::RunFrame()
ARM7Timestamp-SysTimestamp,
GPU.GPU3D.Timestamp-SysTimestamp);
#endif
SPU.TransferOutput();
break;
}

View File

@ -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;

View File

@ -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;

View File

@ -296,6 +296,7 @@ private:
SDL_AudioDeviceID audioDevice;
int audioFreq;
int audioBufSize;
float audioSampleFrac;
bool audioMuted;
SDL_cond* audioSyncCond;

View File

@ -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;