Merge pull request #20117 from hrydgard/split-out-track

Atrac: Split out track analysis
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2025-03-16 16:27:00 +01:00
commit a0cc07559e
5 files changed
+169 -120

No files matched your search

+12 -16
View File
@@ -241,8 +241,7 @@ void Track::DebugLog() {
DEBUG_LOG(Log::ME, "loopStartSample: %d loopEndSample: %d", loopStartSample, loopEndSample);
}
int Atrac::Analyze(u32 addr, u32 size) {
track_ = {};
int Atrac::Analyze(const Track &track, u32 addr, u32 size, u32 fileSize) {
first_ = {};
first_.addr = addr;
first_.size = size;
@@ -259,16 +258,18 @@ int Atrac::Analyze(u32 addr, u32 size) {
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
}
bool aa3 = fileSize != 0;
// TODO: Validate stuff.
if (Memory::ReadUnchecked_U32(addr) != RIFF_CHUNK_MAGIC) {
if (!aa3 && Memory::ReadUnchecked_U32(addr) != RIFF_CHUNK_MAGIC) {
ERROR_LOG(Log::ME, "Couldn't find RIFF header");
return SCE_ERROR_ATRAC_UNKNOWN_FORMAT;
}
int retval = AnalyzeAtracTrack(addr, size, &track_);
first_._filesize_dontuse = track_.fileSize;
track_ = track;
first_._filesize_dontuse = aa3 ? fileSize : track_.fileSize;
track_.DebugLog();
return retval;
return 0;
}
int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) {
@@ -537,16 +538,6 @@ int AnalyzeAA3Track(u32 addr, u32 size, u32 fileSize, Track *track) {
return 0;
}
int Atrac::AnalyzeAA3(u32 addr, u32 size, u32 fileSize) {
first_.addr = addr;
first_.size = size;
first_._filesize_dontuse = fileSize;
AnalyzeReset();
return AnalyzeAA3Track(addr, size, fileSize, &track_);
}
int Atrac::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const {
*endSample = track_.endSample;
*loopStartSample = track_.loopStartSample == -1 ? -1 : track_.loopStartSample - track_.FirstSampleOffsetFull();
@@ -756,6 +747,11 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels)
}
CreateDecoder();
INFO_LOG(Log::ME, "Atrac::SetData (buffer=%08x, readSize=%d, bufferSize=%d): %s %s (%d channels) audio", buffer, readSize, bufferSize, codecName, channelName, track_.channels);
if (track_.channels == 2 && outputChannels == 1) {
// We still do all the tasks, we just return this error.
return SCE_ERROR_ATRAC_NOT_MONO;
}
return 0;
}
+16 -6
View File
@@ -194,8 +194,8 @@ public:
outputChannels_ = channels;
}
// Refactor?
int atracID_ = -1;
virtual void SetID(int id) = 0;
virtual int GetID() const = 0;
PSPPointer<SceAtracContext> context_{};
@@ -223,8 +223,8 @@ public:
virtual int BytesPerFrame() const = 0;
virtual int SamplesPerFrame() const = 0;
virtual int Analyze(u32 addr, u32 size) = 0;
virtual int AnalyzeAA3(u32 addr, u32 size, u32 filesize) = 0;
// Set filesize to 0 for autodetect, unless you are using aa3.
virtual int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) = 0;
void UpdateContextFromPSPMem();
virtual void WriteContextToPSPMem() = 0;
@@ -275,11 +275,18 @@ public:
void DoState(PointerWrap &p) override;
void WriteContextToPSPMem() override;
int Analyze(u32 addr, u32 size) override;
int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override;
int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override;
int GetNextDecodePosition(int *pos) const override;
int RemainingFrames() const override;
void SetID(int id) override {
atracID_ = id;
}
int GetID() const override {
return atracID_;
}
u32 SecondBufferSize() const override {
return second_.size;
}
@@ -361,4 +368,7 @@ private:
u32 bufferPos_ = 0;
u32 bufferValidBytes_ = 0;
u32 bufferHeaderSize_ = 0;
// Refactor?
int atracID_ = -1;
};
+2 -42
View File
@@ -44,50 +44,10 @@ void Atrac2::DoState(PointerWrap &p) {
}
void Atrac2::WriteContextToPSPMem() {
if (!context_.IsValid()) {
return;
}
// context points into PSP memory.
SceAtracContext *context = context_;
context->info.buffer = 0; // bufferAddr_; // first_.addr;
context->info.bufferByte = 0; // bufferMaxSize_;
context->info.secondBuffer = 0; // TODO
context->info.secondBufferByte = 0; // TODO
context->info.codec = track_.codecType;
context->info.loopNum = loopNum_;
context->info.loopStart = track_.loopStartSample > 0 ? track_.loopStartSample : 0;
context->info.loopEnd = track_.loopEndSample > 0 ? track_.loopEndSample : 0;
// Note that we read in the state when loading the atrac object, so it's safe
// to update it back here all the time. Some games, like Sol Trigger, change it.
// TODO: Should we just keep this in PSP ram then, or something?
context->info.state = bufferState_;
if (track_.firstSampleOffset != 0) {
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_.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_);
context->info.streamDataByte = 0; // first_.size - track_.dataOff;
u8 *buf = (u8 *)context;
*(u32_le *)(buf + 0xfc) = atracID_;
NotifyMemInfo(MemBlockFlags::WRITE, context_.ptr, sizeof(SceAtracContext), "AtracContext");
}
int Atrac2::Analyze(u32 addr, u32 size) {
return AnalyzeAtracTrack(addr, size, &track_);
}
int Atrac2::AnalyzeAA3(u32 addr, u32 size, u32 filesize) {
return AnalyzeAA3Track(addr, size, filesize, &track_);
int Atrac2::Analyze(const Track &track, u32 addr, u32 size, u32 filesize) {
return 0;
}
int Atrac2::RemainingFrames() const {
+4 -2
View File
@@ -11,8 +11,10 @@ public:
void DoState(PointerWrap &p) override;
void WriteContextToPSPMem() override;
int Analyze(u32 addr, u32 size) override;
int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override;
int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override;
void SetID(int id) override {}
int GetID() const override { return 0; }
int GetNextDecodePosition(int *pos) const { return 0; }
int RemainingFrames() const override;
+135 -54
View File
@@ -180,11 +180,11 @@ static AtracBase *getAtrac(int atracID) {
return atrac;
}
static int createAtrac(AtracBase *atrac) {
static int RegisterAtrac(AtracBase *atrac) {
for (int i = 0; i < (int)ARRAY_SIZE(atracContexts); ++i) {
if (atracContextTypes[i] == atrac->CodecType() && atracContexts[i] == 0) {
atracContexts[i] = atrac;
atrac->atracID_ = i;
atrac->SetID(i);
return i;
}
}
@@ -210,7 +210,7 @@ static u32 sceAtracGetAtracID(int codecType) {
}
AtracBase *atrac = allocAtrac(codecType);
int atracID = createAtrac(atrac);
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
@@ -571,12 +571,22 @@ static u32 sceAtracSetHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u32 b
return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large");
}
int ret = atrac->Analyze(buffer, readSize);
Track track;
int ret = AnalyzeAtracTrack(buffer, readSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (track.codecType != atracContextTypes[atracID]) {
// TODO: Should this not change the buffer size?
return hleLogError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data");
}
ret = atrac->Analyze(track, buffer, readSize, 0);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
ret = atrac->SetData(buffer, readSize, bufferSize, 2);
// not sure the real delay time
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data", 100);
}
@@ -596,16 +606,20 @@ static u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_ATRACID, "bad atrac ID");
}
int ret = atrac->Analyze(buffer, bufferSize);
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (atrac->CodecType() != atracContextTypes[atracID]) {
if (track.codecType != atracContextTypes[atracID]) {
// TODO: Should this not change the buffer size?
return hleReportError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data");
}
ret = atrac->Analyze(track, buffer, bufferSize, 0);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
ret = atrac->SetData(buffer, bufferSize, bufferSize, 2);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data", 100);
}
@@ -618,39 +632,63 @@ static int sceAtracSetDataAndGetID(u32 buffer, int bufferSize) {
bufferSize = 0x10000000;
}
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
AtracBase *atrac = allocAtrac();
int ret = atrac->Analyze(buffer, bufferSize);
ret = atrac->Analyze(track, buffer, bufferSize, 0);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
ret = atrac->SetData(buffer, bufferSize, bufferSize, 2);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, bufferSize, bufferSize, 2);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100);
}
static int sceAtracSetHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bufferSize) {
if (readSize > bufferSize) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large");
}
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
AtracBase *atrac = allocAtrac();
int ret = atrac->Analyze(buffer, readSize);
ret = atrac->Analyze(track, buffer, readSize, 0);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
ret = atrac->SetData(buffer, readSize, bufferSize, 2);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, readSize, bufferSize, 2);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100);
}
static u32 sceAtracStartEntry() {
@@ -664,7 +702,6 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) {
if (err != 0) {
return hleLogError(Log::ME, err);
}
int ret = atrac->SetLoopNum(loopNum);
if (ret == SCE_ERROR_ATRAC_NO_LOOP_INFORMATION && loopNum == -1) {
// Not really an issue
@@ -752,21 +789,23 @@ static int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u
return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large");
}
int ret = atrac->Analyze(buffer, readSize);
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (atrac->Channels() != 1) {
// It seems it still sets the data.
atrac->SetData(buffer, readSize, bufferSize, 2);
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
} else {
ret = atrac->SetData(buffer, readSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100);
ret = atrac->Analyze(track, buffer, readSize, 0);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
ret = atrac->SetData(buffer, readSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100);
}
// Note: This doesn't seem to be part of any available libatrac3plus library.
// So we should probably remove it?
// HalfwayBuffer can fully replace it though, of course (just set readSize == bufferSize).
static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) {
AtracBase *atrac = getAtrac(atracID);
// Don't use AtracValidate* here.
@@ -774,81 +813,113 @@ static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_ATRACID, "bad atrac ID");
}
int ret = atrac->Analyze(buffer, bufferSize);
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (atrac->Channels() != 1) {
// It seems it still sets the data.
atrac->SetData(buffer, bufferSize, bufferSize, 2);
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
} else {
ret = atrac->SetData(buffer, bufferSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100);
ret = atrac->Analyze(track, buffer, bufferSize, 0);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
ret = atrac->SetData(buffer, bufferSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100);
}
// Note: This doesn't seem to be part of any available libatrac3plus library.
// See note in above function.
static int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) {
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (track.channels != 1) {
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
}
AtracBase *atrac = allocAtrac();
int ret = atrac->Analyze(buffer, bufferSize);
ret = atrac->Analyze(track, buffer, bufferSize, 0);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
if (atrac->Channels() != 1) {
ret = atrac->SetData(buffer, bufferSize, bufferSize, 1);
if (ret < 0) {
delete atrac;
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, bufferSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebugOrError(Log::ME, atracID), "atrac set data", 100);
}
static int sceAtracSetMOutHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bufferSize) {
if (readSize > bufferSize) {
return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large");
}
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
if (track.channels != 1) {
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
}
AtracBase *atrac = allocAtrac();
int ret = atrac->Analyze(buffer, readSize);
ret = atrac->Analyze(track, buffer, readSize, 0);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
if (atrac->Channels() != 1) {
ret = atrac->SetData(buffer, readSize, bufferSize, 1);
if (ret < 0) {
delete atrac;
return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data");
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, readSize, bufferSize, 1);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100);
}
static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, u32 metadataSizeAddr) {
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
AtracBase *atrac = allocAtrac();
int ret = atrac->AnalyzeAA3(buffer, bufferSize, fileSize);
ret = atrac->Analyze(track, buffer, bufferSize, fileSize);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
ret = atrac->SetData(buffer, bufferSize, bufferSize, 2);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, bufferSize, bufferSize, 2);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set aa3 data", 100);
}
static u32 _sceAtracGetContextAddress(int atracID) {
@@ -957,20 +1028,30 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf
return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large");
}
Track track;
int ret = AnalyzeAtracTrack(buffer, bufferSize, &track);
if (ret < 0) {
return hleLogError(Log::ME, ret);
}
AtracBase *atrac = allocAtrac();
int ret = atrac->AnalyzeAA3(buffer, readSize, fileSize);
ret = atrac->Analyze(track, buffer, readSize, fileSize);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = createAtrac(atrac);
ret = atrac->SetData(buffer, readSize, bufferSize, 2);
if (ret < 0) {
delete atrac;
return hleLogError(Log::ME, ret);
}
int atracID = RegisterAtrac(atrac);
if (atracID < 0) {
delete atrac;
return hleLogError(Log::ME, atracID, "no free ID");
}
ret = atrac->SetData(buffer, readSize, bufferSize, 2);
return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100);
return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100);
}
// External interface used by sceSas' AT3 integration.