diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index 1ce2aea597..3cfad06b3d 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -217,7 +217,7 @@ void Atrac::WriteContextToPSPMem() { context->info.endSample = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra(); context->info.dataEnd = track_.fileSize; context->info.curOff = first_.fileoffset; - context->info.decodePos = DecodePosBySample(currentSample_); + context->info.decodePos = track_.DecodePosBySample(currentSample_); context->info.streamDataByte = first_.size - track_.dataOff; u8 *buf = (u8 *)context; @@ -537,7 +537,7 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { first_.offset = 0; first_.writableBytes = 0; } else { - readOffset = FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + readOffset = track_.FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); } } @@ -592,7 +592,7 @@ void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) { // This is because we're filling the buffer start to finish, not streaming. bufferInfo->first.writePosPtr = first_.addr + first_.size; bufferInfo->first.writableBytes = track_.fileSize - first_.size; - int minWriteBytes = FileOffsetBySample(sample) - first_.size; + int minWriteBytes = track_.FileOffsetBySample(sample) - first_.size; if (minWriteBytes > 0) { bufferInfo->first.minWriteBytes = minWriteBytes; } else { @@ -601,7 +601,7 @@ void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) { bufferInfo->first.filePos = first_.size; } else { // This is without the sample offset. The file offset also includes the previous batch of samples? - int sampleFileOffset = FileOffsetBySample(sample - track_.firstSampleOffset - track_.SamplesPerFrame()); + int sampleFileOffset = track_.FileOffsetBySample(sample - track_.firstSampleOffset - track_.SamplesPerFrame()); // Update the writable bytes. When streaming, this is just the number of bytes until the end. const u32 bufSizeAligned = (bufferMaxSize_ / track_.bytesPerFrame) * track_.bytesPerFrame; @@ -688,7 +688,7 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, } u32 Atrac::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) { - u32 secondFileOffset = FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); + u32 secondFileOffset = track_.FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); u32 desiredSize = track_.fileSize - secondFileOffset; // 3 seems to be the number of frames required to handle a loop. @@ -713,7 +713,7 @@ int Atrac::GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) { return hleLogWarning(ME, ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED, "not needed"); } - *fileOffset = FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); + *fileOffset = track_.FileOffsetBySample(track_.loopEndSample - track_.firstSampleOffset); *desiredSize = track_.fileSize - *fileOffset; return hleLogSuccessI(ME, 0); } @@ -728,6 +728,26 @@ void Atrac::GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset *readOffset = calculatedReadOffset; } +void Atrac::UpdateBufferState() { + if (bufferMaxSize_ >= track_.fileSize) { + if (first_.size < track_.fileSize) { + // The buffer is big enough, but we don't have all the data yet. + bufferState_ = ATRAC_STATUS_HALFWAY_BUFFER; + } else { + bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; + } + } else { + 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 (track_.loopEndSample == track_.endSample + track_.firstSampleOffset + (int)FirstOffsetExtra()) { + bufferState_ = ATRAC_STATUS_STREAMED_LOOP_FROM_END; + } else { + bufferState_ = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER; + } + } +} + int Atrac::AddStreamData(u32 bytesToAdd) { u32 readOffset; CalculateStreamInfo(&readOffset); @@ -819,7 +839,7 @@ void Atrac::SeekToSample(int sample) { int offsetSamples = track_.firstSampleOffset + FirstOffsetExtra(); adjust = -(int)(offsetSamples % track_.SamplesPerFrame()); } - const u32 off = FileOffsetBySample(sample + adjust); + const u32 off = track_.FileOffsetBySample(sample + adjust); const u32 backfill = track_.bytesPerFrame * 2; const u32 start = off - track_.dataOff < backfill ? track_.dataOff : off - backfill; @@ -837,7 +857,7 @@ int Atrac::RemainingFrames() const { return PSP_ATRAC_ALLDATA_IS_ON_MEMORY; } - u32 currentFileOffset = FileOffsetBySample(currentSample_ - track_.SamplesPerFrame() + FirstOffsetExtra()); + u32 currentFileOffset = track_.FileOffsetBySample(currentSample_ - track_.SamplesPerFrame() + FirstOffsetExtra()); if (first_.fileoffset >= track_.fileSize) { if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) { return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; @@ -921,7 +941,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i SeekToSample(currentSample_); bool gotFrame = false; - u32 off = FileOffsetBySample(currentSample_ - skipSamples); + u32 off = track_.FileOffsetBySample(currentSample_ - skipSamples); if (off < first_.size) { uint8_t *indata = BufferStart() + off; int bytesConsumed = 0; @@ -957,7 +977,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i if (!gotFrame && currentSample_ < track_.endSample) { // Never got a frame. We may have dropped a GHA frame or otherwise have a bug. // For now, let's try to provide an extra "frame" if possible so games don't infinite loop. - if (FileOffsetBySample(currentSample_) < track_.fileSize) { + if (track_.FileOffsetBySample(currentSample_) < track_.fileSize) { numSamples = std::min(maxSamples, track_.SamplesPerFrame()); u32 outBytes = numSamples * outputChannels_ * sizeof(s16); if (outbuf != nullptr) { @@ -970,7 +990,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i *SamplesNum = numSamples; // update current sample and decodePos currentSample_ += numSamples; - decodePos_ = DecodePosBySample(currentSample_); + decodePos_ = track_.DecodePosBySample(currentSample_); ConsumeFrame(); @@ -986,11 +1006,11 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i } if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { // Whatever bytes we have left were added from the loop. - u32 loopOffset = FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + u32 loopOffset = track_.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(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); + first_.fileoffset = track_.FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2); } } } else if (hitEnd) { diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 52fb6d7acc..5fa111bc39 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -141,6 +141,16 @@ struct Track { bitrate = (bitrate + 511) >> 10; } + u32 DecodePosBySample(int sample) const { + return (u32)(firstSampleOffset + sample / (int)SamplesPerFrame() * bytesPerFrame); + } + + u32 FileOffsetBySample(int sample) const { + int offsetSample = sample + firstSampleOffset; + int frameOffset = offsetSample / (int)SamplesPerFrame(); + return (u32)(dataOff + bytesPerFrame + frameOffset * bytesPerFrame); + } + void AnalyzeReset() { endSample = -1; loopinfo.clear(); @@ -157,20 +167,9 @@ int AnalyzeAtracTrack(u32 addr, u32 size, Track *track); class AtracBase { public: virtual ~AtracBase() {} - virtual void UpdateBufferState() = 0; virtual void DoState(PointerWrap &p) = 0; - u32 DecodePosBySample(int sample) const { - return (u32)(track_.firstSampleOffset + sample / (int)track_.SamplesPerFrame() * track_.bytesPerFrame); - } - - u32 FileOffsetBySample(int sample) const { - int offsetSample = sample + track_.firstSampleOffset; - int frameOffset = offsetSample / (int)track_.SamplesPerFrame(); - return (u32)(track_.dataOff + track_.bytesPerFrame + frameOffset * track_.bytesPerFrame); - } - const Track &GetTrack() const { return track_; } @@ -179,21 +178,11 @@ public: return track_; } - int Bitrate() const { - return track_.bitrate; - } - int Channels() const { - return track_.channels; - } - int GetOutputChannels() const { return outputChannels_; } int atracID_ = -1; - u16 outputChannels_ = 2; - int loopNum_ = 0; - Track track_{}; PSPPointer context_{}; @@ -201,15 +190,19 @@ public: return bufferState_; } + int LoopNum() const { + return loopNum_; + } u32 CodecType() const { return track_.codecType; } - AudioDecoder *GetDecoder() const { + AudioDecoder *Decoder() const { return decoder_; } u32 FirstOffsetExtra() const { return ::FirstOffsetExtra(track_.codecType); } + void CreateDecoder(); virtual uint32_t CurBufferAddress(int adjust = 0) const = 0; @@ -232,8 +225,6 @@ public: virtual int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) = 0; virtual u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0; virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) = 0; - virtual void ForceSeekToSample(int sample) = 0; - virtual void SeekToSample(int sample) = 0; virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) = 0; virtual u32 GetNextSamples() = 0; virtual void InitLowLevel(u32 paramsAddr, bool jointStereo) = 0; @@ -241,6 +232,10 @@ public: protected: virtual void AnalyzeReset() = 0; + Track track_{}; + u16 outputChannels_ = 2; + int loopNum_ = 0; + // TODO: Save the internal state of this, now technically possible. AudioDecoder *decoder_ = nullptr; AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; @@ -251,30 +246,9 @@ public: ~Atrac() { ResetData(); } - void ResetData(); - - virtual void UpdateBufferState() { - if (bufferMaxSize_ >= track_.fileSize) { - if (first_.size < track_.fileSize) { - // The buffer is big enough, but we don't have all the data yet. - bufferState_ = ATRAC_STATUS_HALFWAY_BUFFER; - } else { - bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - } - } else { - 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 (track_.loopEndSample == track_.endSample + track_.firstSampleOffset + (int)FirstOffsetExtra()) { - bufferState_ = ATRAC_STATUS_STREAMED_LOOP_FROM_END; - } else { - bufferState_ = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER; - } - } - } uint32_t CurBufferAddress(int adjust = 0) const override { - u32 off = FileOffsetBySample(currentSample_ + adjust); + u32 off = track_.FileOffsetBySample(currentSample_ + adjust); if (off < first_.size && ignoreDataBuf_) { return first_.addr + off; } @@ -309,22 +283,18 @@ public: int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) override; u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override; int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) override; - void ForceSeekToSample(int sample) override; - void SeekToSample(int sample) override; u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override; u32 GetNextSamples() override; void InitLowLevel(u32 paramsAddr, bool jointStereo); - // Indicates that the dataBuf_ array should not be used. - u8 *dataBuf_ = nullptr; - - InputBuffer first_{}; - InputBuffer second_{}; - protected: void AnalyzeReset(); private: + void UpdateBufferState(); + void ResetData(); + void SeekToSample(int sample); + void ForceSeekToSample(int sample); u32 StreamBufferEnd() const { // The buffer is always aligned to a frame in size, not counting an optional header. // The header will only initially exist after the data is first set. @@ -334,6 +304,11 @@ private: void ConsumeFrame(); void CalculateStreamInfo(u32 *readOffset); + InputBuffer first_{}; + InputBuffer second_{}; + + u8 *dataBuf_ = nullptr; + // Indicates that the dataBuf_ array should not be used. bool ignoreDataBuf_ = false; int currentSample_ = 0; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 802971958a..775d21ec28 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -176,7 +176,7 @@ static u32 sceAtracGetAtracID(int codecType) { } AtracBase *atrac = new Atrac(); - atrac->track_.codecType = codecType; + atrac->GetTrackMut().codecType = codecType; int atracID = createAtrac(atrac); if (atracID < 0) { delete atrac; @@ -310,7 +310,7 @@ static u32 sceAtracGetBitrate(int atracID, u32 outBitrateAddr) { atrac->GetTrackMut().UpdateBitrate(); if (Memory::IsValidAddress(outBitrateAddr)) { - Memory::WriteUnchecked_U32(atrac->Bitrate(), outBitrateAddr); + Memory::WriteUnchecked_U32(atrac->GetTrack().bitrate, outBitrateAddr); return hleLogSuccessI(ME, 0); } else { return hleLogError(ME, 0, "invalid address"); @@ -326,7 +326,7 @@ static u32 sceAtracGetChannel(int atracID, u32 channelAddr) { } if (Memory::IsValidAddress(channelAddr)){ - Memory::WriteUnchecked_U32(atrac->Channels(), channelAddr); + Memory::WriteUnchecked_U32(atrac->GetTrack().channels, channelAddr); return hleLogSuccessI(ME, 0); } else { return hleLogError(ME, 0, "invalid address"); @@ -342,7 +342,7 @@ static u32 sceAtracGetLoopStatus(int atracID, u32 loopNumAddr, u32 statusAddr) { } if (Memory::IsValidAddress(loopNumAddr)) - Memory::WriteUnchecked_U32(atrac->loopNum_, loopNumAddr); + Memory::WriteUnchecked_U32(atrac->LoopNum(), loopNumAddr); // return audio's loopinfo in at3 file if (Memory::IsValidAddress(statusAddr)) { if (atrac->GetTrack().loopinfo.size() > 0) @@ -603,7 +603,7 @@ static u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) { return ret; } - if (atrac->track_.codecType != atracContextTypes[atracID]) { + if (atrac->GetTrack().codecType != atracContextTypes[atracID]) { // TODO: Should this not change the buffer size? return hleReportError(ME, ATRAC_ERROR_WRONG_CODECTYPE, "atracID uses different codec type than data"); } @@ -883,7 +883,7 @@ struct At3HeaderMap { u8 jointStereo; bool Matches(const AtracBase *at) const { - return bytes == at->GetTrack().BytesPerFrame() && channels == at->Channels(); + return bytes == at->GetTrack().BytesPerFrame() && channels == at->GetTrack().channels; } }; @@ -919,7 +919,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { } } if (!found) { - ERROR_LOG_REPORT(ME, "AT3 header map lacks entry for bpf: %i channels: %i", atrac->GetTrack().BytesPerFrame(), atrac->Channels()); + ERROR_LOG_REPORT(ME, "AT3 header map lacks entry for bpf: %i channels: %i", atrac->GetTrack().BytesPerFrame(), atrac->GetTrack().channels); // TODO: Should we return an error code for these values? } } @@ -949,7 +949,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo int bytesConsumed = 0; int bytesWritten = 0; - atrac->GetDecoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, 2, outp, &bytesWritten); + atrac->Decoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, 2, outp, &bytesWritten); *srcConsumed = bytesConsumed; *outWritten = bytesWritten;