Refactor CurrentSample and ResetPlayPosition

This commit is contained in:
Henrik Rydgård 2025-03-16 11:18:15 +01:00
parent fd9564166b
commit a3b43d8283
6 changed files with 54 additions and 41 deletions

View file

@ -554,6 +554,16 @@ int Atrac::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSamp
return 0;
}
int Atrac::GetNextDecodePosition(int *pos) const {
if (currentSample_ >= track_.endSample) {
*pos = 0;
return SCE_ERROR_ATRAC_ALL_DATA_DECODED;
} else {
*pos = currentSample_;
return 0;
}
}
void Atrac::CalculateStreamInfo(u32 *outReadOffset) {
u32 readOffset = first_.fileoffset;
if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) {
@ -860,7 +870,7 @@ u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
}
u32 Atrac::GetNextSamples() {
if (CurrentSample() >= track_.endSample) {
if (currentSample_ >= track_.endSample) {
return 0;
}
@ -1114,16 +1124,24 @@ void AtracBase::SetLoopNum(int loopNum) {
WriteContextToPSPMem();
}
u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) {
int Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) {
*delay = false;
if (BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && SecondBufferSize() == 0) {
return SCE_ERROR_ATRAC_SECOND_BUFFER_NEEDED;
} else if ((u32)sample + GetTrack().firstSampleOffset > (u32)GetTrack().endSample + GetTrack().firstSampleOffset) {
// NOTE: Above we have to add firstSampleOffset to both sides - we seem to rely on wraparound.
return SCE_ERROR_ATRAC_BAD_SAMPLE;
}
// Reuse the same calculation as before.
AtracResetBufferInfo bufferInfo;
GetResetBufferInfo(&bufferInfo, sample);
if ((u32)bytesWrittenFirstBuf < bufferInfo.first.minWriteBytes || (u32)bytesWrittenFirstBuf > bufferInfo.first.writableBytes) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_FIRST_RESET_SIZE, "first byte count not in valid range");
return SCE_ERROR_ATRAC_BAD_FIRST_RESET_SIZE;
}
if ((u32)bytesWrittenSecondBuf < bufferInfo.second.minWriteBytes || (u32)bytesWrittenSecondBuf > bufferInfo.second.writableBytes) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_SECOND_RESET_SIZE, "second byte count not in valid range");
return SCE_ERROR_ATRAC_BAD_SECOND_RESET_SIZE;
}
if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) {
@ -1146,7 +1164,9 @@ u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrit
}
} else {
if (bufferInfo.first.filePos > track_.fileSize) {
return hleDelayResult(hleLogError(Log::ME, SCE_ERROR_ATRAC_API_FAIL, "invalid file position"), "reset play pos", 200);
*delay = true;
// The decoder failed during skip-frame operation.
return SCE_ERROR_ATRAC_API_FAIL;
}
// Move the offset to the specified position.
@ -1171,7 +1191,7 @@ u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrit
}
WriteContextToPSPMem();
return hleNoLog(0);
return 0;
}
void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) {

View file

@ -220,7 +220,7 @@ public:
void CreateDecoder();
virtual int CurrentSample() const = 0;
virtual int GetNextDecodePosition(int *pos) const = 0;
virtual int RemainingFrames() const = 0;
virtual u32 SecondBufferSize() const = 0;
virtual int Bitrate() const = 0;
@ -236,7 +236,7 @@ public:
virtual int AddStreamData(u32 bytesToAdd) = 0;
virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0;
virtual void SetLoopNum(int loopNum);
virtual u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) = 0;
virtual int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) = 0;
virtual int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) = 0;
virtual int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) = 0;
@ -282,9 +282,7 @@ public:
int Analyze(u32 addr, u32 size) override;
int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override;
int CurrentSample() const override {
return currentSample_;
}
int GetNextDecodePosition(int *pos) const override;
int RemainingFrames() const override;
u32 SecondBufferSize() const override {
return second_.size;
@ -315,7 +313,7 @@ public:
// Notify the player that the user has written some new data.
int AddStreamData(u32 bytesToAdd) override;
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override;
int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override;
int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override;
int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override;
u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;

View file

@ -110,7 +110,8 @@ u32 Atrac2::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
return 0;
}
u32 Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) {
int Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) {
*delay = false;
return 0;
}

View file

