Skip to content

Atrac-standalone followup #19043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 23 additions & 34 deletions Core/HLE/sceAtrac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,9 @@ struct AVPacket {
#endif

struct Atrac {
Atrac() : atracID_(-1), dataBuf_(0), decodePos_(0), bufferPos_(0),
channels_(0), outputChannels_(2), bitrate_(64), bytesPerFrame_(0), bufferMaxSize_(0), jointStereo_(0),
currentSample_(0), endSample_(0), firstSampleOffset_(0), dataOff_(0),
loopStartSample_(-1), loopEndSample_(-1), loopNum_(0),
failedDecode_(false), ignoreDataBuf_(false), codecType_(0),
bufferState_(ATRAC_STATUS_NO_DATA) {
Atrac() {
memset(&first_, 0, sizeof(first_));
memset(&second_, 0, sizeof(second_));
#ifdef USE_FFMPEG
codecCtx_ = nullptr;
swrCtx_ = nullptr;
frame_ = nullptr;
packet_ = nullptr;
#endif // USE_FFMPEG
context_ = 0;
}

Expand Down Expand Up @@ -401,40 +390,40 @@ struct Atrac {
return remainingBytes / bytesPerFrame_;
}

int atracID_;
u8 *dataBuf_;
int atracID_ = -1;
u8 *dataBuf_ = nullptr;

u32 decodePos_;
u32 decodePos_ = 0;
// Used by low-level decoding and to track streaming.
u32 bufferPos_;
u32 bufferValidBytes_;
u32 bufferPos_ = 0;
u32 bufferValidBytes_ = 0;
u32 bufferHeaderSize_ = 0;

u16 channels_;
u16 outputChannels_;
u32 bitrate_;
u16 bytesPerFrame_;
u32 bufferMaxSize_;
int jointStereo_;
u16 channels_ = 0;
u16 outputChannels_ = 2;
u32 bitrate_ = 64;
u16 bytesPerFrame_ = 0;
u32 bufferMaxSize_ = 0;
int jointStereo_ = 0;

int currentSample_;
int endSample_;
int firstSampleOffset_;
int currentSample_ = 0;
int endSample_ = 0;
int firstSampleOffset_ = 0;
// Offset of the first sample in the input buffer
int dataOff_;
int dataOff_ = 0;

std::vector<AtracLoopInfo> loopinfo_;

int loopStartSample_;
int loopEndSample_;
int loopNum_;
int loopStartSample_ = -1;
int loopEndSample_ = -1;
int loopNum_ = 0;

bool failedDecode_;
bool failedDecode_ = false;
// Indicates that the dataBuf_ array should not be used.
bool ignoreDataBuf_;
bool ignoreDataBuf_ = false;

u32 codecType_;
AtracStatus bufferState_;
u32 codecType_ = 0;
AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA;

InputBuffer first_;
InputBuffer second_;
Expand Down
10 changes: 4 additions & 6 deletions Core/HLE/sceAtrac.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ typedef AtracStatus AtracStatus_le;
typedef swap_struct_t<AtracStatus, swap_32_t<AtracStatus> > AtracStatus_le;
#endif

typedef struct
{
struct SceAtracIdInfo {
u32_le decodePos; // 0
u32_le endSample; // 4
u32_le loopStart; // 8
Expand All @@ -76,15 +75,14 @@ typedef struct
u32_le secondBufferByte; // 68
// make sure the size is 128
u8 unk[56];
} SceAtracIdInfo;
};

typedef struct
{
struct SceAtracId {
// size 128
SceAudiocodecCodec codec;
// size 128
SceAtracIdInfo info;
} SceAtracId;
};

// provide some decoder interface

Expand Down
3 changes: 2 additions & 1 deletion Core/HLE/sceAudiocodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
// Use SimpleAudioDec to decode audio
auto ctx = PSPPointer<AudioCodecContext>::Create(ctxPtr); // On stack, no need to allocate.
// Decode audio
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes);
int inDataConsumed = 0;
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes);
}
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
Expand Down
5 changes: 3 additions & 2 deletions Core/HLE/sceMp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,11 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed
auto outbuff = Memory::GetPointerWriteUnchecked(samplesAddr);

