Skip to content

Commit 4ea7f46

Browse files
committed
Atrac3+: Try to work around Code Lyoko issue
Now we don't generate an error code when the channel configuration doesn't match the packets. See the code comment for what I've been able to figure out so far. See issue #19994
1 parent 25cc2ba commit 4ea7f46

File tree

3 files changed

+17
-7
lines changed

3 files changed

+17
-7
lines changed

Core/HLE/AtracCtx.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ void AtracBase::CreateDecoder() {
576576
delete decoder_;
577577
}
578578

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

653+
if (outputChannels != track_.channels) {
654+
WARN_LOG(Log::ME, "outputChannels %d doesn't match track_.channels %d", outputChannels, track_.channels);
655+
}
656+
653657
first_.addr = buffer;
654658
first_.size = readSize;
655659

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

702706
u32 Atrac::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {

Core/HW/Atrac3Standalone.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Atrac3Audio : public AudioDecoder {
8282
}
8383
}
8484
if (inbytes != blockAlign_ && blockAlign_ != 0) {
85-
WARN_LOG(Log::ME, "Atrac3Audio::Decode: Unexpected block align %d (expected %d). %s", inbytes, blockAlign_, at3pCtx_ ? "Atrac3+" : "Atrac3");
85+
WARN_LOG(Log::ME, "Atrac3Audio::Decode: inbytes not matching expected blockalign. Updating blockAlign_. Got %d bytes, expected %d. (%s)", inbytes, blockAlign_, at3pCtx_ ? "Atrac3+" : "Atrac3");
8686
}
8787

8888
blockAlign_ = inbytes;

ext/at3_standalone/atrac3plusdec.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,20 @@ int atrac3p_decode_frame(ATRAC3PContext *ctx, float *out_data[2], int *nb_sample
323323
while (get_bits_left(&ctx->gb) >= 2 &&
324324
(ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
325325
if (ch_unit_id == CH_UNIT_EXTENSION) {
326-
avpriv_report_missing_feature("Channel unit extension");
326+
av_log(AV_LOG_ERROR, "Missing atrac3p feature: Channel unit extension");
327327
return AVERROR_PATCHWELCOME;
328328
}
329329
if (ch_block >= ctx->num_channel_blocks ||
330330
ctx->channel_blocks[ch_block] != ch_unit_id) {
331-
av_log(AV_LOG_ERROR,
332-
"Frame data doesn't match channel configuration!");
333-
return AVERROR_INVALIDDATA;
331+
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);
332+
// This happens in Code Lyoko, see issue #19994.
333+
// 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.
334+
// Maybe the data chunk is just improperly terminated, but it's reported that when ignoring this error previously,
335+
// 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
336+
// failed to parse previously?
337+
//
338+
// return AVERROR_INVALIDDATA; // This soft-locks the game.
339+
return FFMIN(ctx->block_align, indata_size); // We try to stumble along.
334340
}
335341

336342
ctx->ch_units[ch_block].unit_type = ch_unit_id;

0 commit comments

Comments
 (0)