diff options
Diffstat (limited to 'src/SPU.cpp')
-rw-r--r-- | src/SPU.cpp | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/src/SPU.cpp b/src/SPU.cpp index 2dfdf44..b36becf 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -27,7 +27,6 @@ // * channel hold // * 'length less than 4' glitch - namespace SPU { @@ -65,8 +64,8 @@ const u32 kSamplesPerRun = 1; const u32 OutputBufferSize = 2*1024; s16 OutputBuffer[2 * OutputBufferSize]; -u32 OutputReadOffset; -u32 OutputWriteOffset; +volatile u32 OutputReadOffset; +volatile u32 OutputWriteOffset; u16 Cnt; @@ -99,9 +98,7 @@ void DeInit() void Reset() { - memset(OutputBuffer, 0, 2*OutputBufferSize*2); - OutputReadOffset = 0; - OutputWriteOffset = OutputBufferSize; + InitOutput(); Cnt = 0; MasterVolume = 0; @@ -629,7 +626,7 @@ void Mix(u32 samples) else if (val > 0x7FFF) val = 0x7FFF; Capture[0]->Run(val); - if (!((Capture[0]->Cnt & (1<<7)))) break; + if (!(Capture[0]->Cnt & (1<<7))) break; } } @@ -644,7 +641,7 @@ void Mix(u32 samples) else if (val > 0x7FFF) val = 0x7FFF; Capture[1]->Run(val); - if (!((Capture[1]->Cnt & (1<<7)))) break; + if (!(Capture[1]->Cnt & (1<<7))) break; } } @@ -734,13 +731,60 @@ void Mix(u32 samples) OutputBuffer[OutputWriteOffset + 1] = r >> 1; OutputWriteOffset += 2; OutputWriteOffset &= ((2*OutputBufferSize)-1); - if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW\n"); + if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1); } NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun); } +void DrainOutput() +{ + OutputReadOffset = 0; + OutputWriteOffset = 0; +} + +void InitOutput() +{ + memset(OutputBuffer, 0, 2*OutputBufferSize*2); + OutputReadOffset = 0; + OutputWriteOffset = OutputBufferSize; +} + +int GetOutputSize() +{ + int ret; + if (OutputWriteOffset >= OutputReadOffset) + ret = OutputWriteOffset - OutputReadOffset; + else + ret = (OutputBufferSize*2) - OutputReadOffset + OutputWriteOffset; + + ret >>= 1; + return ret; +} + +void Sync(bool wait) +{ + // sync to audio output in case the core is running too fast + // * wait=true: wait until enough audio data has been played + // * wait=false: merely skip some audio data to avoid a FIFO overflow + + const int halflimit = (OutputBufferSize / 2); + + if (wait) + { + // TODO: less CPU-intensive wait? + while (GetOutputSize() > halflimit); + } + else if (GetOutputSize() > halflimit) + { + int readpos = OutputWriteOffset - (halflimit*2); + if (readpos < 0) readpos += (OutputBufferSize*2); + + OutputReadOffset = readpos; + } +} + int ReadOutput(s16* data, int samples) { if (OutputReadOffset == OutputWriteOffset) @@ -908,8 +952,8 @@ void Write16(u32 addr, u16 val) return; case 0xA: chan->SetLoopPos(val); return; - case 0xC: chan->SetLength((chan->Length & 0xFFFF0000) | val); return; - case 0xE: chan->SetLength((chan->Length & 0x0000FFFF) | (val << 16)); return; + case 0xC: chan->SetLength(((chan->Length >> 2) & 0xFFFF0000) | val); return; + case 0xE: chan->SetLength(((chan->Length >> 2) & 0x0000FFFF) | (val << 16)); return; } } else |