@ -14,7 +14,7 @@ public:
int Analyze(u32 addr, u32 size) override;
int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override;
int CurrentSample() const override { return currentSample_; }
int GetNextDecodePosition(int *pos) const { return 0; }
int RemainingFrames() const override;
int LoopStatus() const override { return 0; }
int Bitrate() const override { return 0; }
@ -24,7 +24,7 @@ public:
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
int AddStreamData(u32 bytesToAdd) override;
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override;
int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override;
int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override;
int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override;
u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;

View file

@ -406,17 +406,18 @@ static u32 sceAtracGetNextDecodePosition(int atracID, u32 outposAddr) {
return hleLogError(Log::ME, err);
}
if (Memory::IsValidAddress(outposAddr)) {
if (atrac->CurrentSample() >= atrac->GetTrack().endSample) {
Memory::WriteUnchecked_U32(0, outposAddr);
return hleLogDebug(Log::ME, SCE_ERROR_ATRAC_ALL_DATA_DECODED, "all data decoded - beyond endSample");
} else {
Memory::WriteUnchecked_U32(atrac->CurrentSample(), outposAddr);
return hleLogDebug(Log::ME, 0);
}
} else {
int pos = 0;
int ret = atrac->GetNextDecodePosition(&pos);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (!Memory::IsValidAddress(outposAddr)) {
return hleLogError(Log::ME, 0, "invalid address");
}
Memory::WriteUnchecked_U32(pos, outposAddr);
return hleLogDebug(Log::ME, 0);
}
static u32 sceAtracGetNextSample(int atracID, u32 outNAddr) {
@ -547,20 +548,9 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi
return hleLogError(Log::ME, err);
}
if (atrac->BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->SecondBufferSize() == 0) {
return hleReportError(Log::ME, SCE_ERROR_ATRAC_SECOND_BUFFER_NEEDED, "no second buffer");
} else if ((u32)sample + atrac->GetTrack().firstSampleOffset > (u32)atrac->GetTrack().endSample + atrac->GetTrack().firstSampleOffset) {
// NOTE: Above we have to add firstSampleOffset to both sides - we seem to rely on wraparound.
return hleLogWarning(Log::ME, SCE_ERROR_ATRAC_BAD_SAMPLE, "invalid sample position");
}
u32 res = atrac->ResetPlayPosition(sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf);
if (res != 0) {
// Already logged.
return res;
}
return hleDelayResult(0, "reset play pos", 3000);
bool delay = false;
int res = atrac->ResetPlayPosition(sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf, &delay);
return hleDelayResult(hleLogDebugOrError(Log::ME, res), "reset play pos", 3000 + delay ? 200 : 0);
}
static int _AtracSetData(int atracID, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) {

View file

@ -999,7 +999,9 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) {
ImGui::TableNextColumn();
ImGui::Text("%d", ctx->GetOutputChannels());
ImGui::TableNextColumn();
ImGui::Text("%d", ctx->CurrentSample());
int pos;
ctx->GetNextDecodePosition(&pos);
ImGui::Text("%d", pos);
ImGui::TableNextColumn();
ImGui::Text("%d", ctx->RemainingFrames());
}
@ -1014,9 +1016,11 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) {
char header[32];
snprintf(header, sizeof(header), "Atrac context %d", cfg.selectedAtracCtx);
if (ctx && ImGui::CollapsingHeader(header, ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ProgressBar((float)ctx->CurrentSample() / (float)ctx->GetTrack().endSample, ImVec2(200.0f, 0.0f));
int pos;
ctx->GetNextDecodePosition(&pos);
ImGui::ProgressBar((float)pos / (float)ctx->GetTrack().endSample, ImVec2(200.0f, 0.0f));
ImGui::Text("Status: %s", AtracStatusToString(ctx->BufferState()));
ImGui::Text("cur/end sample: %d/%d", ctx->CurrentSample(), ctx->GetTrack().endSample);
ImGui::Text("cur/end sample: %d/%d", pos, ctx->GetTrack().endSample);
ImGui::Text("ctx addr: "); ImGui::SameLine(); ImClickableValue("addr", ctx->Decoder()->GetCtxPtr(), control, ImCmd::SHOW_IN_MEMORY_VIEWER);
ImGui::Text("loop: %d", ctx->LoopNum());
}