Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atrac3+: Try to work around Code Lyoko issue #20005

Merged
merged 1 commit into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Core/HLE/AtracCtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ void AtracBase::CreateDecoder() {
delete decoder_;
}

// First, init the standalone decoder. Only used for low-level-decode initially, but simple.
// First, init the standalone decoder.
if (track_.codecType == PSP_MODE_AT_3) {
// We don't pull this from the RIFF so that we can support OMA also.
uint8_t extraData[14]{};
Expand Down Expand Up @@ -650,6 +650,10 @@ void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) {
int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) {
outputChannels_ = outputChannels;

if (outputChannels != track_.channels) {
WARN_LOG(Log::ME, "outputChannels %d doesn't match track_.channels %d", outputChannels, track_.channels);
}

first_.addr = buffer;
first_.size = readSize;

Expand Down Expand Up @@ -696,7 +700,7 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels,
Memory::Memcpy(dataBuf_, buffer, copybytes, "AtracSetData");
}
CreateDecoder();
return hleLogInfo(Log::ME, successCode, "%s %s audio", codecName, channelName);
return hleLogInfo(Log::ME, successCode, "%s %s (%d channels) audio", codecName, channelName, track_.channels);
}

u32 Atrac::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {
Expand Down
2 changes: 1 addition & 1 deletion Core/HW/Atrac3Standalone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Atrac3Audio : public AudioDecoder {
}
}
if (inbytes != blockAlign_ && blockAlign_ != 0) {
WARN_LOG(Log::ME, "Atrac3Audio::Decode: Unexpected block align %d (expected %d). %s", inbytes, blockAlign_, at3pCtx_ ? "Atrac3+" : "Atrac3");
WARN_LOG(Log::ME, "Atrac3Audio::Decode: inbytes not matching expected blockalign. Updating blockAlign_. Got %d bytes, expected %d. (%s)", inbytes, blockAlign_, at3pCtx_ ? "Atrac3+" : "Atrac3");
}

blockAlign_ = inbytes;
Expand Down
14 changes: 10 additions & 4 deletions ext/at3_standalone/atrac3plusdec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,20 @@ int atrac3p_decode_frame(ATRAC3PContext *ctx, float *out_data[2], int *nb_sample
while (get_bits_left(&ctx->gb) >= 2 &&
(ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
if (ch_unit_id == CH_UNIT_EXTENSION) {
avpriv_report_missing_feature("Channel unit extension");
av_log(AV_LOG_ERROR, "Missing atrac3p feature: Channel unit extension");
return AVERROR_PATCHWELCOME;
}
if (ch_block >= ctx->num_channel_blocks ||
ctx->channel_blocks[ch_block] != ch_unit_id) {
av_log(AV_LOG_ERROR,
"Frame data doesn't match channel configuration!");
return AVERROR_INVALIDDATA;
av_log(AV_LOG_WARNING, "Frame data doesn't match channel configuration! ch_block %d >= num_channel_blocks %d", ch_block, ctx->num_channel_blocks);
// This happens in Code Lyoko, see issue #19994.
// The atrac3+ wav header clearly specifies stereo, so we only have one channel block, but here we try to decode a third (and/or fourth) one.
// Maybe the data chunk is just improperly terminated, but it's reported that when ignoring this error previously,
// it didn't sound right. So I'm really not sure what's going on here. Most likely some unknown feature of the Atrac3+ format that we
// failed to parse previously?
//
// return AVERROR_INVALIDDATA; // This soft-locks the game.
return FFMIN(ctx->block_align, indata_size); // We try to stumble along.
}

ctx->ch_units[ch_block].unit_type = ch_unit_id;
Expand Down
Loading