diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 6be33200bf..c5744afc41 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -42,5 +42,4 @@ void Compatibility::Clear() { void Compatibility::LoadIniSection(IniFile &iniFile, std::string section) { iniFile.Get(section.c_str(), "NoDepthRounding", &flags_.NoDepthRounding, flags_.NoDepthRounding); iniFile.Get(section.c_str(), "PixelDepthRounding", &flags_.PixelDepthRounding, flags_.PixelDepthRounding); - iniFile.Get(section.c_str(), "GTAMusicFix", &flags_.GTAMusicFix, flags_.GTAMusicFix); } diff --git a/Core/Compatibility.h b/Core/Compatibility.h index a5a3a7fa07..0a7d3c64b4 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -47,7 +47,6 @@ struct CompatFlags { bool NoDepthRounding; bool PixelDepthRounding; - bool GTAMusicFix; }; class IniFile; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6861010417..d873b4b2ec 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -17,16 +17,13 @@ #include -#include "Core/CoreParameter.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" #include "Core/CoreTiming.h" -#include "Core/Compatibility.h" #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/Config.h" -#include "Core/System.h" #include "Core/Debugger/Breakpoints.h" #include "Core/HW/MediaEngine.h" #include "Core/HW/BufferQueue.h" @@ -105,6 +102,7 @@ enum AtracDecodeResult { ATDECODE_FAILED = -1, ATDECODE_FEEDME = 0, ATDECODE_GOTFRAME = 1, + ATDECODE_BADFRAME = 2, }; struct InputBuffer { @@ -133,20 +131,17 @@ struct AtracLoopInfo { struct Atrac { Atrac() : atracID(-1), data_buf(0), decodePos(0), decodeEnd(0), bufferPos(0), atracChannels(0),atracOutputChannels(2), - atracBitrate(64), atracBytesPerFrame(0), atracBufSize(0), + atracBitrate(64), atracBytesPerFrame(0), atracBufSize(0), jointStereo(0), currentSample(0), endSample(0), firstSampleoffset(0), dataOff(0), loopinfoNum(0), loopStartSample(-1), loopEndSample(-1), loopNum(0), failedDecode(false), resetBuffer(false), codecType(0) { memset(&first, 0, sizeof(first)); memset(&second, 0, sizeof(second)); #ifdef USE_FFMPEG - pFormatCtx = nullptr; - pAVIOCtx = nullptr; pCodecCtx = nullptr; pSwrCtx = nullptr; pFrame = nullptr; packet = nullptr; - audio_stream_index = 0; #endif // USE_FFMPEG atracContext = 0; } @@ -169,12 +164,15 @@ struct Atrac { } void DoState(PointerWrap &p) { - auto s = p.Section("Atrac", 1, 4); + auto s = p.Section("Atrac", 1, 5); if (!s) return; p.Do(atracChannels); p.Do(atracOutputChannels); + if (s >= 5) { + p.Do(jointStereo); + } p.Do(atracID); p.Do(first); @@ -190,7 +188,7 @@ struct Atrac { dataOff = firstSampleoffset; } - u32 has_data_buf = data_buf != NULL; + u32 has_data_buf = data_buf != nullptr; p.Do(has_data_buf); if (has_data_buf) { if (p.mode == p.MODE_READ) { @@ -200,9 +198,6 @@ struct Atrac { } p.DoArray(data_buf, first.filesize); } - if (p.mode == p.MODE_READ && data_buf != NULL) { - __AtracSetContext(this); - } p.Do(second); p.Do(decodePos); @@ -224,6 +219,11 @@ struct Atrac { p.Do(loopNum); p.Do(atracContext); + + // Make sure to do this late; it depends on things like atracBytesPerFrame. + if (p.mode == p.MODE_READ && data_buf != nullptr) { + __AtracSetContext(this); + } if (s >= 2) p.Do(resetBuffer); @@ -237,6 +237,12 @@ struct Atrac { return (u32)(firstSampleoffset + sample / atracSamplesPerFrame * atracBytesPerFrame ); } + u32 getFileOffsetBySample(int sample) const { + int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); + // This matches where ffmpeg was getting the packets, but it's not clear why the first atracBytesPerFrame is there... + return (u32)(dataOff + atracBytesPerFrame + (sample + atracSamplesPerFrame - 1) / atracSamplesPerFrame * atracBytesPerFrame); + } + int getRemainFrames() const { // games would like to add atrac data when it wants. // Do not try to guess when it want to add data. @@ -259,6 +265,7 @@ struct Atrac { u32 decodePos; u32 decodeEnd; + // Used only by low-level decoding. u32 bufferPos; u16 atracChannels; @@ -266,6 +273,7 @@ struct Atrac { u32 atracBitrate; u16 atracBytesPerFrame; u32 atracBufSize; + int jointStereo; int currentSample; int endSample; @@ -291,41 +299,31 @@ struct Atrac { PSPPointer atracContext; #ifdef USE_FFMPEG - AVFormatContext *pFormatCtx; - AVIOContext *pAVIOCtx; AVCodecContext *pCodecCtx; SwrContext *pSwrCtx; AVFrame *pFrame; AVPacket *packet; - int audio_stream_index; void ReleaseFFMPEGContext() { - if (pFrame) - av_free(pFrame); - if (pAVIOCtx && pAVIOCtx->buffer) - av_free(pAVIOCtx->buffer); - if (pAVIOCtx) - av_free(pAVIOCtx); - if (pSwrCtx) - swr_free(&pSwrCtx); - if (pCodecCtx) - avcodec_close(pCodecCtx); - if (pFormatCtx) - avformat_close_input(&pFormatCtx); - if (packet) - av_free_packet(packet); + // All of these allow null pointers. + av_freep(&pFrame); + swr_free(&pSwrCtx); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) + // If necessary, extradata is automatically freed. + avcodec_free_context(&pCodecCtx); +#else + // Future versions may add other things to free, but avcodec_free_context didn't exist yet here. + avcodec_close(pCodecCtx); + av_freep(&pCodecCtx->extradata); + av_freep(&pCodecCtx->subtitle_header); + av_freep(&pCodecCtx); +#endif + av_free_packet(packet); delete packet; - pFormatCtx = nullptr; - pAVIOCtx = nullptr; - pCodecCtx = nullptr; - pSwrCtx = nullptr; - pFrame = nullptr; packet = nullptr; } void ForceSeekToSample(int sample) { - av_seek_frame(pFormatCtx, audio_stream_index, sample + 0x200000, 0); - av_seek_frame(pFormatCtx, audio_stream_index, sample, 0); avcodec_flush_buffers(pCodecCtx); // Discard any pending packet data. @@ -335,12 +333,6 @@ struct Atrac { } void SeekToSample(int sample) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - s64 seek_pos = (s64)sample; - av_seek_frame(pFormatCtx, audio_stream_index, seek_pos, 0); - return; - } - const u32 atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); // Discard any pending packet data. @@ -354,97 +346,55 @@ struct Atrac { int seekFrame = sample + offsetSamples - unalignedSamples; if (sample != currentSample) { - // "Seeking" by reading frames seems to work much better. - av_seek_frame(pFormatCtx, audio_stream_index, 0, AVSEEK_FLAG_BACKWARD); - avcodec_flush_buffers(pCodecCtx); - - for (int i = 0; i < seekFrame; i += atracSamplesPerFrame) { - while (FillPacket() && DecodePacket() == ATDECODE_FEEDME) { - continue; - } - } - } else { - // For some reason, if we skip seeking, we get the wrong amount of data. - // (even without flushing the packet...) - av_seek_frame(pFormatCtx, audio_stream_index, seekFrame, 0); avcodec_flush_buffers(pCodecCtx); } currentSample = sample; } bool FillPacket() { - if (packet->size > 0) { + u32 off = getFileOffsetBySample(currentSample); + if (off < first.filesize) { + av_init_packet(packet); + packet->data = data_buf + off; + packet->size = atracBytesPerFrame; + packet->pos = off; + return true; + } else { + return false; } - do { - // This is double-free safe, so we just call it before each read and at the end. - av_free_packet(packet); - if (av_read_frame(pFormatCtx, packet) < 0) { - return false; - } - // We keep reading until we get the right stream index. - } while (packet->stream_index != audio_stream_index); return true; } + bool FillLowLevelPacket() { + av_init_packet(packet); + if (bufferPos < (u32)dataOff) { + bufferPos = dataOff; + } + + packet->data = data_buf + bufferPos; + packet->size = atracBytesPerFrame; + packet->pos = bufferPos; + bufferPos += atracBytesPerFrame; + return true; + } + AtracDecodeResult DecodePacket() { - AVPacket tempPacket; - AVPacket *decodePacket = packet; - if (packet->size < (int)atracBytesPerFrame) { - // Whoops, we have a packet that is smaller than a frame. Let's meld a new one. - u32 initialSize = packet->size; - int needed = atracBytesPerFrame - initialSize; - av_init_packet(&tempPacket); - av_copy_packet(&tempPacket, packet); - av_grow_packet(&tempPacket, needed); - - // Okay, we're "out of data", let's get more. - packet->size = 0; - - if (FillPacket()) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - if (packet->size >= needed) { - memcpy(tempPacket.data + initialSize, packet->data, needed); - packet->size -= needed; - packet->data += needed; - } - } else { - int to_copy = packet->size >= needed ? needed : packet->size; - memcpy(tempPacket.data + initialSize, packet->data, to_copy); - packet->size -= to_copy; - packet->data += to_copy; - tempPacket.size = initialSize + to_copy; - } - } else { - tempPacket.size = initialSize; - } - decodePacket = &tempPacket; - } - int got_frame = 0; - int bytes_read = avcodec_decode_audio4(pCodecCtx, pFrame, &got_frame, decodePacket); - if (packet != decodePacket) { - av_free_packet(&tempPacket); - } + int bytes_read = avcodec_decode_audio4(pCodecCtx, pFrame, &got_frame, packet); + av_free_packet(packet); if (bytes_read == AVERROR_PATCHWELCOME) { ERROR_LOG(ME, "Unsupported feature in ATRAC audio."); // Let's try the next packet. - if (packet == decodePacket) { - packet->size = 0; - } - // TODO: Or actually, should we return a blank frame and pretend it worked? - return ATDECODE_FEEDME; + packet->size = 0; + return ATDECODE_BADFRAME; } else if (bytes_read < 0) { ERROR_LOG_REPORT(ME, "avcodec_decode_audio4: Error decoding audio %d / %08x", bytes_read, bytes_read); failedDecode = true; return ATDECODE_FAILED; } - if (packet == decodePacket) { - packet->size -= bytes_read; - packet->data += bytes_read; - } return got_frame ? ATDECODE_GOTFRAME : ATDECODE_FEEDME; } #endif // USE_FFMPEG @@ -665,6 +615,12 @@ int Atrac::Analyze() { } // TODO: There are some format specific bytes here which seem to have fixed values? + // Probably don't need them. + + if (at3fmt->fmtTag == AT3_MAGIC) { + // This is the offset to the jointStereo field. + jointStereo = Memory::Read_U32(first.addr + offset + 24); + } } break; case FACT_CHUNK_MAGIC: @@ -770,6 +726,7 @@ int Atrac::AnalyzeAA3() { atracBytesPerFrame = (codecParams & 0x03FF) * 8; atracBitrate = at3SampleRates[(codecParams >> 13) & 7] * atracBytesPerFrame * 8 / 1024; atracChannels = 2; + jointStereo = (codecParams >> 17) & 1; break; case 1: codecType = PSP_MODE_AT_3_PLUS; @@ -786,7 +743,7 @@ int Atrac::AnalyzeAA3() { return ATRAC_ERROR_AA3_INVALID_DATA; } - dataOff = 0; + dataOff = 10 + tagSize + 96; firstSampleoffset = 0; if (endSample < 0 && atracBytesPerFrame != 0) { int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); @@ -823,7 +780,7 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { atrac->first.size += bytesToAdd; if (atrac->first.size > atrac->first.filesize) atrac->first.size = atrac->first.filesize; - atrac->first.fileoffset = atrac->first.size; + atrac->first.fileoffset += addbytes; atrac->first.writableBytes = 0; if (atrac->atracContext.IsValid()) { // refresh atracContext @@ -857,11 +814,11 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { if (bytesToAdd > 0) { int addbytes = std::min(bytesToAdd, atrac->first.filesize - atrac->first.fileoffset); Memory::Memcpy(atrac->data_buf + atrac->first.fileoffset, atrac->first.addr + atrac->first.offset, addbytes); + atrac->first.fileoffset += addbytes; } atrac->first.size += bytesToAdd; if (atrac->first.size > atrac->first.filesize) atrac->first.size = atrac->first.filesize; - atrac->first.fileoffset = atrac->first.size; atrac->first.writableBytes -= bytesToAdd; atrac->first.offset += bytesToAdd; } @@ -893,28 +850,17 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 // It seems like the PSP aligns the sample position to 0x800...? int offsetSamples = atrac->firstSampleoffset + firstOffsetExtra; int skipSamples = 0; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - skipSamples = atrac->currentSample == 0 ? offsetSamples : 0; - } u32 maxSamples = atrac->endSample - atrac->currentSample; u32 unalignedSamples = (offsetSamples + atrac->currentSample) % atracSamplesPerFrame; if (unalignedSamples != 0) { // We're off alignment, possibly due to a loop. Force it back on. maxSamples = atracSamplesPerFrame - unalignedSamples; - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - skipSamples = unalignedSamples; - } + skipSamples = unalignedSamples; } #ifdef USE_FFMPEG if (!atrac->failedDecode && (atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample; - atrac->SeekToSample(forceseekSample); - atrac->SeekToSample(atrac->currentSample == 0 ? 0 : atrac->currentSample + offsetSamples); - } else { - atrac->SeekToSample(atrac->currentSample); - } + atrac->SeekToSample(atrac->currentSample); AtracDecodeResult res = ATDECODE_FEEDME; while (atrac->FillPacket()) { @@ -965,7 +911,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 } } } - if (res == ATDECODE_GOTFRAME) { + if (res == ATDECODE_GOTFRAME || res == ATDECODE_BADFRAME) { // We only want one frame per call, let's continue the next time. break; } @@ -990,11 +936,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int finishFlag = 0; if (atrac->loopNum != 0 && (atrac->currentSample > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = 0; - } else { - atrac->SeekToSample(atrac->loopStartSample); - } + atrac->SeekToSample(atrac->loopStartSample); if (atrac->loopNum > 0) atrac->loopNum --; } else if (atrac->currentSample >= atrac->endSample || @@ -1067,7 +1009,7 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer return ATRAC_ERROR_BAD_SAMPLE; } - int Sampleoffset = atrac->getDecodePosBySample(sample); + int Sampleoffset = atrac->getFileOffsetBySample(sample); int minWritebytes = std::max(Sampleoffset - (int)atrac->first.size, 0); // Reset temp buf for adding more stream data and set full filled buffer atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->atracBufSize); @@ -1075,10 +1017,6 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer // minWritebytes should not be bigger than writeablebytes minWritebytes = std::min(minWritebytes, (int)atrac->first.writableBytes); - if (atrac->first.fileoffset <= 2*atrac->atracBufSize){ - Sampleoffset = atrac->first.fileoffset; - } - // If we've already loaded everything, the answer is 0. if (atrac->first.size >= atrac->first.filesize) { Sampleoffset = 0; @@ -1344,9 +1282,7 @@ static u32 sceAtracGetStreamDataInfo(int atracID, u32 writeAddr, u32 writableByt // Reset temp buf for adding more stream data and set full filled buffer. atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->atracBufSize); } else { - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); - } + atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); } atrac->first.offset = 0; @@ -1386,64 +1322,22 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return ATRAC_ERROR_NO_DATA; } else { INFO_LOG(ME, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); + atrac->first.fileoffset = atrac->getFileOffsetBySample(sample); if (bytesWrittenFirstBuf > 0) sceAtracAddStreamData(atracID, bytesWrittenFirstBuf); - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = sample; - } #ifdef USE_FFMPEG if ((atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { atrac->SeekToSample(sample); } else #endif // USE_FFMPEG { - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = sample; - } + atrac->currentSample = sample; atrac->decodePos = atrac->getDecodePosBySample(sample); } } return 0; } -#ifdef USE_FFMPEG -static int _AtracReadbuffer(void *opaque, uint8_t *buf, int buf_size) { - Atrac *atrac = (Atrac *)opaque; - if (atrac->bufferPos > atrac->first.filesize) - return -1; - int size = std::min((int)atrac->atracBufSize, buf_size); - size = std::max(std::min(((int)atrac->first.size - (int)atrac->bufferPos), size), 0); - if (size > 0) - memcpy(buf, atrac->data_buf + atrac->bufferPos, size); - atrac->bufferPos += size; - return size; -} - -static int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence) { - Atrac *atrac = (Atrac*)opaque; - if (offset > atrac->first.filesize) - return -1; - - switch (whence) { - case SEEK_SET: - atrac->bufferPos = (u32)offset; - break; - case SEEK_CUR: - atrac->bufferPos += (u32)offset; - break; - case SEEK_END: - atrac->bufferPos = atrac->first.filesize - (u32)offset; - break; -#ifdef USE_FFMPEG - case AVSEEK_SIZE: - return atrac->first.filesize; -#endif - } - return atrac->bufferPos; -} - -#endif // USE_FFMPEG - #ifdef USE_FFMPEG static int __AtracUpdateOutputMode(Atrac *atrac, int wanted_channels) { if (atrac->pSwrCtx && atrac->atracOutputChannels == wanted_channels) @@ -1483,49 +1377,56 @@ int __AtracSetContext(Atrac *atrac) { u8* tempbuf = (u8*)av_malloc(atrac->atracBufSize); - atrac->pFormatCtx = avformat_alloc_context(); - atrac->pAVIOCtx = avio_alloc_context(tempbuf, atrac->atracBufSize, 0, (void*)atrac, _AtracReadbuffer, NULL, _AtracSeekbuffer); - atrac->pFormatCtx->pb = atrac->pAVIOCtx; - - int ret; - // Load audio buffer - if((ret = avformat_open_input((AVFormatContext**)&atrac->pFormatCtx, NULL, NULL, NULL)) != 0) { - ERROR_LOG(ME, "avformat_open_input: Cannot open input %d", ret); - // TODO: This is not exactly correct, but if the header is right and there's not enough data - // (which is likely the case here), this is the correct error. - return ATRAC_ERROR_ALL_DATA_DECODED; - } - - if((ret = avformat_find_stream_info(atrac->pFormatCtx, NULL)) < 0) { - ERROR_LOG(ME, "avformat_find_stream_info: Cannot find stream information %d", ret); + AVCodecID ff_codec; + if (atrac->codecType == PSP_MODE_AT_3) { + ff_codec = AV_CODEC_ID_ATRAC3; + } else if (atrac->codecType == PSP_MODE_AT_3_PLUS) { + ff_codec = AV_CODEC_ID_ATRAC3P; + } else { + ERROR_LOG_REPORT(ME, "Unexpected codec type %d", atrac->codecType); return -1; } - AVCodec *pCodec; - // select the audio stream - ret = av_find_best_stream(atrac->pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); - if (ret < 0) { - if (ret == AVERROR_DECODER_NOT_FOUND) { - ERROR_LOG(HLE, "av_find_best_stream: No appropriate decoder found"); - } else { - ERROR_LOG(HLE, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret); - } - return -1; + const AVCodec *codec = avcodec_find_decoder(ff_codec); + atrac->pCodecCtx = avcodec_alloc_context3(codec); + + if (atrac->codecType == PSP_MODE_AT_3) { + // For ATRAC3, we need the "extradata" in the RIFF header. + atrac->pCodecCtx->extradata = (uint8_t *)av_mallocz(14); + atrac->pCodecCtx->extradata_size = 14; + + // We don't pull this from the RIFF so that we can support OMA also. + // The only thing that changes are the jointStereo values. + atrac->pCodecCtx->extradata[0] = 1; + atrac->pCodecCtx->extradata[3] = 0x10; + atrac->pCodecCtx->extradata[6] = atrac->jointStereo; + atrac->pCodecCtx->extradata[8] = atrac->jointStereo; + atrac->pCodecCtx->extradata[10] = 1; } - atrac->audio_stream_index = ret; - atrac->pCodecCtx = atrac->pFormatCtx->streams[atrac->audio_stream_index]->codec; // Appears we need to force mono in some cases. (See CPkmn's comments in issue #4248) - if (atrac->atracChannels == 1) + if (atrac->atracChannels == 1) { + atrac->pCodecCtx->channels = 1; atrac->pCodecCtx->channel_layout = AV_CH_LAYOUT_MONO; + } else if (atrac->atracChannels == 2) { + atrac->pCodecCtx->channels = 2; + atrac->pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; + } else { + ERROR_LOG_REPORT(ME, "Unexpected channel count %d", atrac->atracChannels); + return -1; + } + // Explicitly set the block_align value (needed by newer FFmpeg versions, see #5772.) if (atrac->pCodecCtx->block_align == 0) { atrac->pCodecCtx->block_align = atrac->atracBytesPerFrame; } + // Only one supported, it seems? + atrac->pCodecCtx->sample_rate = 44100; atrac->pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16; - if ((ret = avcodec_open2(atrac->pCodecCtx, pCodec, NULL)) < 0) { + int ret; + if ((ret = avcodec_open2(atrac->pCodecCtx, codec, nullptr)) < 0) { ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret); return -1; } @@ -1586,7 +1487,6 @@ static int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize) { return __AtracSetContext(atrac); } - return 0; } @@ -1996,16 +1896,16 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) { // TODO: Should we just keep this in PSP ram then, or something? } else if (!atrac->data_buf) { // State 1, no buffer yet. - context->info.state = 1; + context->info.state = ATRAC_STATUS_NO_DATA; } else if (atrac->first.size >= atrac->first.filesize) { // state 2, all data loaded - context->info.state = 2; + context->info.state = ATRAC_STATUS_ALL_DATA_LOADED; } else if (atrac->loopinfoNum == 0) { // state 3, lack some data, no loop info - context->info.state = 3; + context->info.state = ATRAC_STATUS_STREAMED_WITHOUT_LOOP; } else { // state 6, lack some data, has loop info - context->info.state = 6; + context->info.state = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER; } context->info.samplesPerChan = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); context->info.sampleSize = atrac->atracBytesPerFrame; @@ -2136,6 +2036,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { atrac->data_buf = new u8[atrac->first.filesize]; memcpy(atrac->data_buf, at3Header, headersize); atrac->currentSample = 0; + // TODO: Check failure? __AtracSetContext(atrac); return 0; } @@ -2187,17 +2088,11 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo } int numSamples = 0; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - int forceseekSample = 0x200000; - atrac->SeekToSample(forceseekSample); - atrac->SeekToSample(atrac->currentSample); - } else { - atrac->ForceSeekToSample(atrac->currentSample); - } + atrac->ForceSeekToSample(atrac->currentSample); if (!atrac->failedDecode) { AtracDecodeResult res; - while (atrac->FillPacket()) { + while (atrac->FillLowLevelPacket()) { res = atrac->DecodePacket(); if (res == ATDECODE_FAILED) { break; @@ -2215,6 +2110,8 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo ERROR_LOG(ME, "swr_convert: Error while converting %d", avret); } break; + } else if (res == ATDECODE_BADFRAME) { + break; } } } @@ -2222,18 +2119,12 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo atrac->currentSample += numSamples; numSamples = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr); - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->SeekToSample(atrac->currentSample); - } if (atrac->bufferPos >= atrac->first.size) { atrac->first.writableBytes = atrac->atracBytesPerFrame; atrac->first.size = atrac->firstSampleoffset; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = 0; - } else { - atrac->ForceSeekToSample(0); - } + atrac->ForceSeekToSample(0); + atrac->bufferPos = atrac->dataOff; } else atrac->first.writableBytes = 0; diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index aa4d2789c3..41d3b62a0f 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -26,6 +26,26 @@ void __AtracInit(); void __AtracDoState(PointerWrap &p); void __AtracShutdown(); +enum AtracStatus : u8 { + ATRAC_STATUS_NO_DATA = 1, + ATRAC_STATUS_ALL_DATA_LOADED = 2, + ATRAC_STATUS_HALFWAY_BUFFER = 3, + ATRAC_STATUS_STREAMED_WITHOUT_LOOP = 4, + ATRAC_STATUS_STREAMED_LOOP_FROM_END = 5, + // This means there's additional audio after the loop. + // i.e. ~~before loop~~ [ ~~this part loops~~ ] ~~after loop~~ + // The "fork in the road" means a second buffer is needed for the second path. + ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER = 6, + ATRAC_STATUS_LOW_LEVEL = 8, + ATRAC_STATUS_FOR_SCESAS = 16, +}; + +#if COMMON_LITTLE_ENDIAN +typedef AtracStatus AtracStatus_le; +#else +typedef swap_struct_t > AtracStatus_le; +#endif + typedef struct { u32_le decodePos; // 0 @@ -36,7 +56,7 @@ typedef struct char numFrame; // 20 // 2: all the stream data on the buffer // 6: looping -> second buffer needed - char state; // 21 + AtracStatus_le state; // 21 char unk22; char numChan; // 23 u16_le sampleSize; // 24 diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index c66e03e079..f8074f0e99 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -55,7 +55,7 @@ int SimpleAudio::GetAudioCodecID(int audioType) { SimpleAudio::SimpleAudio(int audioType, int sample_rate, int channels) : ctxPtr(0xFFFFFFFF), audioType(audioType), sample_rate_(sample_rate), channels_(channels), outSamples(0), srcPos(0), wanted_resample_freq(44100), frame_(0), codec_(0), codecCtx_(0), swrCtx_(0), - extradata_(0), codecOpen_(false) { + codecOpen_(false) { Init(); } @@ -114,62 +114,36 @@ bool SimpleAudio::OpenCodec(int block_align) { #endif // USE_FFMPEG } -bool SimpleAudio::ResetCodecCtx(int channels, int samplerate) { -#ifdef USE_FFMPEG - if (codecCtx_) - avcodec_close(codecCtx_); - - // Find decoder - int audioCodecId = GetAudioCodecID(audioType); - codec_ = avcodec_find_decoder((AVCodecID)audioCodecId); - if (!codec_) { - // Eh, we shouldn't even have managed to compile. But meh. - ERROR_LOG(ME, "This version of FFMPEG does not support AV_CODEC_ctx for audio (%s). Update your submodule.", GetCodecName(audioType)); - return false; - } - - codecCtx_->channels = channels; - codecCtx_->channel_layout = channels==2?AV_CH_LAYOUT_STEREO:AV_CH_LAYOUT_MONO; - codecCtx_->sample_rate = samplerate; - codecOpen_ = false; - return true; -#endif - return false; -} - void SimpleAudio::SetExtraData(u8 *data, int size, int wav_bytes_per_packet) { - delete [] extradata_; - extradata_ = 0; - - if (data != 0) { - extradata_ = new u8[size]; - memcpy(extradata_, data, size); - } - #ifdef USE_FFMPEG if (codecCtx_) { - codecCtx_->extradata = extradata_; + codecCtx_->extradata = (uint8_t *)av_mallocz(size); codecCtx_->extradata_size = size; codecCtx_->block_align = wav_bytes_per_packet; codecOpen_ = false; + + if (data != nullptr) { + memcpy(codecCtx_->extradata, data, size); + } } #endif } SimpleAudio::~SimpleAudio() { #ifdef USE_FFMPEG - if (swrCtx_) - swr_free(&swrCtx_); - if (frame_) - av_frame_free(&frame_); - if (codecCtx_) - avcodec_close(codecCtx_); - frame_ = 0; - codecCtx_ = 0; + swr_free(&swrCtx_); + av_frame_free(&frame_); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) + avcodec_free_context(&codecCtx_); +#else + // Future versions may add other things to free, but avcodec_free_context didn't exist yet here. + avcodec_close(codecCtx_); + av_freep(&codecCtx_->extradata); + av_freep(&codecCtx_->subtitle_header); + av_freep(&codecCtx_); +#endif codec_ = 0; #endif // USE_FFMPEG - delete [] extradata_; - extradata_ = 0; } bool SimpleAudio::IsOK() const { diff --git a/Core/HW/SimpleAudioDec.h b/Core/HW/SimpleAudioDec.h index 7539fdbdc3..03826ca0c8 100644 --- a/Core/HW/SimpleAudioDec.h +++ b/Core/HW/SimpleAudioDec.h @@ -51,7 +51,6 @@ public: int GetOutSamples(); int GetSourcePos(); - bool ResetCodecCtx(int channels, int samplerate); int GetAudioCodecID(int audioType); // Get audioCodecId from audioType // Not save stated, only used by UI. Used for ATRAC3 (non+) files. @@ -82,8 +81,6 @@ private: AVCodecContext *codecCtx_; SwrContext *swrCtx_; - // Not savestated, only used by UI. - u8 *extradata_; bool codecOpen_; }; diff --git a/assets/compat.ini b/assets/compat.ini index 155751c110..518b1e25ec 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -73,52 +73,3 @@ PixelDepthRounding = true PixelDepthRounding = true [ULJS00454] PixelDepthRounding = true - - -# GTA audio issues -# These games stream their radio stations from disc as giant audio files. They seek into -# the correct position. Our ATRAC3 module (sceAtrac) implementation is still not very accurate -# and needs some special handling for this to work correctly, for unknown reasons. - -# GTAMusicFix removes the effect of pull #6976, which fixed many games but broke GTA. -# Issue #7863 has some more information. - -# GTA Liberty City Stories -[ULUS10041] -GTAMusicFix = true -[ULES00151] -GTAMusicFix = true -[ULJM05255] -GTAMusicFix = true -[ULJM05359] -GTAMusicFix = true -[ULJM05885] -GTAMusicFix = true -[NPJH50825] -GTAMusicFix = true - -# GTA Vice City Stories -[ULES00502] -GTAMusicFix = true -[ULUS10160] -GTAMusicFix = true -[ULJM05297] -GTAMusicFix = true -[ULJM05395] -GTAMusicFix = true -[ULJM05884] -GTAMusicFix = true -[NPJH50827] -GTAMusicFix = true - -# GTA Chinatown Wars -[ULUS10490] -GTAMusicFix = true -[ULES01347] -GTAMusicFix = true -[ULJM05604] -GTAMusicFix = true -[ULJM05804] -GTAMusicFix = true -[NPJH00138] -GTAMusicFix = true