Skip to content

Commit 16f9851

Browse files
authored
Merge pull request #20156 from hrydgard/reimplement-sas-atrac
Reimplement Atrac-through-SAS
2 parents aa87fee + 2af71d0 commit 16f9851

File tree

16 files changed

+389
-202
lines changed

16 files changed

+389
-202
lines changed

Core/HLE/AtracCtx.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -571,21 +571,6 @@ int Atrac::AddStreamData(u32 bytesToAdd) {
571571
return 0;
572572
}
573573

574-
u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
575-
int addbytes = std::min(bytesToAdd, track_.fileSize - first_.fileoffset - track_.FirstOffsetExtra());
576-
Memory::Memcpy(dataBuf_ + first_.fileoffset + track_.FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData");
577-
first_.size += bytesToAdd;
578-
if (first_.size >= track_.fileSize) {
579-
first_.size = track_.fileSize;
580-
if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER)
581-
bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED;
582-
}
583-
first_.fileoffset += addbytes;
584-
// refresh context_
585-
WriteContextToPSPMem();
586-
return 0;
587-
}
588-
589574
u32 Atrac::GetNextSamples() {
590575
if (currentSample_ >= track_.endSample) {
591576
return 0;
@@ -961,6 +946,25 @@ int Atrac::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, i
961946
return 0;
962947
}
963948

949+
void Atrac::CheckForSas() {
950+
SetOutputChannels(1);
951+
}
952+
953+
int Atrac::EnqueueForSas(u32 bufPtr, u32 bytesToAdd) {
954+
int addbytes = std::min(bytesToAdd, track_.fileSize - first_.fileoffset - track_.FirstOffsetExtra());
955+
Memory::Memcpy(dataBuf_ + first_.fileoffset + track_.FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData");
956+
first_.size += bytesToAdd;
957+
if (first_.size >= track_.fileSize) {
958+
first_.size = track_.fileSize;
959+
if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER)
960+
bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED;
961+
}
962+
first_.fileoffset += addbytes;
963+
// refresh context_
964+
WriteContextToPSPMem();
965+
return 0;
966+
}
967+
964968
void Atrac::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
965969
// Hack, but works.
966970
int samplesNum;

Core/HLE/AtracCtx.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ struct AtracResetBufferInfo {
3737
AtracSingleResetBufferInfo second;
3838
};
3939

40+
struct AtracSasStreamState {
41+
u32 bufPtr[2]{};
42+
u32 bufSize[2]{};
43+
int streamOffset = 0;
44+
int fileOffset = 0;
45+
int curBuffer = 0;
46+
bool isStreaming = false;
47+
48+
int CurPos() const {
49+
int retval = fileOffset - bufSize[curBuffer] + streamOffset;
50+
_dbg_assert_(retval >= 0);
51+
return retval;
52+
}
53+
};
4054

4155
const int PSP_ATRAC_ALLDATA_IS_ON_MEMORY = -1;
4256
const int PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY = -2;
@@ -112,7 +126,6 @@ class AtracBase {
112126

113127
virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0;
114128
virtual int AddStreamData(u32 bytesToAdd) = 0;
115-
virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0;
116129
virtual int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) = 0;
117130
virtual int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample, bool *delay) = 0;
118131
virtual int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) = 0;
@@ -121,10 +134,15 @@ class AtracBase {
121134
virtual int SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0;
122135
virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, int *SamplesNum, int *finish, int *remains) = 0;
123136
virtual int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) = 0;
124-
virtual void DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) = 0;
137+
125138
virtual u32 GetNextSamples() = 0;
126139
virtual void InitLowLevel(const Atrac3LowLevelParams &params, int codecType) = 0;
127140

141+
virtual void CheckForSas() = 0;
142+
virtual int EnqueueForSas(u32 address, u32 ptr) = 0;
143+
virtual void DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) = 0;
144+
virtual const AtracSasStreamState *StreamStateForSas() const { return nullptr; }
145+
128146
virtual int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const = 0;
129147

