CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/HLE/AtracCtx.h
Views: 1401
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#pragma once
19
20
#include <vector>
21
22
#include "Common/CommonTypes.h"
23
#include "Common/Swap.h"
24
25
#include "Core/MemMap.h"
26
#include "Core/HLE/sceAtrac.h"
27
28
struct AtracSingleResetBufferInfo {
29
u32_le writePosPtr;
30
u32_le writableBytes;
31
u32_le minWriteBytes;
32
u32_le filePos;
33
};
34
35
struct AtracResetBufferInfo {
36
AtracSingleResetBufferInfo first;
37
AtracSingleResetBufferInfo second;
38
};
39
40
#define AT3_MAGIC 0x0270
41
#define AT3_PLUS_MAGIC 0xFFFE
42
#define PSP_MODE_AT_3_PLUS 0x00001000
43
#define PSP_MODE_AT_3 0x00001001
44
45
#define ATRAC_ERROR_API_FAIL 0x80630002
46
#define ATRAC_ERROR_NO_ATRACID 0x80630003
47
#define ATRAC_ERROR_INVALID_CODECTYPE 0x80630004
48
#define ATRAC_ERROR_BAD_ATRACID 0x80630005
49
#define ATRAC_ERROR_UNKNOWN_FORMAT 0x80630006
50
#define ATRAC_ERROR_WRONG_CODECTYPE 0x80630007
51
#define ATRAC_ERROR_BAD_CODEC_PARAMS 0x80630008
52
#define ATRAC_ERROR_ALL_DATA_LOADED 0x80630009
53
#define ATRAC_ERROR_NO_DATA 0x80630010
54
#define ATRAC_ERROR_SIZE_TOO_SMALL 0x80630011
55
#define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
56
#define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
57
#define ATRAC_ERROR_BAD_SAMPLE 0x80630015
58
#define ATRAC_ERROR_BAD_FIRST_RESET_SIZE 0x80630016
59
#define ATRAC_ERROR_BAD_SECOND_RESET_SIZE 0x80630017
60
#define ATRAC_ERROR_ADD_DATA_IS_TOO_BIG 0x80630018
61
#define ATRAC_ERROR_NOT_MONO 0x80630019
62
#define ATRAC_ERROR_NO_LOOP_INFORMATION 0x80630021
63
#define ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED 0x80630022
64
#define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
65
#define ATRAC_ERROR_ALL_DATA_DECODED 0x80630024
66
#define ATRAC_ERROR_IS_LOW_LEVEL 0x80630031
67
#define ATRAC_ERROR_IS_FOR_SCESAS 0x80630040
68
#define ATRAC_ERROR_AA3_INVALID_DATA 0x80631003
69
#define ATRAC_ERROR_AA3_SIZE_TOO_SMALL 0x80631004
70
71
const u32 ATRAC3_MAX_SAMPLES = 0x400;
72
const u32 ATRAC3PLUS_MAX_SAMPLES = 0x800;
73
74
const int PSP_ATRAC_ALLDATA_IS_ON_MEMORY = -1;
75
const int PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY = -2;
76
const int PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY = -3;
77
78
// This is not a PSP-native struct.
79
// But, it's stored in its entirety in savestates, which makes it awkward to change it.
80
struct InputBuffer {
81
// Address of the buffer.
82
u32 addr;
83
// Size of data read so far into dataBuf_ (to be removed.)
84
u32 size;
85
// Offset into addr at which new data is added.
86
u32 offset;
87
// Last writableBytes number (to be removed.)
88
u32 writableBytes;
89
// Unused, always 0.
90
u32 neededBytes;
91
// Total size of the entire file data.
92
u32 _filesize_dontuse;
93
// Offset into the file at which new data is read.
94
u32 fileoffset;
95
};
96
97
struct AtracLoopInfo {
98
int cuePointID;
99
int type;
100
int startSample;
101
int endSample;
102
int fraction;
103
int playCount;
104
};
105
106
class AudioDecoder;
107
108
struct Track {
109
// This both does and doesn't belong in Track - it's fixed for an Atrac instance. Oh well.
110
u32 codecType = 0;
111
112
// Size of the full track being streamed or played. Can be a lot larger than the in-memory buffer in the streaming modes.
113
u32 fileSize = 0;
114
115
// Not really used for much except queries, this keeps track of the bitrate of the track.
116
u32 bitrate = 64;
117
118
// Signifies whether to use a more efficient coding mode with less stereo separation. For our purposes, just metadata.
119
int jointStereo = 0;
120
121
// Number of audio channels in the track.
122
u16 channels = 0;
123
124
// The size of an encoded frame in bytes.
125
u16 bytesPerFrame = 0;
126
127
// Byte offset of the first encoded frame in the input buffer. Note: Some samples may be skipped according to firstSampleOffset.
128
int dataByteOffset = 0;
129
130
// How many samples to skip from the beginning of a track when decoding.
131
// Actually, the real number is this added to FirstOffsetExtra(codecType). You can call
132
// FirstSampleOffset2() to get that.
133
// Some use of these offsets around the code seem to be inconsistent, sometimes the extra is included,
134
// sometimes not.
135
int firstSampleOffset = 0;
136
137
// Last sample number. Though, we made it so in Analyze, it's exclusive in the file.
138
// Does not take firstSampleOffset into account.
139
int endSample = 0;
140
141
// Loop configuration. The PSP only supports one loop but we store them all.
142
std::vector<AtracLoopInfo> loopinfo;
143
// The actual used loop offsets. These appear to be raw offsets, not taking FirstSampleOffset2() into account.
144
int loopStartSample = -1;
145
int loopEndSample = -1;
146
147
// Input frame size
148
int BytesPerFrame() const {
149
return bytesPerFrame;
150
}
151
152
inline int FirstOffsetExtra() const {
153
return codecType == PSP_MODE_AT_3_PLUS ? 368 : 69;
154
}
155
156
// Includes the extra offset. See firstSampleOffset comment above.
157
int FirstSampleOffsetFull() const {
158
return FirstOffsetExtra() + firstSampleOffset;
159
}
160
161
// Output frame size, different between the two supported codecs.
162
u32 SamplesPerFrame() const {
163
return codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES;
164
}
165
166
void UpdateBitrate() {
167
bitrate = (bytesPerFrame * 352800) / 1000;
168
if (codecType == PSP_MODE_AT_3_PLUS)
169
bitrate = ((bitrate >> 11) + 8) & 0xFFFFFFF0;
170
else
171
bitrate = (bitrate + 511) >> 10;
172
}
173
174
// This appears to be buggy, should probably include FirstOffsetExtra?
175
// Actually the units don't even make sense here.
176
u32 DecodePosBySample(int sample) const {
177
return (u32)(firstSampleOffset + sample / (int)SamplesPerFrame() * bytesPerFrame);
178
}
179
180
// This appears to be buggy, should probably include FirstOffsetExtra?
181
u32 FileOffsetBySample(int sample) const {
182
int offsetSample = sample + firstSampleOffset;
183
int frameOffset = offsetSample / (int)SamplesPerFrame();
184
return (u32)(dataByteOffset + bytesPerFrame + frameOffset * bytesPerFrame);
185
}
186
187
void AnalyzeReset() {
188
endSample = -1;
189
loopinfo.clear();
190
loopStartSample = -1;
191
loopEndSample = -1;
192
channels = 2;
193
// TODO: Could probably reset more.
194
}
195
196
void DebugLog();
197
};
198
199
int AnalyzeAA3Track(u32 addr, u32 size, u32 filesize, Track *track);
200
int AnalyzeAtracTrack(u32 addr, u32 size, Track *track);
201
202
class AtracBase {
203
public:
204
virtual ~AtracBase() {}
205
206
virtual void DoState(PointerWrap &p) = 0;
207
208
const Track &GetTrack() const {
209
return track_;
210
}
211
// This should be rare.
212
Track &GetTrackMut() {
213
return track_;
214
}
215
216
int GetOutputChannels() const {
217
return outputChannels_;
218
}
219
void SetOutputChannels(int channels) {
220
// Only used for sceSas audio. To be refactored away in the future.
221
outputChannels_ = channels;
222
}
223
224
int atracID_ = -1;
225
226
PSPPointer<SceAtracContext> context_{};
227
228
AtracStatus BufferState() const {
229
return bufferState_;
230
}
231
232
int LoopNum() const {
233
return loopNum_;
234
}
235
u32 CodecType() const {
236
return track_.codecType;
237
}
238
AudioDecoder *Decoder() const {
239
return decoder_;
240
}
241
242
void CreateDecoder();
243
244
virtual int CurrentSample() const = 0;
245
virtual int RemainingFrames() const = 0;
246
virtual u32 SecondBufferSize() const = 0;
247
248
virtual int Analyze(u32 addr, u32 size) = 0;
249
virtual int AnalyzeAA3(u32 addr, u32 size, u32 filesize) = 0;
250
251
void UpdateContextFromPSPMem();
252
virtual void WriteContextToPSPMem() = 0;
253
254
virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0;
255
virtual int AddStreamData(u32 bytesToAdd) = 0;
256
virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0;
257
virtual void SetLoopNum(int loopNum);
258
virtual u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) = 0;
259
virtual void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) = 0;
260
virtual int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) = 0;
261
262
virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize);
263
virtual u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0;
264
virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) = 0;
265
virtual u32 GetNextSamples() = 0;
266
virtual void InitLowLevel(u32 paramsAddr, bool jointStereo) = 0;
267
268
protected:
269
Track track_{};
270
u16 outputChannels_ = 2;
271
int loopNum_ = 0;
272
273
// TODO: Save the internal state of this, now technically possible.
274
AudioDecoder *decoder_ = nullptr;
275
AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA;
276
};
277
278
class Atrac : public AtracBase {
279
public:
280
~Atrac() {
281
ResetData();
282
}
283
284
uint32_t CurBufferAddress(int adjust = 0) const {
285
u32 off = track_.FileOffsetBySample(currentSample_ + adjust);
286
if (off < first_.size && ignoreDataBuf_) {
287
return first_.addr + off;
288
}
289
// If it's in dataBug, it's not in PSP memory.
290
return 0;
291
}
292
293
u8 *BufferStart();
294
void DoState(PointerWrap &p) override;
295
void WriteContextToPSPMem() override;
296
297
int Analyze(u32 addr, u32 size) override;
298
int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override;
299
300
int CurrentSample() const override {
301
return currentSample_;
302
}
303
int RemainingFrames() const override;
304
u32 SecondBufferSize() const override {
305
return second_.size;
306
}
307
308
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
309
int AddStreamData(u32 bytesToAdd) override;
310
u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override;
311
u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override;
312
void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override;
313
int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels, int successCode) override;
314
u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override;
315
u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override;
316
u32 GetNextSamples() override;
317
void InitLowLevel(u32 paramsAddr, bool jointStereo) override;
318
319
protected:
320
void AnalyzeReset();
321
322
private:
323
void UpdateBufferState();
324
void ResetData();
325
void SeekToSample(int sample);
326
void ForceSeekToSample(int sample);
327
u32 StreamBufferEnd() const {
328
// The buffer is always aligned to a frame in size, not counting an optional header.
329
// The header will only initially exist after the data is first set.
330
u32 framesAfterHeader = (bufferMaxSize_ - bufferHeaderSize_) / track_.bytesPerFrame;
331
return framesAfterHeader * track_.bytesPerFrame + bufferHeaderSize_;
332
}
333
void ConsumeFrame();
334
void CalculateStreamInfo(u32 *readOffset);
335
336
InputBuffer first_{};
337
InputBuffer second_{}; // only addr, size, fileoffset are used (incomplete)
338
339
u8 *dataBuf_ = nullptr;
340
// Indicates that the dataBuf_ array should not be used.
341
bool ignoreDataBuf_ = false;
342
343
int currentSample_ = 0;
344
u32 decodePos_ = 0;
345
u32 bufferMaxSize_ = 0;
346
347
// Used to track streaming.
348
u32 bufferPos_ = 0;
349
u32 bufferValidBytes_ = 0;
350
u32 bufferHeaderSize_ = 0;
351
};
352
353