More work on atrac-through-sas

This commit is contained in:
Henrik Rydgård 2025-03-25 18:37:30 +01:00
parent 172e54286e
commit 5ea7729f66
4 changed files with 74 additions and 38 deletions

View file

@ -44,6 +44,12 @@ struct AtracSasStreamState {
int fileOffset = 0;
int curBuffer = 0;
bool isStreaming = false;
int CurPos() const {
int retval = fileOffset - bufSize[curBuffer] + streamOffset;
_dbg_assert_(retval >= 0);
return retval;
}
};
const int PSP_ATRAC_ALLDATA_IS_ON_MEMORY = -1;

View file

@ -1064,6 +1064,11 @@ int Atrac2::EnqueueForSas(u32 address, u32 ptr) {
return SCE_SAS_ERROR_ATRAC3_ALREADY_QUEUED;
}
if (address == 0 && ptr == 0) {
INFO_LOG(Log::ME, "Caller tries to send us a zero buffer. Something went wrong.");
}
INFO_LOG(Log::ME, "Second buffer updated to %08x, sz: %08x", address, ptr);
info.secondBuffer = address;
info.secondBufferByte = ptr;
return 0;
@ -1080,7 +1085,7 @@ void Atrac2::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
sas_.bufPtr[0] = info.buffer;
sas_.bufSize[0] = info.bufferByte - info.streamOff;
sas_.streamOffset = 0;
sas_.fileOffset = 0;
sas_.fileOffset = info.bufferByte;
}
u8 assembly[1000];
@ -1091,15 +1096,15 @@ void Atrac2::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
int bytesConsumed = 0;
bool decodeResult = decoder_->Decode(srcData, info.sampleSize, &bytesConsumed, 1, dstData, bytesWritten);
if (!decodeResult) {
ERROR_LOG(Log::ME, "SAS failed to decode packet");
ERROR_LOG(Log::ME, "SAS failed to decode regular packet");
}
sas_.streamOffset += bytesConsumed;
sas_.fileOffset += bytesConsumed;
} else if (sas_.isStreaming) {
// TODO: Do we need special handling for the first buffer, since SetData will wrap around that packet? I think yes!
WARN_LOG(Log::ME, "Streaming, and hit the end of buffer %d, switching over.", sas_.curBuffer);
WARN_LOG(Log::ME, "Streaming, and hit the end of buffer %d", sas_.curBuffer);
// Compute the part sizes using the current size.
int part1Size = sas_.bufSize[sas_.curBuffer] - sas_.streamOffset;
int part2Size = info.sampleSize - part1Size;
_dbg_assert_(part1Size >= 0);
@ -1133,11 +1138,24 @@ void Atrac2::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
// Switch to the other buffer.
sas_.curBuffer ^= 1;
WARN_LOG(Log::ME, "Switching over to buffer %d, updating buffer to %08x, sz: %08x", sas_.curBuffer, info.secondBuffer, info.secondBufferByte);
sas_.bufPtr[sas_.curBuffer] = info.secondBuffer;
sas_.bufSize[sas_.curBuffer] = info.secondBufferByte;
sas_.fileOffset += info.secondBufferByte;
sas_.streamOffset = part2Size;
info.secondBuffer = 0xFFFFFFFF; // Signal to the caller that we accept a new next buffer. NOTE: This
// If we'll reach the end during this buffer, set second buffer to 0, signaling that we don't need more data.
if (sas_.fileOffset >= info.fileDataEnd) {
// We've reached the end.
info.secondBuffer = 0;
WARN_LOG(Log::ME, "%08x >= %08x: Reached the end.", sas_.fileOffset, info.fileDataEnd);
} else {
// Signal to the caller that we accept a new next buffer.
info.secondBuffer = 0xFFFFFFFF;
WARN_LOG(Log::ME, "Signalling for more data (%08x < %08x).", sas_.fileOffset, info.fileDataEnd);
}
// Copy the second half (or if part1Size == 0, the whole packet) to the assembly buffer.
Memory::Memcpy(assembly + part1Size, sas_.bufPtr[sas_.curBuffer], part2Size);
@ -1145,9 +1163,8 @@ void Atrac2::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
const u8 *srcData = assembly;
int bytesConsumed = 0;
bool decodeResult = decoder_->Decode(srcData, info.sampleSize, &bytesConsumed, 1, dstData, bytesWritten);
sas_.fileOffset += bytesConsumed;
if (!decodeResult) {
ERROR_LOG(Log::ME, "SAS failed to decode packet");
ERROR_LOG(Log::ME, "SAS failed to decode assembled packet");
}
}

View file

@ -689,15 +689,12 @@ static u32 __sceSasConcatenateATRAC3(u32 core, int voiceNum, u32 atrac3DataAddr,
return hleLogWarning(Log::sceSas, SCE_SAS_ERROR_INVALID_VOICE, "invalid voicenum");
}
DEBUG_LOG_REPORT_ONCE(concatAtrac3, Log::sceSas, "__sceSasConcatenateATRAC3(%08x, %i, %08x, %i)", core, voiceNum, atrac3DataAddr, atrac3DataLength);
__SasDrain();
SasVoice &v = sas->voices[voiceNum];
if (Memory::IsValidAddress(atrac3DataAddr)) {
v.atrac3.Concatenate(atrac3DataAddr, atrac3DataLength);
}
DEBUG_LOG_REPORT_ONCE(concatAtrac3, Log::sceSas, "__sceSasConcatenateATRAC3(%08x, %i, %08x, %i)", core, voiceNum, atrac3DataAddr, atrac3DataLength);
SasVoice &v = sas->voices[voiceNum];
v.atrac3.Concatenate(atrac3DataAddr, atrac3DataLength);
return hleLogDebug(Log::sceSas, 0);
}

