mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 09:09:29 +01:00
Seek backwards by force decoding, align seeks.
It seems like we can only (safely) seek to sample boundaries, which makes sense. Also, we get wrong data unless we "warm" it by seeking from 0, it seems like. This makes looping produce correct data. Fixes #6970.
This commit is contained in:
1 parent
da6375d89d
commit
97fd19f8cd
1 file changed
+44
-14
+44
-14
@@ -313,11 +313,45 @@ struct Atrac {
|
||||
packet = nullptr;
|
||||
}
|
||||
|
||||
void SeekToSample(int sample) {
|
||||
s64 seek_pos = (s64)sample;
|
||||
av_seek_frame(pFormatCtx, audio_stream_index, seek_pos, 0);
|
||||
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.
|
||||
packet->size = 0;
|
||||
|
||||
currentSample = sample;
|
||||
}
|
||||
|
||||
void SeekToSample(int sample) {
|
||||
const u32 atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
|
||||
// Discard any pending packet data.
|
||||
packet->size = 0;
|
||||
|
||||
// Some kind of header size?
|
||||
const u32 firstOffsetExtra = codecType == PSP_CODEC_AT3PLUS ? 368 : 69;
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
const u32 offsetSamples = firstSampleoffset + firstOffsetExtra;
|
||||
const u32 unalignedSamples = (offsetSamples + sample) % atracSamplesPerFrame;
|
||||
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 {
|
||||
av_seek_frame(pFormatCtx, audio_stream_index, seekFrame, 0);
|
||||
avcodec_flush_buffers(pCodecCtx);
|
||||
}
|
||||
currentSample = sample;
|
||||
}
|
||||
|
||||
bool FillPacket() {
|
||||
@@ -829,19 +863,18 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3
|
||||
u32 firstOffsetExtra = atrac->codecType == PSP_CODEC_AT3PLUS ? 368 : 69;
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
int offsetSamples = atrac->firstSampleoffset + firstOffsetExtra;
|
||||
int skipSamples = atrac->currentSample == 0 ? offsetSamples : 0;
|
||||
int skipSamples = 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;
|
||||
skipSamples = unalignedSamples;
|
||||
}
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
if (!atrac->failedDecode && (atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) {
|
||||
int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample;
|
||||
atrac->SeekToSample(forceseekSample);
|
||||
atrac->SeekToSample(atrac->currentSample == 0 ? 0 : atrac->currentSample + offsetSamples);
|
||||
atrac->SeekToSample(atrac->currentSample);
|
||||
|
||||
AtracDecodeResult res = ATDECODE_FEEDME;
|
||||
while (atrac->FillPacket()) {
|
||||
@@ -918,7 +951,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))) {
|
||||
atrac->currentSample = atrac->loopStartSample;
|
||||
atrac->SeekToSample(atrac->loopStartSample);
|
||||
if (atrac->loopNum > 0)
|
||||
atrac->loopNum --;
|
||||
} else if (atrac->currentSample >= atrac->endSample ||
|
||||
@@ -1288,13 +1321,13 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi
|
||||
INFO_LOG(ME, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf);
|
||||
if (bytesWrittenFirstBuf > 0)
|
||||
sceAtracAddStreamData(atracID, bytesWrittenFirstBuf);
|
||||
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
|
||||
{
|
||||
atrac->currentSample = sample;
|
||||
atrac->decodePos = atrac->getDecodePosBySample(sample);
|
||||
}
|
||||
}
|
||||
@@ -2120,9 +2153,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo
|
||||
}
|
||||
|
||||
int numSamples = 0;
|
||||
int forceseekSample = 0x200000;
|
||||
atrac->SeekToSample(forceseekSample);
|
||||
atrac->SeekToSample(atrac->currentSample);
|
||||
atrac->ForceSeekToSample(atrac->currentSample);
|
||||
|
||||
if (!atrac->failedDecode) {
|
||||
AtracDecodeResult res;
|
||||
@@ -2152,12 +2183,11 @@ 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);
|
||||
atrac->SeekToSample(atrac->currentSample);
|
||||
|
||||
if (atrac->decodePos >= atrac->first.size) {
|
||||
atrac->first.writableBytes = atrac->atracBytesPerFrame;
|
||||
atrac->first.size = atrac->firstSampleoffset;
|
||||
atrac->currentSample = 0;
|
||||
atrac->ForceSeekToSample(0);
|
||||
}
|
||||
else
|
||||
atrac->first.writableBytes = 0;
|
||||
|
||||
Reference in new issue
Block a user