130148
virtual int GetContextVersion() const = 0;
@@ -205,14 +223,16 @@ class Atrac : public AtracBase {
205223
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
206224
// Notify the player that the user has written some new data.
207225
int AddStreamData(u32 bytesToAdd) override;
208-
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
209226
int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override;
210227
int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample, bool *delay) override;
211228
int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override;
212229
int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) override;
213230
int SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;
214231
u32 DecodeData(u8 *outbuf, u32 outbufPtr, int *SamplesNum, int *finish, int *remains) override;
215232
int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) override;
233+
234+
void CheckForSas() override;
235+
int EnqueueForSas(u32 address, u32 ptr) override;
216236
void DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) override;
217237

218238
// Returns how many samples the next DecodeData will write.

Core/HLE/AtracCtx2.cpp

Lines changed: 139 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,37 @@ Atrac2::Atrac2(u32 contextAddr, int codecType) {
175175
info.state = ATRAC_STATUS_NO_DATA;
176176
info.curBuffer = 0;
177177

178-
sasReadOffset_ = 0;
179-
sasBasePtr_ = 0;
178+
sas_.streamOffset = 0;
179+
sas_.bufPtr[0] = 0;
180+
sas_.bufPtr[1] = 0;
180181
} else {
181182
// We're loading state, we'll restore the context in DoState.
182183
}
183184
}
184185