View file

@ -1028,14 +1028,14 @@ 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)) {
int pos;
ctx->GetNextDecodePosition(&pos);
int endSample, loopStart, loopEnd;
ctx->GetSoundSample(&endSample, &loopStart, &loopEnd);
ImGui::ProgressBar((float)pos / (float)endSample, ImVec2(200.0f, 0.0f));
ImGui::Text("Status: %s", AtracStatusToString(ctx->BufferState()));
if (ctx->BufferState() <= ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) {
ImGui::Text("cur/end sample: %d/%d/%d", pos, endSample);
bool isNormal = AtracStatusIsNormal(ctx->BufferState());
if (isNormal) {
int pos;
ctx->GetNextDecodePosition(&pos);
int endSample, loopStart, loopEnd;
ctx->GetSoundSample(&endSample, &loopStart, &loopEnd);
ImGui::ProgressBar((float)pos / (float)endSample, ImVec2(200.0f, 0.0f));
ImGui::Text("Status: %s", AtracStatusToString(ctx->BufferState())); ImGui::Text("cur/end sample: %d/%d/%d", pos, endSample);
}
if (ctx->context_.IsValid()) {
ImGui::Text("ctx addr: ");
@ -1044,25 +1044,41 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) {
}
if (ctx->context_.IsValid() && ctx->GetContextVersion() >= 2) {
const auto &info = ctx->context_->info;
ImGui::Text("Buffer: (size: %d / %08x) Frame: %d", info.bufferByte, info.bufferByte, info.sampleSize);
ImGui::SameLine();
ImClickableValue("buffer", info.buffer, control, ImCmd::SHOW_IN_MEMORY_VIEWER);
if (info.secondBuffer || info.secondBufferByte) {
ImGui::Text("Second: (size: %d / %08x)", info.secondBufferByte, info.secondBufferByte);
if (isNormal) {
ImGui::Text("Buffer: (size: %d / %08x) Frame: %d", info.bufferByte, info.bufferByte, info.sampleSize);
ImGui::SameLine();
ImClickableValue("second", info.secondBuffer, control, ImCmd::SHOW_IN_MEMORY_VIEWER);
ImClickableValue("buffer", info.buffer, control, ImCmd::SHOW_IN_MEMORY_VIEWER);
if (info.secondBuffer || info.secondBufferByte) {
ImGui::Text("Second: (size: %d / %08x)", info.secondBufferByte, info.secondBufferByte);
ImGui::SameLine();
ImClickableValue("second", info.secondBuffer, control, ImCmd::SHOW_IN_MEMORY_VIEWER);
}
ImGui::Text("Data: %d/%d", info.dataOff, info.fileDataEnd);
if (info.state != ATRAC_STATUS_STREAMED_WITHOUT_LOOP) {
ImGui::Text("LoopNum: %d (%d-%d)", info.loopNum, info.loopStart, info.loopEnd);
}
ImGui::Text("DecodePos: %d EndSample: %d", info.decodePos, info.fileDataEnd);
if (AtracStatusIsStreaming(info.state)) {
ImGui::Text("Stream: offset %d, streamDataBytes: %d", info.streamOff, info.streamDataByte);
}
ImGui::Text("numFrame: %d curBuffer: %d streamOff2: %d", info.numSkipFrames, info.curBuffer, info.secondStreamOff);
} else if (ctx->BufferState() == ATRAC_STATUS_FOR_SCESAS) {
// A different set of state!
const AtracSasStreamState *sas = ctx->StreamStateForSas();
if (sas) {
ImGui::ProgressBar((float)sas->CurPos() / (float)info.fileDataEnd, ImVec2(200.0f, 0.0f));
ImGui::ProgressBar((float)sas->streamOffset / (float)sas->bufSize[sas->curBuffer], ImVec2(200.0f, 0.0f));
ImGui::Text("Cur pos: %08x File offset: %08x File end: %08x%s", sas->CurPos(), sas->fileOffset, info.fileDataEnd, sas->fileOffset >= info.fileDataEnd ? " (END)" : "");
ImGui::Text("Second (next buffer): %08x (sz: %08x)", info.secondBuffer, info.secondBufferByte);
ImGui::Text("Cur buffer: %d (%08x, sz: %08x)", sas->curBuffer, sas->bufPtr[sas->curBuffer], sas->bufSize[sas->curBuffer]);
ImGui::Text("2nd buffer: %d (%08x, sz: %08x)", sas->curBuffer ^ 1, sas->bufPtr[sas->curBuffer ^ 1], sas->bufSize[sas->curBuffer ^ 1]);
ImGui::Text("Loop points: %08x, %08x", info.loopStart, info.loopEnd);
ImGui::TextUnformatted(sas->isStreaming ? "Streaming mode!" : "Non-streaming mode");
} else {
ImGui::Text("can't access sas state");
}
}
ImGui::Text("Data: %d/%d", info.dataOff, info.fileDataEnd);
if (info.state != ATRAC_STATUS_STREAMED_WITHOUT_LOOP) {
ImGui::Text("LoopNum: %d (%d-%d)", info.loopNum, info.loopStart, info.loopEnd);
}
ImGui::Text("DecodePos: %d EndSample: %d", info.decodePos, info.fileDataEnd);
if (AtracStatusIsStreaming(info.state)) {
ImGui::Text("Stream: offset %d, streamDataBytes: %d", info.streamOff, info.streamDataByte);
}
// Display unknown vars.
ImGui::Text("numFrame: %d curBuffer: %d streamOff2: %d", info.numSkipFrames, info.curBuffer, info.secondStreamOff);
} else {
} else {
ImGui::Text("loop: %d", ctx->LoopNum());
}
}