int outpcmbytes = 0;
ctx->decoder->Decode(inbuff, 4096, outbuff, &outpcmbytes);
int inbytesConsumed = 0;
ctx->decoder->Decode(inbuff, 4096, &inbytesConsumed, outbuff, &outpcmbytes);
NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode");

Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr);
Memory::Write_U32(inbytesConsumed, sourceBytesConsumedAddr);
Memory::Write_U32(outpcmbytes, sampleBytesAddr);
return 0;
}
Expand Down
23 changes: 14 additions & 9 deletions Core/HW/Atrac3Standalone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ inline int16_t clamp16(float f) {
class Atrac3Audio : public AudioDecoder {
public:
Atrac3Audio(PSPAudioType audioType, int channels, size_t blockAlign, const uint8_t *extraData, size_t extraDataSize) : audioType_(audioType) {
blockAlign_ = blockAlign;
blockAlign_ = (int)blockAlign;
if (audioType == PSP_CODEC_AT3PLUS) {
at3pCtx_ = atrac3p_alloc(channels, &blockAlign_);
if (at3pCtx_)
codecOpen_ = true;
} else if (audioType_ == PSP_CODEC_AT3) {
at3Ctx_ = atrac3_alloc(channels, &blockAlign_, extraData, extraDataSize);
at3Ctx_ = atrac3_alloc(channels, &blockAlign_, extraData, (int)extraDataSize);
if (at3Ctx_)
codecOpen_ = true;
}
Expand All @@ -46,7 +46,16 @@ class Atrac3Audio : public AudioDecoder {
return codecOpen_;
}

bool Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) override {
void FlushBuffers() {
if (at3Ctx_) {
atrac3_flush_buffers(at3Ctx_);
}
if (at3pCtx_) {
atrac3p_flush_buffers(at3pCtx_);
}
}

bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override {
if (!codecOpen_) {
_dbg_assert_(false);
}
Expand All @@ -61,19 +70,18 @@ class Atrac3Audio : public AudioDecoder {
if (audioType_ == PSP_CODEC_AT3PLUS) {
result = atrac3p_decode_frame(at3pCtx_, buffers_, &nb_samples, &got_frame, inbuf, inbytes);
} else {

result = atrac3_decode_frame(at3Ctx_, buffers_, &nb_samples, &got_frame, inbuf, inbytes);
}
if (result < 0) {
*outbytes = 0;
return false;
}
srcPos_ = result;
*inbytesConsumed = result;
outSamples_ = nb_samples;
if (nb_samples > 0) {
*outbytes = nb_samples * 2 * 2;

// Convert frame to outbuf.
// Convert frame to outbuf. TODO: Very SIMDable, though hardly hot.
for (int channel = 0; channel < 2; channel++) {
int16_t *output = (int16_t *)outbuf;
for (int i = 0; i < nb_samples; i++) {
Expand All @@ -90,9 +98,6 @@ class Atrac3Audio : public AudioDecoder {
int GetOutSamples() const override {
return outSamples_;
}
int GetSourcePos() const override {
return srcPos_;
}

void SetChannels(int channels) override {
// Hmm. ignore for now.
Expand Down
3 changes: 2 additions & 1 deletion Core/HW/MediaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,8 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) {
m_audioContext->SetChannels(1);
}

if (!m_audioContext->Decode(audioFrame, frameSize, buffer, &outbytes)) {
int inbytesConsumed = 0;
if (!m_audioContext->Decode(audioFrame, frameSize, &inbytesConsumed, buffer, &outbytes)) {
ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType));
}

Expand Down
47 changes: 19 additions & 28 deletions Core/HW/SimpleAudioDec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ class MiniMp3Audio : public AudioDecoder {
}
~MiniMp3Audio() {}

bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) override {
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override {
mp3dec_frame_info_t info{};
int samplesWritten = mp3dec_decode_frame(&mp3_, inbuf, inbytes, (mp3d_sample_t *)outbuf, &info);
srcPos_ = info.frame_bytes;
*inbytesConsumed = info.frame_bytes;
*outbytes = samplesWritten * sizeof(mp3d_sample_t) * info.channels;
outSamples_ = samplesWritten * info.channels;
return true;
Expand All @@ -78,9 +78,6 @@ class MiniMp3Audio : public AudioDecoder {
int GetOutSamples() const override {
return outSamples_;
}
int GetSourcePos() const override {
return srcPos_;
}

void SetChannels(int channels) override {
// Hmm. ignore for now.
Expand All @@ -101,7 +98,7 @@ class SimpleAudio : public AudioDecoder {
SimpleAudio(PSPAudioType audioType, int sampleRateHz = 44100, int channels = 2);
~SimpleAudio();

bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) override;
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override;
bool IsOK() const override {
#ifdef USE_FFMPEG
return codec_ != 0;
Expand All @@ -111,10 +108,7 @@ class SimpleAudio : public AudioDecoder {
}

int GetOutSamples() const override {
return outSamples;
}
int GetSourcePos() const override {
return srcPos;
return outSamples_;
}

void SetChannels(int channels) override;
Expand All @@ -128,18 +122,17 @@ class SimpleAudio : public AudioDecoder {
PSPAudioType audioType;
int sample_rate_;
int channels_;
int outSamples; // output samples per frame
int srcPos; // bytes consumed in source during the last decoding
int outSamples_ = 0; // output samples per frame

AVFrame *frame_;
AVFrame *frame_ = nullptr;
#if HAVE_LIBAVCODEC_CONST_AVCODEC // USE_FFMPEG is implied
const
#endif
AVCodec *codec_;
AVCodecContext *codecCtx_;
SwrContext *swrCtx_;
AVCodec *codec_ = nullptr;
AVCodecContext *codecCtx_ = nullptr;
SwrContext *swrCtx_ = nullptr;

bool codecOpen_;
bool codecOpen_ = false;
};

AudioDecoder *CreateAudioDecoder(PSPAudioType audioType, int sampleRateHz, int channels, size_t blockAlign, const uint8_t *extraData, size_t extraDataSize) {
Expand Down Expand Up @@ -176,10 +169,7 @@ static int GetAudioCodecID(int audioType) {
}

SimpleAudio::SimpleAudio(PSPAudioType audioType, int sampleRateHz, int channels)
: audioType(audioType), sample_rate_(sampleRateHz), channels_(channels),
outSamples(0), srcPos(0),
frame_(0), codec_(0), codecCtx_(0), swrCtx_(0),
codecOpen_(false) {
: audioType(audioType), sample_rate_(sampleRateHz), channels_(channels) {

#ifdef USE_FFMPEG
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
Expand Down Expand Up @@ -274,7 +264,7 @@ SimpleAudio::~SimpleAudio() {
}

// Decodes a single input frame.
bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) {
#ifdef USE_FFMPEG
if (!codecOpen_) {
OpenCodec(inbytes);
Expand All @@ -289,7 +279,7 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
av_frame_unref(frame_);

*outbytes = 0;
srcPos = 0;
*inbytesConsumed = 0;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
if (inbytes != 0) {
int err = avcodec_send_packet(codecCtx_, &packet);
Expand Down Expand Up @@ -321,7 +311,7 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
}

// get bytes consumed in source
srcPos = len;
*inbytesConsumed = len;

if (got_frame) {
// Initializing the sample rate convert. We will use it to convert float output into int.
Expand Down Expand Up @@ -358,10 +348,10 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
return false;
}
// output samples per frame, we should *2 since we have two channels
outSamples = swrRet * 2;
outSamples_ = swrRet * 2;

// each sample occupies 2 bytes
*outbytes = outSamples * 2;
*outbytes = outSamples_ * 2;

// Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file.
// SaveAudio("dump.pcm", outbuf, *outbytes);
Expand Down Expand Up @@ -446,7 +436,8 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
if (!sourcebuff.empty()) {
// FFmpeg doesn't seem to search for a sync for us, so let's do that.
int nextSync = (int)FindNextMp3Sync();
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, outbuf, &outpcmbufsize);
int inbytesConsumed = 0;
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, outbuf, &outpcmbufsize);

if (outpcmbufsize == 0) {
// Nothing was output, hopefully we're at the end of the stream.
Expand All @@ -456,7 +447,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
// Update our total decoded samples, but don't count stereo.
SumDecodedSamples += decoder->GetOutSamples() / 2;
// get consumed source length
int srcPos = decoder->GetSourcePos() + nextSync;
int srcPos = inbytesConsumed + nextSync;
// remove the consumed source
if (srcPos > 0)
sourcebuff.erase(sourcebuff.begin(), sourcebuff.begin() + srcPos);
Expand Down
6 changes: 4 additions & 2 deletions Core/HW/SimpleAudioDec.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,17 @@ class AudioDecoder {

virtual PSPAudioType GetAudioType() const = 0;

virtual bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) = 0;
// inbytesConsumed can include skipping metadata.
virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) = 0;
virtual bool IsOK() const = 0;

// These two are only ever called after Decode, so can initialize on first.
virtual int GetOutSamples() const = 0;
virtual int GetSourcePos() const = 0;

virtual void SetChannels(int channels) = 0;

virtual void FlushBuffers() {}

// Just metadata.
void SetCtxPtr(uint32_t ptr) { ctxPtr = ptr; }
uint32_t GetCtxPtr() const { return ctxPtr; }
Expand Down
3 changes: 2 additions & 1 deletion UI/BackgroundAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ class AT3PlusReader {

while (bgQueue.size() < (size_t)(len * 2)) {
int outBytes = 0;
decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, (uint8_t *)buffer_, &outBytes);
int inbytesConsumed = 0;
decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, &inbytesConsumed, (uint8_t *)buffer_, &outBytes);
if (!outBytes)
return false;

Expand Down
3 changes: 3 additions & 0 deletions ext/at3_standalone/at3_decoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ struct ATRAC3Context;
struct ATRAC3PContext;

// If the block_align passed in is 0, tries to audio detect.
// flush_buffers should be called when seeking before the next decode_frame.

ATRAC3Context *atrac3_alloc(int channels, int *block_align, const uint8_t *extra_data, int extra_data_size);
void atrac3_free(ATRAC3Context *ctx);
void atrac3_flush_buffers(ATRAC3Context *ctx);
int atrac3_decode_frame(ATRAC3Context *ctx, float *out_data[2], int *nb_samples, int *got_frame_ptr, const uint8_t *buf, int buf_size);

ATRAC3PContext *atrac3p_alloc(int channels, int *block_align);
void atrac3p_free(ATRAC3PContext *ctx);
void atrac3p_flush_buffers(ATRAC3PContext *ctx);
int atrac3p_decode_frame(ATRAC3PContext *ctx, float *out_data[2], int *nb_samples, int *got_frame_ptr, const uint8_t *buf, int buf_size);
Loading