mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
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:
parent
e4817b4e83
commit
ac43e55194
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user