185186
void Atrac2::DoState(PointerWrap &p) {
186-
auto s = p.Section("Atrac2", 1, 2);
187+
auto s = p.Section("Atrac2", 1, 3);
187188
if (!s)
188189
return;
189190

190191
Do(p, outputChannels_);
191192
// The only thing we need to save now is the outputChannels_ and the context pointer. And technically, not even that since
192193
// it can be computed. Still, for future proofing, let's save it.
193194
Do(p, context_);
195+
194196
// Actually, now we also need to save sas state. I guess this could also be saved on the Sas side, but this is easier.
195197
if (s >= 2) {
196-
Do(p, sasReadOffset_);
197-
Do(p, sasBasePtr_);
198+
Do(p, sas_.streamOffset);
199+
Do(p, sas_.bufPtr[0]);
200+
}
201+
// Added support for streaming sas audio, need some more context state.
202+
if (s >= 3) {
203+
Do(p, sas_.bufPtr[1]);
204+
Do(p, sas_.bufSize[0]);
205+
Do(p, sas_.bufSize[1]);
206+
Do(p, sas_.isStreaming);
207+
Do(p, sas_.curBuffer);
208+
Do(p, sas_.fileOffset);
198209
}
199210

200211
const SceAtracIdInfo &info = context_->info;
@@ -497,20 +508,6 @@ int Atrac2::AddStreamData(u32 bytesToAdd) {
497508
return 0;
498509
}
499510

500-
u32 Atrac2::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
501-
SceAtracIdInfo &info = context_->info;
502-
// Internal API, seems like a combination of GetStreamDataInfo and AddStreamData, for use when
503-
// an Atrac context is bound to an sceSas channel.
504-
// Sol Trigger is the only game I know that uses this.
505-
_dbg_assert_(false);
506-
507-
u8 *dest = Memory::GetPointerWrite(sasBasePtr_ + sasReadOffset_);
508-
memcpy(dest, Memory::GetPointer(bufPtr), bytesToAdd);
509-
info.buffer += bytesToAdd;
510-
info.streamDataByte += bytesToAdd;
511-
return 0;
512-
}
513-
514511
static int ComputeLoopedStreamWritableBytes(const SceAtracIdInfo &info, const int loopStartFileOffset, const u32 loopEndFileOffset) {
515512
const u32 writeOffset = info.curFileOff + info.streamDataByte;
516513
if (writeOffset >= loopEndFileOffset) {
@@ -681,6 +678,10 @@ u32 Atrac2::DecodeInternal(u32 outbufAddr, int *SamplesNum, int *finish) {
681678
return SCE_ERROR_ATRAC_BUFFER_IS_EMPTY;
682679
}
683680

681+
if (info.state == ATRAC_STATUS_FOR_SCESAS) {
682+
_dbg_assert_(false);
683+
}
684+
684685
u32 streamOff;
685686
u32 bufferPtr;
686687
if (!AtracStatusIsStreaming(info.state)) {
@@ -1039,27 +1040,132 @@ int Atrac2::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData,
10391040
return 0;
10401041
}
10411042

1043+
void Atrac2::CheckForSas() {
1044+
SceAtracIdInfo &info = context_->info;
1045+
if (info.numChan != 1) {
1046+
WARN_LOG(Log::ME, "Caller forgot to set channels to 1");
1047+
}
1048+
if (info.state != 0x10) {
1049+
WARN_LOG(Log::ME, "Caller forgot to set state to 0x10");
1050+
}
1051+
sas_.isStreaming = info.fileDataEnd > info.bufferByte;
1052+
if (sas_.isStreaming) {
1053+
INFO_LOG(Log::ME, "SasAtrac stream mode");
1054+
} else {
1055+
INFO_LOG(Log::ME, "SasAtrac non-streaming mode");
1056+
}
1057+
}
1058+
1059+
int Atrac2::EnqueueForSas(u32 address, u32 ptr) {
1060+
SceAtracIdInfo &info = context_->info;
1061+
// Set the new buffer up to be adopted by the next call to Decode that needs more data.
1062+
// Note: Can't call this if the decoder isn't asking for another buffer to be queued.
1063+
if (info.secondBuffer != 0xFFFFFFFF) {
1064+
return SCE_SAS_ERROR_ATRAC3_ALREADY_QUEUED;
1065+
}
1066+
1067+
if (address == 0 && ptr == 0) {
1068+
WARN_LOG(Log::ME, "Caller tries to send us a zero buffer. Something went wrong.");
1069+
}
1070+
1071+
DEBUG_LOG(Log::ME, "EnqueueForSas: Second buffer updated to %08x, sz: %08x", address, ptr);
1072+
info.secondBuffer = address;
1073+
info.secondBufferByte = ptr;
1074+
return 0;
1075+
}
1076+
1077+
// Completely different streaming setup!
10421078
void Atrac2::DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) {
10431079
SceAtracIdInfo &info = context_->info;
1080+
*bytesWritten = 0;
10441081

1082+
// First frame handling. Not sure if accurate. Set up the initial buffer as the current streaming buffer.
1083+
// Also works for the non-streaming case.
10451084
if (info.buffer) {
1046-
// Adopt it then zero it.
1047-
sasBasePtr_ = info.buffer;
1048-
sasReadOffset_ = 0;
1049-
info.buffer = 0;
1050-
}
1085+
sas_.curBuffer = 0;
1086+
sas_.bufPtr[0] = info.buffer;
1087+
sas_.bufSize[0] = info.bufferByte - info.streamOff; // also equals info.streamDataByte
1088+
sas_.streamOffset = 0;
1089+
sas_.fileOffset = info.bufferByte; // Possibly should just set it to info.curFileOff
1090+
info.buffer = 0; // yes, this happens.
1091+
}
1092+
1093+
u8 assembly[1000];
1094+
// Keep decoding from the current buffer until it runs out.
1095+
if (sas_.streamOffset + info.sampleSize <= sas_.bufSize[sas_.curBuffer]) {
1096+
// Just decode.
1097+
const u8 *srcData = Memory::GetPointer(sas_.bufPtr[sas_.curBuffer] + sas_.streamOffset);
1098+
int bytesConsumed = 0;
1099+
bool decodeResult = decoder_->Decode(srcData, info.sampleSize, &bytesConsumed, 1, dstData, bytesWritten);
1100+
if (!decodeResult) {
1101+
ERROR_LOG(Log::ME, "SAS failed to decode regular packet");
1102+
}
1103+
sas_.streamOffset += bytesConsumed;
1104+
} else if (sas_.isStreaming) {
1105+
// TODO: Do we need special handling for the first buffer, since SetData will wrap around that packet? I think yes!
1106+
DEBUG_LOG(Log::ME, "Streaming atrac through sas, and hit the end of buffer %d", sas_.curBuffer);
1107+
1108+
// Compute the part sizes using the current size.
1109+
int part1Size = sas_.bufSize[sas_.curBuffer] - sas_.streamOffset;
1110+
int part2Size = info.sampleSize - part1Size;
1111+
_dbg_assert_(part1Size >= 0);
1112+
if (part1Size >= 0) {
1113+
// Grab the partial packet, before we switch over to the other buffer.
1114+
Memory::Memcpy(assembly, sas_.bufPtr[sas_.curBuffer] + sas_.streamOffset, part1Size);
1115+
}
10511116

1052-
const u8 *srcData = Memory::GetPointer(sasBasePtr_ + sasReadOffset_);
1117+
// Check if we hit the end.
1118+
if (sas_.fileOffset >= info.fileDataEnd) {
1119+
DEBUG_LOG(Log::ME, "Streaming and hit the file end.");
1120+
*bytesWritten = 0;
1121+
*finish = 1;
1122+
return;
1123+
}
10531124

1054-
int outSamples = 0;
1055-
int bytesConsumed = 0;
1056-
decoder_->Decode(srcData, info.sampleSize, &bytesConsumed, 1, dstData, bytesWritten);
1125+
// Check that a new buffer actually exists
1126+
if (info.secondBuffer == sas_.bufPtr[sas_.curBuffer]) {
1127+
ERROR_LOG(Log::ME, "Can't enqueue the same buffer twice in a row!");
1128+
*bytesWritten = 0;
1129+
*finish = 1;
1130+
return;
1131+
}
10571132

1058-
sasReadOffset_ += bytesConsumed;
1133+
if ((int)info.secondBuffer < 0) {
1134+
ERROR_LOG(Log::ME, "AtracSas streaming ran out of data, no secondbuffer pending");
1135+
*bytesWritten = 0;
1136+
*finish = 1;
1137+
return;
1138+
}
10591139

1060-
if (sasReadOffset_ + info.dataOff >= info.fileDataEnd) {
1061-
*finish = 1;
1062-
} else {
1063-
*finish = 0;
1140+
// Switch to the other buffer.
1141+
sas_.curBuffer ^= 1;
1142+
1143+
sas_.bufPtr[sas_.curBuffer] = info.secondBuffer;
1144+
sas_.bufSize[sas_.curBuffer] = info.secondBufferByte;
1145+
sas_.fileOffset += info.secondBufferByte;
1146+
1147+
sas_.streamOffset = part2Size;
1148+
1149+
// If we'll reach the end during this buffer, set second buffer to 0, signaling that we don't need more data.
1150+
if (sas_.fileOffset >= info.fileDataEnd) {
1151+
// We've reached the end.
1152+
info.secondBuffer = 0;
1153+
DEBUG_LOG(Log::ME, "%08x >= %08x: Reached the end.", sas_.fileOffset, info.fileDataEnd);
1154+
} else {
1155+
// Signal to the caller that we accept a new next buffer.
1156+
info.secondBuffer = 0xFFFFFFFF;
1157+
}
1158+
1159+
DEBUG_LOG(Log::ME, "Switching over to buffer %d, updating buffer to %08x, sz: %08x. %s", sas_.curBuffer, info.secondBuffer, info.secondBufferByte, info.secondBuffer == 0xFFFFFFFF ? "Signalling for more data." : "");
1160+
1161+
// Copy the second half (or if part1Size == 0, the whole packet) to the assembly buffer.
1162+
Memory::Memcpy(assembly + part1Size, sas_.bufPtr[sas_.curBuffer], part2Size);
1163+
// Decode the packet from the assembly, whether it's was assembled from two or one.
1164+
const u8 *srcData = assembly;
1165+
int bytesConsumed = 0;
1166+
bool decodeResult = decoder_->Decode(srcData, info.sampleSize, &bytesConsumed, 1, dstData, bytesWritten);
1167+
if (!decodeResult) {
1168+
ERROR_LOG(Log::ME, "SAS failed to decode assembled packet");
1169+
}
10641170
}
10651171
}

Core/HLE/AtracCtx2.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class Atrac2 : public AtracBase {
3333
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
3434
int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) override;
3535
int AddStreamData(u32 bytesToAdd) override;
36-
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
3736
int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override;
3837
int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample, bool *delay) override;
3938
int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override;
@@ -42,7 +41,11 @@ class Atrac2 : public AtracBase {
4241

4342
u32 DecodeData(u8 *outbuf, u32 outbufPtr, int *SamplesNum, int *finish, int *remains) override;
4443
int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) override;
44+
45+
void CheckForSas() override;
46+
int EnqueueForSas(u32 address, u32 ptr) override;
4547
void DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) override;
48+
const AtracSasStreamState *StreamStateForSas() const { return context_->info.state == 0x10 ? &sas_ : nullptr; }
4649

