Merge pull request #19026 from hrydgard/minimp3-decoder

Decode MP3 without using ffmpeg
This commit is contained in:
Henrik Rydgård 2024-04-11 14:35:34 +02:00 committed by GitHub
commit 9953786156
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 67 additions and 33 deletions

View file

@ -511,7 +511,7 @@ static int sceMp3GetLoopNum(u32 mp3) {
return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
}
return hleLogSuccessI(ME, ctx->AuGetLoopNum());
return hleLogSuccessI(ME, ctx->LoopNum);
}
static int sceMp3GetMaxOutputSample(u32 mp3) {
@ -555,7 +555,8 @@ static int sceMp3SetLoopNum(u32 mp3, int loop) {
if (loop < 0)
loop = -1;
return hleLogSuccessI(ME, ctx->AuSetLoopNum(loop));
ctx->LoopNum = loop;
return hleLogSuccessI(ME, 0);
}
static int sceMp3GetMp3ChannelNum(u32 mp3) {

View file

@ -301,7 +301,7 @@ static u32 sceAacGetLoopNum(u32 id)
ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
return -1;
}
return ctx->AuGetLoopNum();
return ctx->LoopNum;
}
static u32 sceAacSetLoopNum(u32 id, int loop)
@ -313,7 +313,8 @@ static u32 sceAacSetLoopNum(u32 id, int loop)
return -1;
}
return ctx->AuSetLoopNum(loop);
ctx->LoopNum = loop;
return 0;
}
static int sceAacCheckStreamDataNeeded(u32 id)

View file

@ -26,6 +26,8 @@
#include "Core/HW/MediaEngine.h"
#include "Core/HW/BufferQueue.h"
#include "ext/minimp3/minimp3.h"
#ifdef USE_FFMPEG
extern "C" {
@ -49,6 +51,44 @@ extern "C" {
#endif // USE_FFMPEG
// minimp3-based decoder.
class MiniMp3Audio : public AudioDecoder {
public:
MiniMp3Audio() {
mp3dec_init(&mp3_);
}
~MiniMp3Audio() {}
bool Decode(const uint8_t* inbuf, int inbytes, 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;
*outbytes = samplesWritten * sizeof(mp3d_sample_t) * info.channels;
outSamples_ = samplesWritten * info.channels;
return true;
}
bool IsOK() const override { return true; }
int GetOutSamples() const override {
return outSamples_;
}
int GetSourcePos() const override {
return srcPos_;
}
void SetChannels(int channels) override {
// Hmm. ignore for now.
}
PSPAudioType GetAudioType() const override { return PSP_CODEC_MP3; }
private:
// We use the lowest-level API.
mp3dec_t mp3_{};
int outSamples_ = 0;
int srcPos_ = 0;
};
// FFMPEG-based decoder. TODO: Replace with individual codecs.
class SimpleAudio : public AudioDecoder {
public:
@ -56,7 +96,13 @@ public:
~SimpleAudio();
bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) override;
bool IsOK() const override;
bool IsOK() const override {
#ifdef USE_FFMPEG
return codec_ != 0;
#else
return 0;
#endif
}
int GetOutSamples() const override {
return outSamples;
@ -67,11 +113,10 @@ public:
// Not save stated, only used by UI. Used for ATRAC3 (non+) files.
void SetExtraData(const uint8_t *data, int size, int wav_bytes_per_packet) override;
void SetChannels(int channels) override;
// These two are only here because of save states.
PSPAudioType GetAudioType() const { return audioType; }
PSPAudioType GetAudioType() const override { return audioType; }
private:
bool OpenCodec(int block_align);
@ -95,7 +140,12 @@ private:
// TODO: This should also be able to create other types of decoders.
AudioDecoder *CreateAudioDecoder(PSPAudioType audioType, int sampleRateHz, int channels) {
return new SimpleAudio(audioType, sampleRateHz, channels);
switch (audioType) {
case PSP_CODEC_MP3:
return new MiniMp3Audio();
default:
return new SimpleAudio(audioType, sampleRateHz, channels);
}
}
static int GetAudioCodecID(int audioType) {
@ -230,14 +280,6 @@ SimpleAudio::~SimpleAudio() {
#endif // USE_FFMPEG
}
bool SimpleAudio::IsOK() const {
#ifdef USE_FFMPEG
return codec_ != 0;
#else
return 0;
#endif
}
// Decodes a single input frame.
bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
#ifdef USE_FFMPEG
@ -458,17 +500,6 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
return outpcmbufsize;
}
u32 AuCtx::AuGetLoopNum()
{
return LoopNum;
}
u32 AuCtx::AuSetLoopNum(int loop)
{
LoopNum = loop;
return 0;
}
// return 1 to read more data stream, 0 don't read
int AuCtx::AuCheckStreamDataNeeded() {
// If we would ask for bytes, then some are needed.

View file

@ -37,15 +37,17 @@ class AudioDecoder {
public:
virtual ~AudioDecoder() {}
virtual PSPAudioType GetAudioType() const = 0;
virtual bool Decode(const uint8_t* inbuf, int inbytes, 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 PSPAudioType GetAudioType() const = 0;
virtual void SetChannels(int channels) = 0;
virtual void SetExtraData(const uint8_t *data, int size, int wav_bytes_per_packet) = 0;
virtual void SetExtraData(const uint8_t *data, int size, int wav_bytes_per_packet) {}
// Just metadata.
void SetCtxPtr(uint32_t ptr) { ctxPtr = ptr; }
@ -73,10 +75,6 @@ public:
int AuStreamWorkareaSize();
u32 AuResetPlayPosition();
u32 AuResetPlayPositionByFrame(int position);
u32 AuSetLoopNum(int loop);
u32 AuGetLoopNum();
u32 AuGetInfoToAddStreamData(u32 bufPtr, u32 sizePtr, u32 srcPosPtr);
void SetReadPos(int pos) { readPos = pos; }

View file

@ -171,6 +171,9 @@ endif
SOURCES_C += $(LIBRETRODIR)/ext/glew/glew.c
SOURCES_C += \
$(EXTDIR)/minimp3/minimp3.cpp
SOURCES_C += \
$(EXTDIR)/libkirk/AES.c \
$(EXTDIR)/libkirk/amctrl.c \