mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Correct GetStreamDataInfo. Now passes the test at all buffer sizes I've tried.
This commit is contained in:
parent
1dd48ec73b
commit
67c8703302
2 changed files with 39 additions and 20 deletions
|
@ -280,8 +280,12 @@ int Atrac2::AddStreamData(u32 bytesToAdd) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int RoundDownToMultiple(int x, int n) {
|
||||
return (x % n == 0) ? x : x - (x % n) - (n * (x < 0));
|
||||
}
|
||||
|
||||
void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *bytesToRead, u32 *readFileOffset) {
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
const SceAtracIdInfo &info = context_->info;
|
||||
|
||||
*writePtr = info.buffer;
|
||||
switch (info.state) {
|
||||
|
@ -302,12 +306,11 @@ void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *bytesToRead, u32 *readFileOff
|
|||
// TODO: Take care of looping.
|
||||
// Compute some helper variables.
|
||||
int fileOffset = (int)info.curOff + (int)info.streamDataByte;
|
||||
int bytesLeft = (int)info.dataEnd - fileOffset;
|
||||
int bufferSpace = (int)info.bufferByte - (int)info.streamDataByte;
|
||||
int bytesLeftInFile = (int)info.dataEnd - fileOffset;
|
||||
|
||||
_dbg_assert_(bytesLeft >= 0);
|
||||
_dbg_assert_(bytesLeftInFile >= 0);
|
||||
|
||||
if (bytesLeft == 0) {
|
||||
if (bytesLeftInFile == 0) {
|
||||
// We've got all the data up to the end buffered, no more streaming is needed.
|
||||
// Signalling this by setting everything to zero.
|
||||
*writePtr = info.buffer;
|
||||
|
@ -316,16 +319,32 @@ void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *bytesToRead, u32 *readFileOff
|
|||
return;
|
||||
}
|
||||
|
||||
// Clamp to both available space in the buffer, and end-of-file.
|
||||
if (info.curOff < info.bufferByte) {
|
||||
// If on the first lap, we need some special handling to handle the cut packet.
|
||||
int cutLen = (info.bufferByte - info.curOff) % info.sampleSize;
|
||||
*writePtr = info.buffer + cutLen;
|
||||
*bytesToRead = std::min(bytesLeft, bufferSpace - cutLen);
|
||||
// Last allowed offset where a packet can start.
|
||||
const int lastPacketStart = info.bufferByte - info.sampleSize; // Last possible place in the buffer to put the next packet
|
||||
|
||||
// writePos is where the next write should be done in order to append to the circular buffer.
|
||||
// First frame after SetData, this will be equal to the buffer size, and the partial packet at the end
|
||||
// will actually be located at the start of the buffer (see the end of SetData for how it gets moved).
|
||||
const int writePos = info.streamOff + info.streamDataByte;
|
||||
if (writePos > lastPacketStart) {
|
||||
// The buffered data wraps around. This also applies at the first frame after SetData.
|
||||
const int distanceToEnd = info.bufferByte - info.streamOff;
|
||||
// Round it down to even packets.
|
||||
const int firstPart = RoundDownToMultiple(distanceToEnd, info.sampleSize);
|
||||
const int secondPart = info.streamDataByte - firstPart;
|
||||
*writePtr = info.buffer + secondPart;
|
||||
// OK, now to compute how much space we have.
|
||||
_dbg_assert_(secondPart <= info.streamOff);
|
||||
const int spaceLeft = info.streamOff - secondPart;
|
||||
*bytesToRead = std::min(spaceLeft, bytesLeftInFile);
|
||||
} else {
|
||||
*writePtr = info.buffer + info.dataOff;
|
||||
*bytesToRead = std::min(bytesLeft, bufferSpace);
|
||||
// We always start aligned at the start of the buffer. So, when computing the space left,
|
||||
// we just shrink the buffer so it's an even number of frames, then compute the free space.
|
||||
const int spaceLeft = RoundDownToMultiple(info.bufferByte, info.sampleSize) - writePos;
|
||||
*writePtr = info.buffer + writePos;
|
||||
*bytesToRead = std::min(spaceLeft, bytesLeftInFile);
|
||||
}
|
||||
|
||||
*readFileOffset = fileOffset;
|
||||
break;
|
||||
}
|
||||
|
@ -378,11 +397,10 @@ u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish,
|
|||
info.decodePos += samplesToWrite;
|
||||
|
||||
// If we reached the end of the buffer, move the cursor back to the start.
|
||||
// SetData takes care of any split packet.
|
||||
// SetData takes care of any split packet on the first lap (On other laps, no split packets
|
||||
// happen).
|
||||
if (AtracStatusIsStreaming(info.state) && info.streamOff + info.sampleSize > info.bufferByte) {
|
||||
// Check that we're on the first lap. Should only happen on the first lap around.
|
||||
_dbg_assert_(info.curOff - info.sampleSize < info.bufferByte);
|
||||
INFO_LOG(Log::ME, "Hit the buffer wrap.");
|
||||
INFO_LOG(Log::ME, "Hit the stream buffer wrap point (decoding).");
|
||||
info.streamOff = 0;
|
||||
}
|
||||
|
||||
|
@ -487,8 +505,9 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer
|
|||
|
||||
// We need to handle wrapping the overshot partial packet at the end. Let's start by computing it.
|
||||
if (AtracStatusIsStreaming(info.state)) {
|
||||
int cutLen = (info.bufferByte - info.curOff) % info.sampleSize;
|
||||
int cutRest = info.sampleSize - cutLen;
|
||||
// curOff also works (instead of streamOff) of course since it's also packet aligned, unlike the buffer size.
|
||||
const int cutLen = (info.bufferByte - info.streamOff) % info.sampleSize;
|
||||
const int cutRest = info.sampleSize - cutLen;
|
||||
|
||||
// Then, let's copy it.
|
||||
if (cutLen > 0) {
|
||||
|
|
|
@ -75,7 +75,7 @@ struct SceAtracIdInfo {
|
|||
u32_le curOff; // 32
|
||||
u32_le dataEnd; // 36
|
||||
s32_le loopNum; // 40
|
||||
u32_le streamDataByte; // 44
|
||||
u32_le streamDataByte; // 44 // Amount of queued data.
|
||||
u32_le streamOff; // Previously unk48. this appears to possibly be the offset inside the buffer for streaming.
|
||||
u32_le unk52;
|
||||
u32_le buffer; // 56
|
||||
|
|
Loading…
Add table
Reference in a new issue