4750
u32 GetNextSamples() override;
4851

@@ -55,7 +58,6 @@ class Atrac2 : public AtracBase {
5558
void NotifyGetContextAddress() override {}
5659

5760
int GetContextVersion() const override { return 2; }
58-
5961
u32 GetInternalCodecError() const override;
6062

6163
private:
@@ -73,6 +75,5 @@ class Atrac2 : public AtracBase {
7375

7476
// This is hidden state inside sceSas, really. Not visible in the context.
7577
// But it doesn't really matter whether it's here or there.
76-
u32 sasBasePtr_ = 0;
77-
int sasReadOffset_ = 0;
78+
AtracSasStreamState sas_;
7879
};

Core/HLE/ErrorCodes.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,4 +467,29 @@ enum PSPErrorCode : u32 {
467467
SCE_SSL_ERROR_ALREADY_INIT = 0x80435020,
468468
SCE_SSL_ERROR_OUT_OF_MEMORY = 0x80435022,
469469
SCE_SSL_ERROR_INVALID_PARAMETER = 0x804351FE,
470+
471+
SCE_SAS_ERROR_INVALID_GRAIN = 0x80420001,
472+
SCE_SAS_ERROR_INVALID_MAX_VOICES = 0x80420002,
473+
SCE_SAS_ERROR_INVALID_OUTPUT_MODE = 0x80420003,
474+
SCE_SAS_ERROR_INVALID_SAMPLE_RATE = 0x80420004,
475+
SCE_SAS_ERROR_BAD_ADDRESS = 0x80420005,
476+
SCE_SAS_ERROR_INVALID_VOICE = 0x80420010,
477+
SCE_SAS_ERROR_INVALID_NOISE_FREQ = 0x80420011,
478+
SCE_SAS_ERROR_INVALID_PITCH = 0x80420012,
479+
SCE_SAS_ERROR_INVALID_ADSR_CURVE_MODE = 0x80420013,
480+
SCE_SAS_ERROR_INVALID_PARAMETER = 0x80420014,
481+
SCE_SAS_ERROR_INVALID_LOOP_POS = 0x80420015,
482+
SCE_SAS_ERROR_VOICE_PAUSED = 0x80420016,
483+
SCE_SAS_ERROR_INVALID_VOLUME = 0x80420018,
484+
SCE_SAS_ERROR_INVALID_ADSR_RATE = 0x80420019,
485+
SCE_SAS_ERROR_INVALID_PCM_SIZE = 0x8042001A,
486+
SCE_SAS_ERROR_REV_INVALID_TYPE = 0x80420020,
487+
SCE_SAS_ERROR_REV_INVALID_FEEDBACK = 0x80420021,
488+
SCE_SAS_ERROR_REV_INVALID_DELAY = 0x80420022,
489+
SCE_SAS_ERROR_REV_INVALID_VOLUME = 0x80420023,
490+
SCE_SAS_ERROR_BUSY = 0x80420030,
491+
SCE_SAS_ERROR_ATRAC3_ALREADY_SET = 0x80420040,
492+
SCE_SAS_ERROR_ATRAC3_NOT_SET = 0x80420041,
493+
SCE_SAS_ERROR_ATRAC3_ALREADY_QUEUED = 0x80420042,
494+
SCE_SAS_ERROR_NOT_INIT = 0x80420100,
470495
};

0 commit comments

Comments
 (0)