mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-18 17:00:30 +02:00
Merge pull request #19074 from hrydgard/more-atrac-updates
More sceAtrac code cleanup and comments
This commit is contained in:
8 files changed
+160
-86
No files matched your search
+14
-4
@@ -37,9 +37,10 @@
|
||||
|
||||
static bool hitAnyAsserts = false;
|
||||
|
||||
std::mutex g_extraAssertInfoMutex;
|
||||
std::string g_extraAssertInfo = "menu";
|
||||
double g_assertInfoTime = 0.0;
|
||||
static std::mutex g_extraAssertInfoMutex;
|
||||
static std::string g_extraAssertInfo = "menu";
|
||||
static double g_assertInfoTime = 0.0;
|
||||
static bool g_exitOnAssert;
|
||||
|
||||
void SetExtraAssertInfo(const char *info) {
|
||||
std::lock_guard<std::mutex> guard(g_extraAssertInfoMutex);
|
||||
@@ -47,6 +48,10 @@ void SetExtraAssertInfo(const char *info) {
|
||||
g_assertInfoTime = time_now_d();
|
||||
}
|
||||
|
||||
void SetCleanExitOnAssert() {
|
||||
g_exitOnAssert = true;
|
||||
}
|
||||
|
||||
bool HandleAssert(const char *function, const char *file, int line, const char *expression, const char* format, ...) {
|
||||
// Read message and write it to the log
|
||||
char text[LOG_BUF_SIZE];
|
||||
@@ -78,8 +83,13 @@ bool HandleAssert(const char *function, const char *file, int line, const char *
|
||||
std::wstring wtext = ConvertUTF8ToWString(formatted) + L"\n\nTry to continue?";
|
||||
std::wstring wcaption = ConvertUTF8ToWString(std::string(caption) + " " + GetCurrentThreadName());
|
||||
OutputDebugString(wtext.c_str());
|
||||
printf("%s\n", formatted);
|
||||
if (IDYES != MessageBox(0, wtext.c_str(), wcaption.c_str(), msgBoxStyle)) {
|
||||
return false;
|
||||
if (g_exitOnAssert) {
|
||||
// Hard exit.
|
||||
ExitProcess(1);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ __attribute__((format(printf, 5, 6)))
|
||||
bool HitAnyAsserts();
|
||||
void ResetHitAnyAsserts();
|
||||
void SetExtraAssertInfo(const char *info);
|
||||
void SetCleanExitOnAssert();
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Tricky macro to get the basename, that also works if *built* on Win32.
|
||||
|
||||
+51
-41
@@ -64,9 +64,9 @@ void Atrac::DoState(PointerWrap &p) {
|
||||
Do(p, track_.endSample);
|
||||
Do(p, track_.firstSampleOffset);
|
||||
if (s >= 3) {
|
||||
Do(p, track_.dataOff);
|
||||
Do(p, track_.dataByteOffset);
|
||||
} else {
|
||||
track_.dataOff = track_.firstSampleOffset;
|
||||
track_.dataByteOffset = track_.firstSampleOffset;
|
||||
}
|
||||
|
||||
u32 hasDataBuf = dataBuf_ != nullptr;
|
||||
@@ -127,10 +127,10 @@ void Atrac::DoState(PointerWrap &p) {
|
||||
Do(p, bufferValidBytes_);
|
||||
Do(p, bufferHeaderSize_);
|
||||
} else {
|
||||
bufferHeaderSize_ = track_.dataOff;
|
||||
bufferValidBytes_ = std::min(first_.size - track_.dataOff, StreamBufferEnd() - track_.dataOff);
|
||||
bufferHeaderSize_ = track_.dataByteOffset;
|
||||
bufferValidBytes_ = std::min(first_.size - track_.dataByteOffset, StreamBufferEnd() - track_.dataByteOffset);
|
||||
if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) {
|
||||
bufferPos_ = track_.dataOff;
|
||||
bufferPos_ = track_.dataByteOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,18 +211,18 @@ void Atrac::WriteContextToPSPMem() {
|
||||
// TODO: Should we just keep this in PSP ram then, or something?
|
||||
context->info.state = bufferState_;
|
||||
if (track_.firstSampleOffset != 0) {
|
||||
context->info.samplesPerChan = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
context->info.samplesPerChan = track_.FirstSampleOffsetFull();
|
||||
} else {
|
||||
context->info.samplesPerChan = (track_.codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
}
|
||||
context->info.sampleSize = track_.bytesPerFrame;
|
||||
context->info.numChan = track_.channels;
|
||||
context->info.dataOff = track_.dataOff;
|
||||
context->info.endSample = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra();
|
||||
context->info.dataOff = track_.dataByteOffset;
|
||||
context->info.endSample = track_.endSample + track_.FirstSampleOffsetFull();
|
||||
context->info.dataEnd = track_.fileSize;
|
||||
context->info.curOff = first_.fileoffset;
|
||||
context->info.decodePos = track_.DecodePosBySample(currentSample_);
|
||||
context->info.streamDataByte = first_.size - track_.dataOff;
|
||||
context->info.streamDataByte = first_.size - track_.dataByteOffset;
|
||||
|
||||
u8 *buf = (u8 *)context;
|
||||
*(u32_le *)(buf + 0xfc) = atracID_;
|
||||
@@ -230,6 +230,13 @@ void Atrac::WriteContextToPSPMem() {
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, context_.ptr, sizeof(SceAtracContext), "AtracContext");
|
||||
}
|
||||
|
||||
void Track::DebugLog() {
|
||||
DEBUG_LOG(ME, "ATRAC analyzed: %s channels: %d filesize: %d bitrate: %d kbps jointStereo: %d",
|
||||
codecType == PSP_MODE_AT_3 ? "AT3" : "AT3Plus", channels, fileSize, bitrate / 1024, jointStereo);
|
||||
DEBUG_LOG(ME, "dataoff: %d firstSampleOffset: %d endSample: %d", dataByteOffset, firstSampleOffset, endSample);
|
||||
DEBUG_LOG(ME, "loopStartSample: %d loopEndSample: %d", loopStartSample, loopEndSample);
|
||||
}
|
||||
|
||||
int Atrac::Analyze(u32 addr, u32 size) {
|
||||
track_ = {};
|
||||
first_ = {};
|
||||
@@ -255,6 +262,7 @@ int Atrac::Analyze(u32 addr, u32 size) {
|
||||
|
||||
int retval = AnalyzeAtracTrack(addr, size, &track_);
|
||||
first_._filesize_dontuse = track_.fileSize;
|
||||
track_.DebugLog();
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -397,7 +405,7 @@ int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) {
|
||||
case DATA_CHUNK_MAGIC:
|
||||
{
|
||||
bfoundData = true;
|
||||
track->dataOff = offset;
|
||||
track->dataByteOffset = offset;
|
||||
dataChunkSize = chunkSize;
|
||||
if (track->fileSize < offset + chunkSize) {
|
||||
WARN_LOG_REPORT(ME, "Atrac data chunk extends beyond riff chunk");
|
||||
@@ -419,8 +427,8 @@ int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) {
|
||||
|
||||
// set the loopStartSample_ and loopEndSample_ by loopinfo_
|
||||
if (track->loopinfo.size() > 0) {
|
||||
track->loopStartSample = track->loopinfo[0].startSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust;
|
||||
track->loopEndSample = track->loopinfo[0].endSample + ::FirstOffsetExtra(track->codecType) + sampleOffsetAdjust;
|
||||
track->loopStartSample = track->loopinfo[0].startSample + track->FirstOffsetExtra() + sampleOffsetAdjust;
|
||||
track->loopEndSample = track->loopinfo[0].endSample + track->FirstOffsetExtra() + sampleOffsetAdjust;
|
||||
} else {
|
||||
track->loopStartSample = -1;
|
||||
track->loopEndSample = -1;
|
||||
@@ -429,11 +437,11 @@ int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) {
|
||||
// if there is no correct endsample, try to guess it
|
||||
if (track->endSample <= 0 && track->bytesPerFrame != 0) {
|
||||
track->endSample = (dataChunkSize / track->bytesPerFrame) * track->SamplesPerFrame();
|
||||
track->endSample -= track->firstSampleOffset + ::FirstOffsetExtra(track->codecType);
|
||||
track->endSample -= track->FirstSampleOffsetFull();
|
||||
}
|
||||
track->endSample -= 1;
|
||||
|
||||
if (track->loopEndSample != -1 && track->loopEndSample > track->endSample + track->firstSampleOffset + (int)::FirstOffsetExtra(track->codecType)) {
|
||||
if (track->loopEndSample != -1 && track->loopEndSample > track->endSample + track->FirstSampleOffsetFull()) {
|
||||
return hleReportError(ME, ATRAC_ERROR_BAD_CODEC_PARAMS, "loop after end of data");
|
||||
}
|
||||
|
||||
@@ -501,10 +509,10 @@ int AnalyzeAA3Track(u32 addr, u32 size, u32 fileSize, Track *track) {
|
||||
return hleReportError(ME, ATRAC_ERROR_AA3_INVALID_DATA, "invalid codec type %d", buffer[32]);
|
||||
}
|
||||
|
||||
track->dataOff = 10 + tagSize + 96;
|
||||
track->dataByteOffset = 10 + tagSize + 96;
|
||||
track->firstSampleOffset = 0;
|
||||
if (track->endSample < 0 && track->bytesPerFrame != 0) {
|
||||
track->endSample = ((track->fileSize - track->dataOff) / track->bytesPerFrame) * track->SamplesPerFrame();
|
||||
track->endSample = ((track->fileSize - track->dataByteOffset) / track->bytesPerFrame) * track->SamplesPerFrame();
|
||||
}
|
||||
track->endSample -= 1;
|
||||
return 0;
|
||||
@@ -541,7 +549,7 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) {
|
||||
first_.offset = 0;
|
||||
first_.writableBytes = 0;
|
||||
} else {
|
||||
readOffset = track_.FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2);
|
||||
readOffset = track_.FileOffsetBySample(track_.loopStartSample - track_.FirstSampleOffsetFull() - track_.SamplesPerFrame() * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,7 +617,7 @@ void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) {
|
||||
|
||||
// Update the writable bytes. When streaming, this is just the number of bytes until the end.
|
||||
const u32 bufSizeAligned = (bufferMaxSize_ / track_.bytesPerFrame) * track_.bytesPerFrame;
|
||||
const int needsMoreFrames = FirstOffsetExtra();
|
||||
const int needsMoreFrames = track_.FirstOffsetExtra(); // ?
|
||||
|
||||
bufferInfo->first.writePosPtr = first_.addr;
|
||||
bufferInfo->first.writableBytes = std::min(track_.fileSize - sampleFileOffset, bufSizeAligned);
|
||||
@@ -619,7 +627,7 @@ void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) {
|
||||
} else {
|
||||
bufferInfo->first.minWriteBytes = track_.bytesPerFrame * 2;
|
||||
}
|
||||
if ((u32)sample < (u32)track_.firstSampleOffset && sampleFileOffset != track_.dataOff) {
|
||||
if ((u32)sample < (u32)track_.firstSampleOffset && sampleFileOffset != track_.dataByteOffset) {
|
||||
sampleFileOffset -= track_.bytesPerFrame;
|
||||
}
|
||||
bufferInfo->first.filePos = sampleFileOffset;
|
||||
@@ -670,8 +678,8 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels,
|
||||
ignoreDataBuf_ = true;
|
||||
}
|
||||
if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP || bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END || bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) {
|
||||
bufferHeaderSize_ = track_.dataOff;
|
||||
bufferPos_ = track_.dataOff + track_.bytesPerFrame;
|
||||
bufferHeaderSize_ = track_.dataByteOffset;
|
||||
bufferPos_ = track_.dataByteOffset + track_.bytesPerFrame;
|
||||
bufferValidBytes_ = first_.size - bufferPos_;
|
||||
}
|
||||
|
||||
@@ -709,7 +717,7 @@ u32 Atrac::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {
|
||||
return hleLogSuccessI(ME, 0);
|
||||
}
|
||||
|
||||
int Atrac::GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) {
|
||||
int AtracBase::GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) {
|
||||
if (BufferState() != ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) {
|
||||
// Writes zeroes in this error case.
|
||||
*fileOffset = 0;
|
||||
@@ -744,7 +752,7 @@ void Atrac::UpdateBufferState() {
|
||||
if (track_.loopEndSample <= 0) {
|
||||
// There's no looping, but we need to stream the data in our buffer.
|
||||
bufferState_ = ATRAC_STATUS_STREAMED_WITHOUT_LOOP;
|
||||
} else if (track_.loopEndSample == track_.endSample + track_.firstSampleOffset + (int)FirstOffsetExtra()) {
|
||||
} else if (track_.loopEndSample == track_.endSample + track_.FirstSampleOffsetFull()) {
|
||||
bufferState_ = ATRAC_STATUS_STREAMED_LOOP_FROM_END;
|
||||
} else {
|
||||
bufferState_ = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER;
|
||||
@@ -779,15 +787,15 @@ int Atrac::AddStreamData(u32 bytesToAdd) {
|
||||
|
||||
if (PSP_CoreParameter().compat.flags().AtracLoopHack && bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && RemainingFrames() > 2) {
|
||||
loopNum_++;
|
||||
SeekToSample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset);
|
||||
SeekToSample(track_.loopStartSample - track_.FirstSampleOffsetFull());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
|
||||
int addbytes = std::min(bytesToAdd, track_.fileSize - first_.fileoffset - FirstOffsetExtra());
|
||||
Memory::Memcpy(dataBuf_ + first_.fileoffset + FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData");
|
||||
int addbytes = std::min(bytesToAdd, track_.fileSize - first_.fileoffset - track_.FirstOffsetExtra());
|
||||
Memory::Memcpy(dataBuf_ + first_.fileoffset + track_.FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData");
|
||||
first_.size += bytesToAdd;
|
||||
if (first_.size >= track_.fileSize) {
|
||||
first_.size = track_.fileSize;
|
||||
@@ -802,7 +810,7 @@ u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
|
||||
|
||||
u32 Atrac::GetNextSamples() {
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
u32 skipSamples = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
u32 skipSamples = track_.FirstSampleOffsetFull();
|
||||
u32 firstSamples = (track_.SamplesPerFrame() - skipSamples) % track_.SamplesPerFrame();
|
||||
u32 numSamples = track_.endSample + 1 - currentSample_;
|
||||
if (currentSample_ == 0 && firstSamples != 0) {
|
||||
@@ -830,7 +838,7 @@ void Atrac::ForceSeekToSample(int sample) {
|
||||
|
||||
void Atrac::SeekToSample(int sample) {
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
const u32 offsetSamples = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
const u32 offsetSamples = track_.FirstSampleOffsetFull();
|
||||
const u32 unalignedSamples = (offsetSamples + sample) % track_.SamplesPerFrame();
|
||||
int seekFrame = sample + offsetSamples - unalignedSamples;
|
||||
|
||||
@@ -840,12 +848,12 @@ void Atrac::SeekToSample(int sample) {
|
||||
|
||||
int adjust = 0;
|
||||
if (sample == 0) {
|
||||
int offsetSamples = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
int offsetSamples = track_.FirstSampleOffsetFull();
|
||||
adjust = -(int)(offsetSamples % track_.SamplesPerFrame());
|
||||
}
|
||||
const u32 off = track_.FileOffsetBySample(sample + adjust);
|
||||
const u32 backfill = track_.bytesPerFrame * 2;
|
||||
const u32 start = off - track_.dataOff < backfill ? track_.dataOff : off - backfill;
|
||||
const u32 start = off - track_.dataByteOffset < backfill ? track_.dataByteOffset : off - backfill;
|
||||
|
||||
for (u32 pos = start; pos < off; pos += track_.bytesPerFrame) {
|
||||
decoder_->Decode(BufferStart() + pos, track_.bytesPerFrame, nullptr, 2, nullptr, nullptr);
|
||||
@@ -861,12 +869,12 @@ int Atrac::RemainingFrames() const {
|
||||
return PSP_ATRAC_ALLDATA_IS_ON_MEMORY;
|
||||
}
|
||||
|
||||
u32 currentFileOffset = track_.FileOffsetBySample(currentSample_ - track_.SamplesPerFrame() + FirstOffsetExtra());
|
||||
u32 currentFileOffset = track_.FileOffsetBySample(currentSample_ - track_.SamplesPerFrame() + track_.FirstOffsetExtra());
|
||||
if (first_.fileoffset >= track_.fileSize) {
|
||||
if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) {
|
||||
return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY;
|
||||
}
|
||||
int loopEndAdjusted = track_.loopEndSample - FirstOffsetExtra() - track_.firstSampleOffset;
|
||||
int loopEndAdjusted = track_.loopEndSample - track_.FirstOffsetExtra() - track_.firstSampleOffset;
|
||||
if (bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && currentSample_ > loopEndAdjusted) {
|
||||
// No longer looping in this case, outside the loop.
|
||||
return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY;
|
||||
@@ -926,7 +934,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
|
||||
u32 numSamples = 0;
|
||||
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
int offsetSamples = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
int offsetSamples = track_.FirstSampleOffsetFull();
|
||||
int skipSamples = 0;
|
||||
u32 maxSamples = track_.endSample + 1 - currentSample_;
|
||||
u32 unalignedSamples = (offsetSamples + currentSample_) % track_.SamplesPerFrame();
|
||||
@@ -939,6 +947,8 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
|
||||
if (skipSamples != 0 && bufferHeaderSize_ == 0) {
|
||||
// Skip the initial frame used to load state for the looped frame.
|
||||
// TODO: We will want to actually read this in.
|
||||
// TODO again: This seems to happen on the first frame of playback regardless of loops.
|
||||
// Can't be good.
|
||||
ConsumeFrame();
|
||||
}
|
||||
|
||||
@@ -1002,20 +1012,20 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
|
||||
int finishFlag = 0;
|
||||
// TODO: Verify.
|
||||
bool hitEnd = currentSample_ >= track_.endSample || (numSamples == 0 && first_.size >= track_.fileSize);
|
||||
int loopEndAdjusted = track_.loopEndSample - FirstOffsetExtra() - track_.firstSampleOffset;
|
||||
int loopEndAdjusted = track_.loopEndSample - track_.FirstSampleOffsetFull();
|
||||
if ((hitEnd || currentSample_ > loopEndAdjusted) && loopNum != 0) {
|
||||
SeekToSample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset);
|
||||
SeekToSample(track_.loopStartSample - track_.FirstSampleOffsetFull());
|
||||
if (bufferState_ != ATRAC_STATUS_FOR_SCESAS) {
|
||||
if (loopNum_ > 0)
|
||||
loopNum_--;
|
||||
}
|
||||
if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) {
|
||||
// Whatever bytes we have left were added from the loop.
|
||||
u32 loopOffset = track_.FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2);
|
||||
u32 loopOffset = track_.FileOffsetBySample(track_.loopStartSample - track_.FirstSampleOffsetFull() - track_.SamplesPerFrame() * 2);
|
||||
// TODO: Hmm, need to manage the buffer better. But don't move fileoffset if we already have valid data.
|
||||
if (loopOffset > first_.fileoffset || loopOffset + bufferValidBytes_ < first_.fileoffset) {
|
||||
// Skip the initial frame at the start.
|
||||
first_.fileoffset = track_.FileOffsetBySample(track_.loopStartSample - FirstOffsetExtra() - track_.firstSampleOffset - track_.SamplesPerFrame() * 2);
|
||||
first_.fileoffset = track_.FileOffsetBySample(track_.loopStartSample - track_.FirstSampleOffsetFull() - track_.SamplesPerFrame() * 2);
|
||||
}
|
||||
}
|
||||
} else if (hitEnd) {
|
||||
@@ -1033,15 +1043,15 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atrac::SetLoopNum(int loopNum) {
|
||||
void AtracBase::SetLoopNum(int loopNum) {
|
||||
// Spammed in MHU
|
||||
loopNum_ = loopNum;
|
||||
if (loopNum != 0 && track_.loopinfo.size() == 0) {
|
||||
// Just loop the whole audio
|
||||
// This is a rare modification of track_ after the fact.
|
||||
// Maybe we can get away with setting these by default.
|
||||
track_.loopStartSample = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
track_.loopEndSample = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra();
|
||||
track_.loopStartSample = track_.FirstSampleOffsetFull();
|
||||
track_.loopEndSample = track_.endSample + track_.FirstSampleOffsetFull();
|
||||
}
|
||||
WriteContextToPSPMem();
|
||||
}
|
||||
@@ -1124,7 +1134,7 @@ void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) {
|
||||
track_.jointStereo = false;
|
||||
}
|
||||
|
||||
track_.dataOff = 0;
|
||||
track_.dataByteOffset = 0;
|
||||
first_.size = 0;
|
||||
track_.fileSize = track_.bytesPerFrame; // not really meaningful
|
||||
bufferState_ = ATRAC_STATUS_LOW_LEVEL;
|
||||
|
||||
+49
-21
@@ -105,24 +105,42 @@ struct AtracLoopInfo {
|
||||
|
||||
class AudioDecoder;
|
||||
|
||||
inline u32 FirstOffsetExtra(int codecType) {
|
||||
return codecType == PSP_MODE_AT_3_PLUS ? 368 : 69;
|
||||
}
|
||||
|
||||
struct Track {
|
||||
u32 fileSize;
|
||||
// This both does and doesn't belong in Track - it's fixed for an Atrac instance. Oh well.
|
||||
u32 codecType;
|
||||
u16 bytesPerFrame;
|
||||
int firstSampleOffset;
|
||||
int endSample;
|
||||
// Offset of the first sample in the input buffer
|
||||
int dataOff = 0;
|
||||
u32 codecType = 0;
|
||||
|
||||
// Size of the full track being streamed or played. Can be a lot larger than the in-memory buffer in the streaming modes.
|
||||
u32 fileSize = 0;
|
||||
|
||||
// Not really used for much except queries, this keeps track of the bitrate of the track.
|
||||
u32 bitrate = 64;
|
||||
|
||||
// Signifies whether to use a more efficient coding mode with less stereo separation. For our purposes, just metadata.
|
||||
int jointStereo = 0;
|
||||
|
||||
// Number of audio channels in the track.
|
||||
u16 channels = 0;
|
||||
|
||||
// The size of an encoded frame in bytes.
|
||||
u16 bytesPerFrame = 0;
|
||||
|
||||
// Byte offset of the first encoded frame in the input buffer. Note: Some samples may be skipped according to firstSampleOffset.
|
||||
int dataByteOffset = 0;
|
||||
|
||||
// How many samples to skip from the beginning of a track when decoding.
|
||||
// Actually, the real number is this added to FirstOffsetExtra(codecType). You can call
|
||||
// FirstSampleOffset2() to get that.
|
||||
// Some use of these offsets around the code seem to be inconsistent, sometimes the extra is included,
|
||||
// sometimes not.
|
||||
int firstSampleOffset = 0;
|
||||
|
||||
// Last sample number. Though, we made it so in Analyze, it's exclusive in the file.
|
||||
// Does not take firstSampleOffset into account.
|
||||
int endSample = 0;
|
||||
|
||||
// Loop configuration. The PSP only supports one loop but we store them all.
|
||||
std::vector<AtracLoopInfo> loopinfo;
|
||||
// The actual used loop offsets. These appear to be raw offsets, not taking FirstSampleOffset2() into account.
|
||||
int loopStartSample = -1;
|
||||
int loopEndSample = -1;
|
||||
|
||||
@@ -131,7 +149,16 @@ struct Track {
|
||||
return bytesPerFrame;
|
||||
}
|
||||
|
||||
// Output frame size
|
||||
inline int FirstOffsetExtra() const {
|
||||
return codecType == PSP_MODE_AT_3_PLUS ? 368 : 69;
|
||||
}
|
||||
|
||||
// Includes the extra offset. See firstSampleOffset comment above.
|
||||
int FirstSampleOffsetFull() const {
|
||||
return FirstOffsetExtra() + firstSampleOffset;
|
||||
}
|
||||
|
||||
// Output frame size, different between the two supported codecs.
|
||||
u32 SamplesPerFrame() const {
|
||||
return codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES;
|
||||
}
|
||||
@@ -144,14 +171,17 @@ struct Track {
|
||||
bitrate = (bitrate + 511) >> 10;
|
||||
}
|
||||
|
||||
// This appears to be buggy, should probably include FirstOffsetExtra?
|
||||
// Actually the units don't even make sense here.
|
||||
u32 DecodePosBySample(int sample) const {
|
||||
return (u32)(firstSampleOffset + sample / (int)SamplesPerFrame() * bytesPerFrame);
|
||||
}
|
||||
|
||||
// This appears to be buggy, should probably include FirstOffsetExtra?
|
||||
u32 FileOffsetBySample(int sample) const {
|
||||
int offsetSample = sample + firstSampleOffset;
|
||||
int frameOffset = offsetSample / (int)SamplesPerFrame();
|
||||
return (u32)(dataOff + bytesPerFrame + frameOffset * bytesPerFrame);
|
||||
return (u32)(dataByteOffset + bytesPerFrame + frameOffset * bytesPerFrame);
|
||||
}
|
||||
|
||||
void AnalyzeReset() {
|
||||
@@ -162,6 +192,8 @@ struct Track {
|
||||
channels = 2;
|
||||
// TODO: Could probably reset more.
|
||||
}
|
||||
|
||||
void DebugLog();
|
||||
};
|
||||
|
||||
int AnalyzeAA3Track(u32 addr, u32 size, u32 filesize, Track *track);
|
||||
@@ -202,9 +234,6 @@ public:
|
||||
AudioDecoder *Decoder() const {
|
||||
return decoder_;
|
||||
}
|
||||
u32 FirstOffsetExtra() const {
|
||||
return ::FirstOffsetExtra(track_.codecType);
|
||||
}
|
||||
|
||||
void CreateDecoder();
|
||||
|
||||
@@ -221,12 +250,13 @@ public:
|
||||
virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0;
|
||||
virtual int AddStreamData(u32 bytesToAdd) = 0;
|
||||
virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0;
|
||||
virtual void SetLoopNum(int loopNum) = 0;
|
||||
virtual void SetLoopNum(int loopNum);
|
||||
virtual u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) = 0;
|
||||
virtual void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) = 0;
|
||||
virtual int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) = 0;
|
||||
|
||||
virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize);
|
||||
virtual u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0;
|
||||
virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) = 0;
|
||||
virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) = 0;
|
||||
virtual u32 GetNextSamples() = 0;
|
||||
virtual void InitLowLevel(u32 paramsAddr, bool jointStereo) = 0;
|
||||
@@ -274,12 +304,10 @@ public:
|
||||
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
|
||||
int AddStreamData(u32 bytesToAdd) override;
|
||||
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
|
||||
void SetLoopNum(int loopNum) override;
|
||||
u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override;
|
||||
void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override;
|
||||
int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) override;
|
||||
u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;
|
||||
int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) override;
|
||||
u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override;
|
||||
u32 GetNextSamples() override;
|
||||
void InitLowLevel(u32 paramsAddr, bool jointStereo) override;
|
||||
@@ -302,7 +330,7 @@ private:
|
||||
void CalculateStreamInfo(u32 *readOffset);
|
||||
|
||||
InputBuffer first_{};
|
||||
InputBuffer second_{};
|
||||
InputBuffer second_{}; // only addr, size, fileoffset are used (incomplete)
|
||||
|
||||
u8 *dataBuf_ = nullptr;
|
||||
// Indicates that the dataBuf_ array should not be used.
|
||||
|
||||
+35
-14
@@ -3,6 +3,37 @@
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
#include "Core/HLE/AtracCtx2.h"
|
||||
#include "Core/HW/Atrac3Standalone.h"
|
||||
|
||||
// Convenient command line:
|
||||
// Windows\x64\debug\PPSSPPHeadless.exe --root pspautotests/tests/../ --compare --timeout=5 --new-atrac --graphics=software pspautotests/tests/audio/atrac/decode.prx
|
||||
|
||||
// See the big comment in sceAtrac.cpp for an overview of the different modes of operation.
|
||||
//
|
||||
// Test cases
|
||||
//
|
||||
// Halfway buffer
|
||||
//
|
||||
// * None found yet
|
||||
//
|
||||
// All-data-loaded
|
||||
//
|
||||
// * MotoGP (menu music with specified loop). Simple repeated calls to sceAtracDecodeData
|
||||
// * Archer MacLean's Mercury (in-game, not menu)
|
||||
// * Crisis Core
|
||||
//
|
||||
// Streaming
|
||||
//
|
||||
// - Good ones (early)
|
||||
// * Everybody's Golf 2 (0x2000 buffer size, loop from end)
|
||||
// * Burnout Legends (no loop, 0x1800 buffer size)
|
||||
// * Suicide Barbie
|
||||
// - Others
|
||||
// * Bleach
|
||||
// * God of War: Chains of Olympus
|
||||
// * Ape Academy 2 (bufsize 8192)
|
||||
// * Half Minute Hero (bufsize 65536)
|
||||
// * Flatout (tricky! needs investigation)
|
||||
|
||||
void Atrac2::DoState(PointerWrap &p) {
|
||||
_assert_msg_(false, "Savestates not yet support with new Atrac implementation.\n\nTurn it off in Developer settings.\n\n");
|
||||
@@ -28,14 +59,14 @@ void Atrac2::WriteContextToPSPMem() {
|
||||
// TODO: Should we just keep this in PSP ram then, or something?
|
||||
context->info.state = bufferState_;
|
||||
if (track_.firstSampleOffset != 0) {
|
||||
context->info.samplesPerChan = track_.firstSampleOffset + FirstOffsetExtra();
|
||||
context->info.samplesPerChan = track_.FirstSampleOffsetFull();
|
||||
} else {
|
||||
context->info.samplesPerChan = (track_.codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
}
|
||||
context->info.sampleSize = track_.bytesPerFrame;
|
||||
context->info.numChan = track_.channels;
|
||||
context->info.dataOff = track_.dataOff;
|
||||
context->info.endSample = track_.endSample + track_.firstSampleOffset + FirstOffsetExtra();
|
||||
context->info.dataOff = track_.dataByteOffset;
|
||||
context->info.endSample = track_.endSample + track_.FirstSampleOffsetFull();
|
||||
context->info.dataEnd = track_.fileSize;
|
||||
context->info.curOff = 0; // first_.fileoffset;
|
||||
context->info.decodePos = track_.DecodePosBySample(currentSample_);
|
||||
@@ -83,10 +114,6 @@ u32 Atrac2::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atrac2::SetLoopNum(int loopNum) {
|
||||
|
||||
}
|
||||
|
||||
u32 Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) {
|
||||
return 0;
|
||||
}
|
||||
@@ -108,12 +135,6 @@ u32 Atrac2::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Atrac2::GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) {
|
||||
*fileOffset = 0;
|
||||
*desiredSize = 0;
|
||||
return hleLogSuccessInfoI(ME, ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED, "not needed");
|
||||
}
|
||||
|
||||
u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) {
|
||||
|
||||
return 0;
|
||||
@@ -137,7 +158,7 @@ void Atrac2::InitLowLevel(u32 paramsAddr, bool jointStereo) {
|
||||
track_.bitrate = ((track_.bitrate >> 11) + 8) & 0xFFFFFFF0;
|
||||
track_.jointStereo = false;
|
||||
}
|
||||
track_.dataOff = 0;
|
||||
track_.dataByteOffset = 0;
|
||||
bufferState_ = ATRAC_STATUS_LOW_LEVEL;
|
||||
currentSample_ = 0;
|
||||
CreateDecoder();
|
||||
|
||||
@@ -15,17 +15,16 @@ public:
|
||||
|
||||
int CurrentSample() const override { return currentSample_; }
|
||||
int RemainingFrames() const override;
|
||||
u32 SecondBufferSize() const override;
|
||||
|
||||
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
|
||||
int AddStreamData(u32 bytesToAdd) override;
|
||||
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
|
||||
void SetLoopNum(int loopNum) override;
|
||||
u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override;
|
||||
void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override;
|
||||
int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) override;
|
||||
u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;
|
||||
int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) override;
|
||||
u32 SecondBufferSize() const override;
|
||||
|
||||
u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override;
|
||||
u32 GetNextSamples() override;
|
||||
void InitLowLevel(u32 paramsAddr, bool jointStereo) override;
|
||||
|
||||
@@ -405,7 +405,7 @@ static u32 sceAtracGetNextDecodePosition(int atracID, u32 outposAddr) {
|
||||
if (Memory::IsValidAddress(outposAddr)) {
|
||||
if (atrac->CurrentSample() >= atrac->GetTrack().endSample) {
|
||||
Memory::WriteUnchecked_U32(0, outposAddr);
|
||||
return hleLogSuccessI(ME, ATRAC_ERROR_ALL_DATA_DECODED, "all data decoded");
|
||||
return hleLogSuccessI(ME, ATRAC_ERROR_ALL_DATA_DECODED, "all data decoded - beyond endSample");
|
||||
} else {
|
||||
Memory::WriteUnchecked_U32(atrac->CurrentSample(), outposAddr);
|
||||
return hleLogSuccessI(ME, 0);
|
||||
@@ -488,10 +488,10 @@ static u32 sceAtracGetSoundSample(int atracID, u32 outEndSampleAddr, u32 outLoop
|
||||
*outEndSample = atrac->GetTrack().endSample;
|
||||
auto outLoopStart = PSPPointer<u32_le>::Create(outLoopStartSampleAddr);
|
||||
if (outLoopStart.IsValid())
|
||||
*outLoopStart = atrac->GetTrack().loopStartSample == -1 ? -1 : atrac->GetTrack().loopStartSample - atrac->GetTrack().firstSampleOffset - atrac->FirstOffsetExtra();
|
||||
*outLoopStart = atrac->GetTrack().loopStartSample == -1 ? -1 : atrac->GetTrack().loopStartSample - atrac->GetTrack().FirstSampleOffsetFull();
|
||||
auto outLoopEnd = PSPPointer<u32_le>::Create(outLoopEndSampleAddr);
|
||||
if (outLoopEnd.IsValid())
|
||||
*outLoopEnd = atrac->GetTrack().loopEndSample == -1 ? -1 : atrac->GetTrack().loopEndSample - atrac->GetTrack().firstSampleOffset - atrac->FirstOffsetExtra();
|
||||
*outLoopEnd = atrac->GetTrack().loopEndSample == -1 ? -1 : atrac->GetTrack().loopEndSample - atrac->GetTrack().FirstSampleOffsetFull();
|
||||
|
||||
if (!outEndSample.IsValid() || !outLoopStart.IsValid() || !outLoopEnd.IsValid()) {
|
||||
return hleReportError(ME, 0, "invalid address");
|
||||
|
||||
@@ -319,6 +319,7 @@ int main(int argc, const char* argv[])
|
||||
{
|
||||
PROFILE_INIT();
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
SetCleanExitOnAssert();
|
||||
timeBeginPeriod(1);
|
||||
#else
|
||||
// Ignore sigpipe.
|
||||
@@ -338,6 +339,7 @@ int main(int argc, const char* argv[])
|
||||
GPUCore gpuCore = GPUCORE_SOFTWARE;
|
||||
CPUCore cpuCore = CPUCore::JIT;
|
||||
int debuggerPort = -1;
|
||||
bool newAtrac = false;
|
||||
|
||||
std::vector<std::string> testFilenames;
|
||||
const char *mountIso = nullptr;
|
||||
@@ -374,6 +376,8 @@ int main(int argc, const char* argv[])
|
||||
testOptions.bench = true;
|
||||
else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))
|
||||
testOptions.verbose = true;
|
||||
else if (!strcmp(argv[i], "--new-atrac"))
|
||||
newAtrac = true;
|
||||
else if (!strncmp(argv[i], "--graphics=", strlen("--graphics=")) && strlen(argv[i]) > strlen("--graphics="))
|
||||
{
|
||||
const char *gpuName = argv[i] + strlen("--graphics=");
|
||||
@@ -497,6 +501,7 @@ int main(int argc, const char* argv[])
|
||||
g_Config.iGlobalVolume = VOLUME_FULL;
|
||||
g_Config.iReverbVolume = VOLUME_FULL;
|
||||
g_Config.internalDataDirectory.clear();
|
||||
g_Config.bUseNewAtrac = newAtrac;
|
||||
|
||||
Path exePath = File::GetExeDirectory();
|
||||
g_Config.flash0Directory = exePath / "assets/flash0";
|
||||
|
||||
Reference in new issue
Block a user