Mp3: Loop correctly from an offset.

If the offset points to an ID3 tag or the middle of a frame, that's fine -
it should just search forward to the next sync.  FFmpeg just returns a
decode error, so we do this first.
This commit is contained in:
Unknown W. Brackets 2019-04-28 08:35:35 -07:00
parent e4817b4e83
commit ac43e55194
3 changed files with 24 additions and 10 deletions

View File

@ -388,7 +388,7 @@ static int sceMp3Init(u32 mp3) {
for (int offset = 0; offset < 1440; ++offset) {
header = ParseMp3Header(ctx, offset, &hasID3Tag);
// If we hit valid sync bits, then we've found a header.
if (((header >> 21) & 0x0FFE) == 0x0FFE) {
if ((header & 0xFFC00000) == 0xFFC00000) {
// Ignore the data before that.
ctx->EatSourceBuff(offset);
break;
@ -398,7 +398,7 @@ static int sceMp3Init(u32 mp3) {
static const int PARSE_DELAY_MS = 500;
// Couldn't find a header after all?
if (((header >> 21) & 0x0FFE) != 0x0FFE) {
if ((header & 0xFFC00000) != 0xFFC00000) {
return hleDelayResult(hleLogWarning(ME, ERROR_AVCODEC_INVALID_DATA, "no header found"), "mp3 init", PARSE_DELAY_MS);
}
@ -427,12 +427,9 @@ static int sceMp3Init(u32 mp3) {
// this is very important for ID3 tag mp3, since our universal audio decoder is for decoding stream part only.
if (hasID3Tag) {
// if get ID3 tage, we will decode from 0x400
// TODO: This doesn't seem right.
ctx->startPos = 0x400;
ctx->EatSourceBuff(0x400);
} else {
// if no ID3 tag, we will decode from the begining of the file
// TODO: This seems wrong, since it's an init parameter?
ctx->startPos = 0;
}
DEBUG_LOG(ME, "sceMp3Init(): channels=%i, samplerate=%iHz, bitrate=%ikbps", ctx->Channels, ctx->SamplingRate, ctx->BitRate);

View File

@ -311,9 +311,21 @@ AuCtx::~AuCtx(){
}
};
size_t AuCtx::FindNextMp3Sync() {
if (audioType != PSP_CODEC_MP3) {
return 0;
}
for (size_t i = 0; i < sourcebuff.size() - 2; ++i) {
if ((sourcebuff[i] & 0xFF) == 0xFF && (sourcebuff[i + 1] & 0xC0) == 0xC0) {
return i;
}
}
return 0;
}
// return output pcm size, <0 error
u32 AuCtx::AuDecode(u32 pcmAddr)
{
u32 AuCtx::AuDecode(u32 pcmAddr) {
if (!Memory::IsValidAddress(pcmAddr)){
ERROR_LOG(ME, "%s: output bufferAddress %08x is invalctx", __FUNCTION__, pcmAddr);
return -1;
@ -325,7 +337,10 @@ u32 AuCtx::AuDecode(u32 pcmAddr)
// Decode a single frame in sourcebuff and output into PCMBuf.
if (!sourcebuff.empty()) {
decoder->Decode((void *)sourcebuff.c_str(), (int)sourcebuff.size(), outbuf, &outpcmbufsize);
// FFmpeg doesn't seem to search for a sync for us, so let's do that.
int nextSync = (int)FindNextMp3Sync();
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, outbuf, &outpcmbufsize);
if (outpcmbufsize == 0) {
// no output pcm, we are at the end of the stream
AuBufAvailable = 0;
@ -334,7 +349,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr)
// Update our total decoded samples, but don't count stereo.
SumDecodedSamples += decoder->GetOutSamples() / 2;
// get consumed source length
int srcPos = decoder->GetSourcePos();
int srcPos = decoder->GetSourcePos() + nextSync;
// remove the consumed source
sourcebuff.erase(0, srcPos);
// reduce the available Aubuff size

View File

@ -153,6 +153,8 @@ public:
int askedReadSize; // the size of data requied to be read from file by the game
private:
size_t FindNextMp3Sync();
std::string sourcebuff; // source buffer
};