diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index eaa643aaaf..e686a5bcf5 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -96,14 +96,14 @@ void Atrac::DoState(PointerWrap &p) { Do(p, bitrate_); Do(p, track_.bytesPerFrame); - Do(p, loopinfo_); + Do(p, track_.loopinfo); if (s < 9) { int oldLoopInfoNum = 42; Do(p, oldLoopInfoNum); } - Do(p, loopStartSample_); - Do(p, loopEndSample_); + Do(p, track_.loopStartSample); + Do(p, track_.loopEndSample); Do(p, loopNum_); Do(p, context_); @@ -170,9 +170,9 @@ void Atrac::AnalyzeReset() { currentSample_ = 0; track_.endSample = -1; loopNum_ = 0; - loopinfo_.clear(); - loopStartSample_ = -1; - loopEndSample_ = -1; + track_.loopinfo.clear(); + track_.loopStartSample = -1; + track_.loopEndSample = -1; decodePos_ = 0; bufferPos_ = 0; channels_ = 2; @@ -202,8 +202,8 @@ void Atrac::WriteContextToPSPMem() { context->info.secondBufferByte = second_.size; context->info.codec = track_.codecType; context->info.loopNum = loopNum_; - context->info.loopStart = loopStartSample_ > 0 ? loopStartSample_ : 0; - context->info.loopEnd = loopEndSample_ > 0 ? loopEndSample_ : 0; + context->info.loopStart = track_.loopStartSample > 0 ? track_.loopStartSample : 0; + context->info.loopEnd = track_.loopEndSample > 0 ? track_.loopEndSample : 0; // Note that we read in the state when loading the atrac object, so it's safe // to update it back here all the time. Some games, like Sol Trigger, change it. @@ -371,19 +371,19 @@ int Atrac::Analyze(u32 addr, u32 size) { return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "bad checkNumLoops (%d)", checkNumLoops); } - loopinfo_.resize(checkNumLoops); + track->loopinfo.resize(checkNumLoops); u32 loopinfoAddr = addr + offset + 36; // The PSP only cares about the first loop start and end, it seems. // Most likely can skip the rest of this data, but it's not hurting anyone. for (int i = 0; i < checkNumLoops && 36 + (u32)i < chunkSize; i++, loopinfoAddr += 24) { - loopinfo_[i].cuePointID = Memory::Read_U32(loopinfoAddr); - loopinfo_[i].type = Memory::Read_U32(loopinfoAddr + 4); - loopinfo_[i].startSample = Memory::Read_U32(loopinfoAddr + 8); - loopinfo_[i].endSample = Memory::Read_U32(loopinfoAddr + 12); - loopinfo_[i].fraction = Memory::Read_U32(loopinfoAddr + 16); - loopinfo_[i].playCount = Memory::Read_U32(loopinfoAddr + 20); + track->loopinfo[i].cuePointID = Memory::Read_U32(loopinfoAddr); + track->loopinfo[i].type = Memory::Read_U32(loopinfoAddr + 4); + track->loopinfo[i].startSample = Memory::Read_U32(loopinfoAddr + 8); + track->loopinfo[i].endSample = Memory::Read_U32(loopinfoAddr + 12); + track->loopinfo[i].fraction = Memory::Read_U32(loopinfoAddr + 16); + track->loopinfo[i].playCount = Memory::Read_U32(loopinfoAddr + 20); - if (loopinfo_[i].startSample >= loopinfo_[i].endSample) { + if (track->loopinfo[i].startSample >= track->loopinfo[i].endSample) { return hleReportError(ME, ATRAC_ERROR_BAD_CODEC_PARAMS, "loop starts after it ends"); } } @@ -413,12 +413,12 @@ int Atrac::Analyze(u32 addr, u32 size) { } // set the loopStartSample_ and loopEndSample_ by loopinfo_ - if (loopinfo_.size() > 0) { - loopStartSample_ = loopinfo_[0].startSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust; - loopEndSample_ = loopinfo_[0].endSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust; + if (track->loopinfo.size() > 0) { + track->loopStartSample = track->loopinfo[0].startSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust; + track->loopEndSample = track->loopinfo[0].endSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust; } else { - loopStartSample_ = -1; - loopEndSample_ = -1; + track->loopStartSample = -1; + track->loopEndSample = -1; } // if there is no correct endsample, try to guess it @@ -428,7 +428,7 @@ int Atrac::Analyze(u32 addr, u32 size) { } track->endSample -= 1; - if (loopEndSample_ != -1 && loopEndSample_ > track->endSample + track->firstSampleOffset + (int)::FirstOffsetExtra(track->codecType)) { + if (track->loopEndSample != -1 && track->loopEndSample > track->endSample + track->firstSampleOffset + (int)::FirstOffsetExtra(track->codecType)) { return hleReportError(ME, ATRAC_ERROR_BAD_CODEC_PARAMS, "loop after end of data"); } @@ -536,7 +536,7 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { first_.offset = 0; first_.writableBytes = 0; } else { - readOffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + readOffset = FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); } } @@ -687,7 +687,7 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int successCode) { } u32 Atrac::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) { - u32 secondFileOffset = FileOffsetBySample(loopEndSample_ - track_.firstSampleOffset); + u32 secondFileOffset = FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); u32 desiredSize = track_.fileSize - secondFileOffset; // 3 seems to be the number of frames required to handle a loop. @@ -712,7 +712,7 @@ int Atrac::GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) { return hleLogWarning(ME, ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED, "not needed"); } - *fileOffset = FileOffsetBySample(loopEndSample_ - track_.firstSampleOffset); + *fileOffset = FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); *desiredSize = track_.fileSize - *fileOffset; return hleLogSuccessI(ME, 0); } @@ -752,7 +752,7 @@ int Atrac::AddStreamData(u32 bytesToAdd) { if (PSP_CoreParameter().compat.flags().AtracLoopHack && bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && RemainingFrames() > 2) { loopNum_++; - SeekToSample(loopStartSample_ - FirstOffsetExtra() - track_.firstSampleOffset); + SeekToSample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset); } return 0; @@ -843,7 +843,7 @@ int Atrac::RemainingFrames() const { if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) { return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; } - int loopEndAdjusted = loopEndSample_ - FirstOffsetExtra() - track_.firstSampleOffset; + int loopEndAdjusted = track_.loopEndSample - FirstOffsetExtra() - track_.firstSampleOffset; if (bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && currentSample_ > loopEndAdjusted) { // No longer looping in this case, outside the loop. return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; @@ -980,20 +980,20 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i int finishFlag = 0; // TODO: Verify. bool hitEnd = currentSample_ >= track_.endSample || (numSamples == 0 && first_.size >= track_.fileSize); - int loopEndAdjusted = loopEndSample_ - FirstOffsetExtra() - track_.firstSampleOffset; + int loopEndAdjusted = track_.loopEndSample - FirstOffsetExtra() - track_.firstSampleOffset; if ((hitEnd || currentSample_ > loopEndAdjusted) && loopNum != 0) { - SeekToSample(loopStartSample_ - FirstOffsetExtra() - track_.firstSampleOffset); + SeekToSample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset); if (bufferState_ != ATRAC_STATUS_FOR_SCESAS) { if (loopNum_ > 0) loopNum_--; } if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { // Whatever bytes we have left were added from the loop. - u32 loopOffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + u32 loopOffset = FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); // TODO: Hmm, need to manage the buffer better. But don't move fileoffset if we already have valid data. if (loopOffset > first_.fileoffset || loopOffset + bufferValidBytes_ < first_.fileoffset) { // Skip the initial frame at the start. - first_.fileoffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + first_.fileoffset = FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); } } } else if (hitEnd) { @@ -1014,10 +1014,12 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i void Atrac::SetLoopNum(int loopNum) { // Spammed in MHU loopNum_ = loopNum; - if (loopNum != 0 && loopinfo_.size() == 0) { + if (loopNum != 0 && track_.loopinfo.size() == 0) { // Just loop the whole audio - loopStartSample_ = track_.firstSampleOffset + FirstOffsetExtra(); - loopEndSample_ = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra(); + // This is a rare modification of track_ after the fact. + // Maybe we can get away with setting these by default. + track_.loopStartSample = track_.firstSampleOffset + FirstOffsetExtra(); + track_.loopEndSample = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra(); } WriteContextToPSPMem(); } diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 4b3b710a26..674ec9a973 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -113,6 +113,10 @@ struct Track { int firstSampleOffset; int endSample; + std::vector loopinfo; + int loopStartSample = -1; + int loopEndSample = -1; + // Input frame size int BytesPerFrame() const { return bytesPerFrame; @@ -139,10 +143,10 @@ struct Atrac { bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; } } else { - if (loopEndSample_ <= 0) { + if (track_.loopEndSample <= 0) { // There's no looping, but we need to stream the data in our buffer. bufferState_ = ATRAC_STATUS_STREAMED_WITHOUT_LOOP; - } else if (loopEndSample_ == track_.endSample + track_.firstSampleOffset + (int)FirstOffsetExtra()) { + } else if (track_.loopEndSample == track_.endSample + track_.firstSampleOffset + (int)FirstOffsetExtra()) { bufferState_ = ATRAC_STATUS_STREAMED_LOOP_FROM_END; } else { bufferState_ = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER; @@ -193,10 +197,6 @@ struct Atrac { u16 outputChannels_ = 2; int currentSample_ = 0; - - std::vector loopinfo_; - int loopStartSample_ = -1; - int loopEndSample_ = -1; int loopNum_ = 0; InputBuffer first_{}; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 8e59219ac3..3ee875cf4e 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -345,7 +345,7 @@ static u32 sceAtracGetLoopStatus(int atracID, u32 loopNumAddr, u32 statusAddr) { Memory::WriteUnchecked_U32(atrac->loopNum_, loopNumAddr); // return audio's loopinfo in at3 file if (Memory::IsValidAddress(statusAddr)) { - if (atrac->loopinfo_.size() > 0) + if (atrac->GetTrack().loopinfo.size() > 0) Memory::WriteUnchecked_U32(1, statusAddr); else Memory::WriteUnchecked_U32(0, statusAddr); @@ -478,10 +478,10 @@ static u32 sceAtracGetSoundSample(int atracID, u32 outEndSampleAddr, u32 outLoop *outEndSample = atrac->GetTrack().endSample; auto outLoopStart = PSPPointer::Create(outLoopStartSampleAddr); if (outLoopStart.IsValid()) - *outLoopStart = atrac->loopStartSample_ == -1 ? -1 : atrac->loopStartSample_ - atrac->track_.firstSampleOffset - atrac->FirstOffsetExtra(); + *outLoopStart = atrac->GetTrack().loopStartSample == -1 ? -1 : atrac->GetTrack().loopStartSample - atrac->GetTrack().firstSampleOffset - atrac->FirstOffsetExtra(); auto outLoopEnd = PSPPointer::Create(outLoopEndSampleAddr); if (outLoopEnd.IsValid()) - *outLoopEnd = atrac->loopEndSample_ == -1 ? -1 : atrac->loopEndSample_ - atrac->track_.firstSampleOffset - atrac->FirstOffsetExtra(); + *outLoopEnd = atrac->GetTrack().loopEndSample == -1 ? -1 : atrac->GetTrack().loopEndSample - atrac->GetTrack().firstSampleOffset - atrac->FirstOffsetExtra(); if (!outEndSample.IsValid() || !outLoopStart.IsValid() || !outLoopEnd.IsValid()) { return hleReportError(ME, 0, "invalid address"); @@ -669,7 +669,7 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { // Already logged. return err; } - if (atrac->loopinfo_.size() == 0) { + if (atrac->GetTrack().loopinfo.size() == 0) { return hleLogError(ME, ATRAC_ERROR_NO_LOOP_INFORMATION, "no loop information"); }