#pragma once
#include "Common/CommonTypes.h"
#include "Common/Swap.h"
#include "Core/MemMap.h"
#include "Core/HLE/sceAudiocodec.h"
constexpr u32 ATRAC3_MAX_SAMPLES = 0x400;
constexpr u32 ATRAC3PLUS_MAX_SAMPLES = 0x800;
enum AtracStatus : u8 {
ATRAC_STATUS_UNINITIALIZED = 0,
ATRAC_STATUS_NO_DATA = 1,
ATRAC_STATUS_ALL_DATA_LOADED = 2,
ATRAC_STATUS_HALFWAY_BUFFER = 3,
ATRAC_STATUS_STREAMED_WITHOUT_LOOP = 4,
ATRAC_STATUS_STREAMED_LOOP_FROM_END = 5,
ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER = 6,
ATRAC_STATUS_LOW_LEVEL = 8,
ATRAC_STATUS_FOR_SCESAS = 16,
ATRAC_STATUS_STREAMED_MASK = 4,
};
const char *AtracStatusToString(AtracStatus status);
inline bool AtracStatusIsStreaming(AtracStatus status) {
return (status & ATRAC_STATUS_STREAMED_MASK) != 0;
}
inline bool AtracStatusIsNormal(AtracStatus status) {
return (int)status >= ATRAC_STATUS_ALL_DATA_LOADED && (int)status <= ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER;
}
struct SceAtracIdInfo {
s32 decodePos;
s32 endSample;
s32 loopStart;
s32 loopEnd;
s32 firstValidSample;
u8 numSkipFrames;
AtracStatus state;
u8 curBuffer;
u8 numChan;
u16 sampleSize;
u16 codec;
s32 dataOff;
s32 curFileOff;
s32 fileDataEnd;
s32 loopNum;
s32 streamDataByte;
s32 streamOff;
s32 secondStreamOff;
u32 buffer;
u32 secondBuffer;
u32 bufferByte;
u32 secondBufferByte;
u32 unk[14];
int SamplesPerFrame() const {
return codec == 0x1000 ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES;
}
int SamplesFrameMask() const {
return SamplesPerFrame() - 1;
}
int SkipSamples() const {
return codec == 0x1000 ? 0x170 : 0x45;
}
int BitRate() const {
int bitrate = (sampleSize * 352800) / 1000;
if (codec == PSP_CODEC_AT3PLUS) {
bitrate = ((bitrate >> 11) + 8) & 0xFFFFFFF0;
} else {
bitrate = (bitrate + 511) >> 10;
}
return bitrate;
}
};
struct SceAtracContext {
SceAudiocodecCodec codec;
SceAtracIdInfo info;
};
struct Atrac3LowLevelParams {
int encodedChannels;
int outputChannels;
int bytesPerFrame;
};
struct AtracSingleResetBufferInfo {
u32_le writePosPtr;
u32_le writableBytes;
u32_le minWriteBytes;
u32_le filePos;
};
struct AtracResetBufferInfo {
AtracSingleResetBufferInfo first;
AtracSingleResetBufferInfo second;
};
struct AtracSasStreamState {
u32 bufPtr[2]{};
u32 bufSize[2]{};
int streamOffset = 0;
int fileOffset = 0;
int curBuffer = 0;
bool isStreaming = false;
int CurPos() const {
int retval = fileOffset - bufSize[curBuffer] + streamOffset;
_dbg_assert_(retval >= 0);
return retval;
}
};
const int PSP_ATRAC_ALLDATA_IS_ON_MEMORY = -1;
const int PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY = -2;
const int PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY = -3;
struct InputBuffer {
u32 addr;
u32 size;
u32 offset;
u32 writableBytes;
u32 neededBytes;
u32 _filesize_dontuse;
u32 fileoffset;
};
class AudioDecoder;
class PointerWrap;
struct Track;
class AtracBase {
public:
virtual ~AtracBase();
virtual void DoState(PointerWrap &p) = 0;
virtual void UpdateContextFromPSPMem() = 0;
virtual int Channels() const = 0;
int GetOutputChannels() const {
return outputChannels_;
}
void SetOutputChannels(int channels) {
outputChannels_ = channels;
}
virtual u32 GetInternalCodecError() const { return 0; }
PSPPointer<SceAtracContext> context_{};
virtual AtracStatus BufferState() const = 0;
virtual int SetLoopNum(int loopNum) = 0;
virtual int LoopNum() const = 0;
virtual int LoopStatus() const = 0;
virtual int CodecType() const = 0;
AudioDecoder *Decoder() const {
return decoder_;
}
void CreateDecoder(int codecType, int bytesPerFrame, int channels);
virtual void NotifyGetContextAddress() = 0;
virtual int GetNextDecodePosition(int *pos) const = 0;
virtual int RemainingFrames() const = 0;
virtual bool HasSecondBuffer() const = 0;
virtual int Bitrate() const = 0;
virtual int BytesPerFrame() const = 0;
virtual int SamplesPerFrame() const = 0;
virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0;
virtual int AddStreamData(u32 bytesToAdd) = 0;
virtual int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) = 0;
virtual int GetBufferInfoForResetting(AtracResetBufferInfo *bufferInfo, int sample, bool *delay) = 0;
virtual int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, u32 fileSize, int outputChannels, bool isAA3) = 0;
virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize) const = 0;
virtual int SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0;
virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, int *SamplesNum, int *finish, int *remains) = 0;
virtual int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) = 0;
virtual u32 GetNextSamples() = 0;
virtual void InitLowLevel(const Atrac3LowLevelParams ¶ms, int codecType) = 0;
virtual void CheckForSas() = 0;
virtual int EnqueueForSas(u32 address, u32 ptr) = 0;
virtual void DecodeForSas(s16 *dstData, int *bytesWritten, int *finish) = 0;
virtual const AtracSasStreamState *StreamStateForSas() const { return nullptr; }
virtual int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const = 0;
virtual int GetContextVersion() const = 0;
protected:
u16 outputChannels_ = 2;
AudioDecoder *decoder_ = nullptr;
};