Merge pull request #19024 from hrydgard/audio-decoder-refactor

Audio format decoder: Refactor to enable multiple decoder implementations
This commit is contained in:
Henrik Rydgård 2024-04-10 14:52:03 +02:00 committed by GitHub
commit c6f5ac0c81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 189 additions and 137 deletions

View File

@ -36,12 +36,12 @@ struct AudioCodecContext {
};
// audioList is to store current playing audios.
static std::map<u32, SimpleAudio *> audioList;
static std::map<u32, AudioDecoder *> audioList;
static bool oldStateLoaded = false;
// find the audio decoder for corresponding ctxPtr in audioList
static SimpleAudio *findDecoder(u32 ctxPtr) {
static AudioDecoder *findDecoder(u32 ctxPtr) {
auto it = audioList.find(ctxPtr);
if (it != audioList.end()) {
return it->second;
@ -77,29 +77,31 @@ void __AudioCodecShutdown() {
}
static int sceAudiocodecInit(u32 ctxPtr, int codec) {
if (IsValidCodec(codec)) {
PSPAudioType audioType = (PSPAudioType)codec;
if (IsValidCodec(audioType)) {
// Create audio decoder for given audio codec and push it into AudioList
if (removeDecoder(ctxPtr)) {
WARN_LOG_REPORT(HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec);
}
auto decoder = new SimpleAudio(codec);
AudioDecoder *decoder = CreateAudioDecoder(audioType);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(audioType));
DEBUG_LOG(ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size());
return 0;
}
ERROR_LOG_REPORT(ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(codec), codec);
ERROR_LOG_REPORT(ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(audioType), codec);
return 0;
}
static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
PSPAudioType audioType = (PSPAudioType)codec;
if (!ctxPtr){
ERROR_LOG_REPORT(ME, "sceAudiocodecDecode(%08x, %i (%s)) got NULL pointer", ctxPtr, codec, GetCodecName(codec));
ERROR_LOG_REPORT(ME, "sceAudiocodecDecode(%08x, %i (%s)) got NULL pointer", ctxPtr, codec, GetCodecName(audioType));
return -1;
}
if (IsValidCodec(codec)){
if (IsValidCodec(audioType)){
int outbytes = 0;
// find a decoder in audioList
auto decoder = findDecoder(ctxPtr);
@ -107,7 +109,7 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
if (!decoder && oldStateLoaded) {
// We must have loaded an old state that did not have sceAudiocodec information.
// Fake it by creating the desired context.
decoder = new SimpleAudio(codec);
decoder = CreateAudioDecoder(audioType);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
}
@ -194,7 +196,7 @@ void __sceAudiocodecDoState(PointerWrap &p){
DoArray(p, codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));
DoArray(p, ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));
for (int i = 0; i < count; i++) {
auto decoder = new SimpleAudio(codec_[i]);
auto decoder = CreateAudioDecoder((PSPAudioType)codec_[i]);
decoder->SetCtxPtr(ctxPtr_[i]);
audioList[ctxPtr_[i]] = decoder;
}
@ -214,7 +216,7 @@ void __sceAudiocodecDoState(PointerWrap &p){
auto ctxPtr_ = new u32[count];
int i = 0;
for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
const SimpleAudio *decoder = it->second;
const AudioDecoder *decoder = it->second;
codec_[i] = decoder->GetAudioType();
ctxPtr_[i] = decoder->GetCtxPtr();
i++;

View File

@ -124,6 +124,7 @@ void __KernelInit()
__IoInit();
__JpegInit();
__AudioInit();
__Mp3Init();
__SasInit();
__AtracInit();
__CccInit();

View File

@ -15,6 +15,57 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// Games known to support custom music and almost certainly use sceMp3:
//
// * ATV Offroad Fury: Blazin' Trails
// * Beats (/PSP/MUSIC)
// * Crazy Taxi : Fare Wars (/MUSIC)
// * Dead or Alive Paradise
// * Gran Turismo - You must first clear all driving challenges up to C to unlock this feature, then it will be available through the options menu.
// * Grand Theft Auto : Liberty City Stories
// * Grand Theft Auto : Vice City Stories
// * Heroes' VS (#5866 ?)
// * MLB 08 : The Show
// * MotorStorm : Artic Edge
// * NBA Live 09
// * Need for Speed Carbon
// * Need for Speed Pro Street
// * Pro Evolution Soccer 2014
// * SD Gundam G Generation Overworld
// * TOCA Race Driver 2
// * Untold Legends II
// * Wipeout Pulse (/MUSIC/WIPEOUT)
//
// Games known to use LowLevelDecode:
//
// * Gundam G (custom BGM)
// * Heroes' VS (custom BGM)
//
// Games that use sceMp3 internally
//
// * Kirameki School Life SP
// * Breakquest (mini)
// * Orbit (mini)
// * SWAT Target Liberty ULES00927
// * Geometry Wars (homebrew)
// * Hanayaka Nari Wa ga Ichizoku
// * Velocity (mini)
// * N+ (mini) (#9379)
// * Mighty Flip Champs DX (mini)
// * EDGE (mini)
// * Stellar Attack (mini)
// * Hungry Giraffe (mini)
// * OMG - Z (mini)
// ...probably lots more minis...
//
// BUGS
//
// Custom music plays but starts stuttering:
// * Beats
//
// Custom music just repeats a small section:
// * Crazy Taxi
#include <map>
#include <algorithm>
@ -44,9 +95,9 @@ static const int AU_BUF_MIN_SIZE = 8192;
static const int PCM_BUF_MIN_SIZE = 9216;
static const size_t MP3_MAX_HANDLES = 2;
struct Mp3Context {
// This one is only used for save state upgrading.
struct Mp3ContextOld {
public:
int mp3StreamStart;
int mp3StreamEnd;
u32 mp3Buf;
@ -106,6 +157,10 @@ static AuCtx *getMp3Ctx(u32 mp3) {
return mp3Map[mp3];
}
void __Mp3Init() {
resourceInited = false;
}
void __Mp3Shutdown() {
for (auto it = mp3Map.begin(), end = mp3Map.end(); it != end; ++it) {
delete it->second;
@ -121,7 +176,7 @@ void __Mp3DoState(PointerWrap &p) {
if (s >= 2) {
Do(p, mp3Map);
} else {
std::map<u32, Mp3Context *> mp3Map_old;
std::map<u32, Mp3ContextOld *> mp3Map_old;
Do(p, mp3Map_old); // read old map
for (auto it = mp3Map_old.begin(), end = mp3Map_old.end(); it != end; ++it) {
auto mp3 = new AuCtx;
@ -143,8 +198,7 @@ void __Mp3DoState(PointerWrap &p) {
mp3->MaxOutputSample = mp3_old->mp3MaxSamples;
mp3->SetReadPos(mp3_old->readPosition);
mp3->audioType = PSP_CODEC_MP3;
mp3->decoder = new SimpleAudio(mp3->audioType);
mp3->decoder = CreateAudioDecoder(PSP_CODEC_MP3);
mp3Map[id] = mp3;
}
}
@ -249,9 +303,8 @@ static u32 sceMp3ReserveMp3Handle(u32 mp3Addr) {
Au->PCMBufSize = 0;
}
Au->audioType = PSP_CODEC_MP3;
Au->SetReadPos(Au->startPos);
Au->decoder = new SimpleAudio(Au->audioType);
Au->decoder = CreateAudioDecoder(PSP_CODEC_MP3);
int handle = (int)mp3Map.size();
mp3Map[handle] = Au;
@ -445,9 +498,6 @@ static int sceMp3Init(u32 mp3) {
ctx->Version = versionBits;
// This tells us to resample to the same frequency it decodes to.
ctx->decoder->SetResampleFrequency(ctx->freq);
return hleDelayResult(hleLogSuccessI(ME, 0), "mp3 init", PARSE_DELAY_MS);
}
@ -476,7 +526,7 @@ static int sceMp3GetMaxOutputSample(u32 mp3) {
return hleLogWarning(ME, 0, "no channel available for low level");
}
return hleLogSuccessI(ME, ctx->AuGetMaxOutputSample());
return hleLogSuccessI(ME, ctx->MaxOutputSample);
}
static int sceMp3GetSumDecodedSample(u32 mp3) {
@ -489,7 +539,7 @@ static int sceMp3GetSumDecodedSample(u32 mp3) {
return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
}
return hleLogSuccessI(ME, ctx->AuGetSumDecodedSample());
return hleLogSuccessI(ME, ctx->SumDecodedSamples);
}
static int sceMp3SetLoopNum(u32 mp3, int loop) {
@ -520,7 +570,7 @@ static int sceMp3GetMp3ChannelNum(u32 mp3) {
return hleLogWarning(ME, 0, "no channel available for low level");
}
return hleLogSuccessI(ME, ctx->AuGetChannelNum());
return hleLogSuccessI(ME, ctx->Channels);
}
static int sceMp3GetBitRate(u32 mp3) {
@ -535,7 +585,7 @@ static int sceMp3GetBitRate(u32 mp3) {
return hleLogWarning(ME, 0, "no bitrate available for low level");
}
return hleLogSuccessI(ME, ctx->AuGetBitRate());
return hleLogSuccessI(ME, ctx->BitRate);
}
static int sceMp3GetSamplingRate(u32 mp3) {
@ -550,7 +600,7 @@ static int sceMp3GetSamplingRate(u32 mp3) {
return hleLogWarning(ME, 0, "no sample rate available for low level");
}
return hleLogSuccessI(ME, ctx->AuGetSamplingRate());
return hleLogSuccessI(ME, ctx->SamplingRate);
}
static int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) {
@ -613,7 +663,7 @@ static u32 sceMp3GetFrameNum(u32 mp3) {
return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
}
return hleLogSuccessI(ME, ctx->AuGetFrameNum());
return hleLogSuccessI(ME, ctx->FrameNum);
}
static u32 sceMp3GetMPEGVersion(u32 mp3) {
@ -630,7 +680,7 @@ static u32 sceMp3GetMPEGVersion(u32 mp3) {
}
// Tests have not revealed how to expose more than "3" here as a result.
return hleReportDebug(ME, ctx->AuGetVersion());
return hleReportDebug(ME, ctx->Version);
}
static u32 sceMp3ResetPlayPositionByFrame(u32 mp3, u32 frame) {
@ -643,7 +693,7 @@ static u32 sceMp3ResetPlayPositionByFrame(u32 mp3, u32 frame) {
return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
}
if (frame >= (u32)ctx->AuGetFrameNum()) {
if (frame >= (u32)ctx->FrameNum) {
return hleLogError(ME, ERROR_MP3_BAD_RESET_FRAME, "bad frame position");
}
@ -651,11 +701,10 @@ static u32 sceMp3ResetPlayPositionByFrame(u32 mp3, u32 frame) {
}
static u32 sceMp3LowLevelInit(u32 mp3, u32 unk) {
auto ctx = new AuCtx;
auto ctx = new AuCtx();
ctx->audioType = PSP_CODEC_MP3;
// create mp3 decoder
ctx->decoder = new SimpleAudio(ctx->audioType);
ctx->decoder = CreateAudioDecoder(PSP_CODEC_MP3);
// close the audio if mp3 already exists.
if (mp3Map.find(mp3) != mp3Map.end()) {

View File

@ -21,5 +21,6 @@ class PointerWrap;
void Register_sceMp3();
void __Mp3Init();
void __Mp3Shutdown();
void __Mp3DoState(PointerWrap &p);
void __Mp3DoState(PointerWrap &p);

View File

@ -253,10 +253,9 @@ static u32 sceAacInit(u32 id)
aac->Channels = 2;
aac->MaxOutputSample = aac->PCMBufSize / 4;
aac->SetReadPos((int)aac->startPos);
aac->audioType = PSP_CODEC_AAC;
// create aac decoder
aac->decoder = new SimpleAudio(aac->audioType);
aac->decoder = CreateAudioDecoder(PSP_CODEC_AAC);
// close the audio if id already exist.
if (aacMap.find(id) != aacMap.end()) {
@ -368,7 +367,7 @@ static u32 sceAacGetMaxOutputSample(u32 id)
return -1;
}
return ctx->AuGetMaxOutputSample();
return ctx->MaxOutputSample;
}
static u32 sceAacGetSumDecodedSample(u32 id)
@ -380,7 +379,7 @@ static u32 sceAacGetSumDecodedSample(u32 id)
return -1;
}
return ctx->AuGetSumDecodedSample();
return ctx->SumDecodedSamples;
}
static u32 sceAacResetPlayPosition(u32 id)

View File

@ -340,7 +340,7 @@ bool MediaEngine::openContext(bool keepReadPos) {
return false;
setVideoDim();
m_audioContext = new SimpleAudio(m_audioType, 44100, 2);
m_audioContext = CreateAudioDecoder((PSPAudioType)m_audioType);
m_isVideoEnd = false;
#endif // USE_FFMPEG
return true;

View File

@ -31,7 +31,7 @@
#include "Core/HW/SimpleAudioDec.h"
class PointerWrap;
class SimpleAudio;
class AudioDecoder;
#ifdef USE_FFMPEG
struct SwsContext;
@ -50,8 +50,7 @@ inline s64 getMpegTimeStamp(const u8 *buf) {
bool InitFFmpeg();
#endif
class MediaEngine
{
class MediaEngine {
public:
MediaEngine();
~MediaEngine();
@ -144,7 +143,7 @@ private:
s64 m_lastPts = -1;
MpegDemux *m_demux = nullptr;
SimpleAudio *m_audioContext = nullptr;
AudioDecoder *m_audioContext = nullptr;
s64 m_audiopts = 0;
// used for audio type

View File

@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include <cmath>
#include "Common/Serialize/SerializeFuncs.h"
#include "Core/Config.h"
@ -32,12 +33,63 @@ extern "C" {
#include "libswresample/swresample.h"
#include "libavutil/samplefmt.h"
#include "libavcodec/avcodec.h"
}
#include "libavutil/version.h"
#include "Core/FFMPEGCompat.h"
}
#endif // USE_FFMPEG
int SimpleAudio::GetAudioCodecID(int audioType) {
// FFMPEG-based decoder. TODO: Replace with individual codecs.
class SimpleAudio : public AudioDecoder {
public:
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 IsOK() const override;
int GetOutSamples() const override {
return outSamples;
}
int GetSourcePos() const override {
return srcPos;
}
// 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; }
private:
bool OpenCodec(int block_align);
PSPAudioType audioType;
int sample_rate_;
int channels_;
int outSamples; // output samples per frame
int srcPos; // bytes consumed in source during the last decoding
AVFrame *frame_;
#if HAVE_LIBAVCODEC_CONST_AVCODEC // USE_FFMPEG is implied
const
#endif
AVCodec *codec_;
AVCodecContext *codecCtx_;
SwrContext *swrCtx_;
bool codecOpen_;
};
// 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);
}
static int GetAudioCodecID(int audioType) {
#ifdef USE_FFMPEG
switch (audioType) {
case PSP_CODEC_AAC:
@ -56,14 +108,12 @@ int SimpleAudio::GetAudioCodecID(int audioType) {
#endif // USE_FFMPEG
}
SimpleAudio::SimpleAudio(int audioType, int sample_rate, int channels)
: ctxPtr(0xFFFFFFFF), audioType(audioType), sample_rate_(sample_rate), channels_(channels),
outSamples(0), srcPos(0), wanted_resample_freq(44100), frame_(0), codec_(0), codecCtx_(0), swrCtx_(0),
codecOpen_(false) {
Init();
}
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) {
void SimpleAudio::Init() {
#ifdef USE_FFMPEG
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
avcodec_register_all();
@ -122,7 +172,7 @@ bool SimpleAudio::OpenCodec(int block_align) {
#endif // USE_FFMPEG
}
void SimpleAudio::SetExtraData(const u8 *data, int size, int wav_bytes_per_packet) {
void SimpleAudio::SetExtraData(const uint8_t *data, int size, int wav_bytes_per_packet) {
#ifdef USE_FFMPEG
if (codecCtx_) {
codecCtx_->extradata = (uint8_t *)av_mallocz(size);
@ -179,6 +229,7 @@ bool SimpleAudio::IsOK() const {
#endif
}
// Decodes a single input frame.
bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
#ifdef USE_FFMPEG
if (!codecOpen_) {
@ -238,7 +289,7 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
swrCtx_,
wanted_channel_layout,
AV_SAMPLE_FMT_S16,
wanted_resample_freq,
codecCtx_->sample_rate,
dec_channel_layout,
codecCtx_->sample_fmt,
codecCtx_->sample_rate,
@ -279,12 +330,11 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
#endif // USE_FFMPEG
}
int SimpleAudio::GetOutSamples() {
return outSamples;
}
int SimpleAudio::GetSourcePos() {
return srcPos;
void AudioClose(AudioDecoder **ctx) {
#ifdef USE_FFMPEG
delete *ctx;
*ctx = 0;
#endif // USE_FFMPEG
}
void AudioClose(SimpleAudio **ctx) {
@ -294,7 +344,6 @@ void AudioClose(SimpleAudio **ctx) {
#endif // USE_FFMPEG
}
static const char *const codecNames[4] = {
"AT3+", "AT3", "MP3", "AAC",
};
@ -307,7 +356,7 @@ const char *GetCodecName(int codec) {
}
};
bool IsValidCodec(int codec){
bool IsValidCodec(PSPAudioType codec){
if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
return true;
}
@ -328,7 +377,7 @@ AuCtx::~AuCtx() {
}
size_t AuCtx::FindNextMp3Sync() {
if (audioType != PSP_CODEC_MP3) {
if (decoder->GetAudioType() != PSP_CODEC_MP3) {
return 0;
}
@ -421,7 +470,7 @@ int AuCtx::AuCheckStreamDataNeeded() {
}
int AuCtx::AuStreamBytesNeeded() {
if (audioType == PSP_CODEC_MP3) {
if (decoder->GetAudioType() == PSP_CODEC_MP3) {
// The endPos and readPos are not considered, except when you've read to the end.
if (readPos >= endPos)
return 0;
@ -436,7 +485,7 @@ int AuCtx::AuStreamBytesNeeded() {
int AuCtx::AuStreamWorkareaSize() {
// Note that this is 31 bytes more than the max layer 3 frame size.
if (audioType == PSP_CODEC_MP3)
if (decoder->GetAudioType() == PSP_CODEC_MP3)
return 0x05c0;
return 0;
}
@ -533,6 +582,7 @@ void AuCtx::DoState(PointerWrap &p) {
Do(p, Channels);
Do(p, MaxOutputSample);
Do(p, readPos);
int audioType = (int)decoder->GetAudioType();
Do(p, audioType);
Do(p, BitRate);
Do(p, SamplingRate);
@ -552,6 +602,6 @@ void AuCtx::DoState(PointerWrap &p) {
}
if (p.mode == p.MODE_READ) {
decoder = new SimpleAudio(audioType);
decoder = CreateAudioDecoder((PSPAudioType)audioType);
}
}

View File

@ -17,88 +17,48 @@
#pragma once
#include <cmath>
#include "Core/HW/MediaEngine.h"
#include "Core/HLE/sceAudio.h"
struct AVFrame;
struct AVCodec;
struct AVCodecContext;
struct SwrContext;
#ifdef USE_FFMPEG
extern "C" {
#include "libavutil/version.h"
};
#endif
// Wraps FFMPEG for audio decoding in a nice interface.
// Decodes packet by packet - does NOT demux.
// Based on http://ffmpeg.org/doxygen/trunk/doc_2examples_2decoding_encoding_8c-example.html#_a13
// audioType
enum {
enum PSPAudioType {
PSP_CODEC_AT3PLUS = 0x00001000,
PSP_CODEC_AT3 = 0x00001001,
PSP_CODEC_MP3 = 0x00001002,
PSP_CODEC_AAC = 0x00001003,
};
class SimpleAudio {
class AudioDecoder {
public:
SimpleAudio(int audioType, int sample_rate = 44100, int channels = 2);
~SimpleAudio();
virtual ~AudioDecoder() {}
bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes);
bool IsOK() const;
virtual bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) = 0;
virtual bool IsOK() const = 0;
int GetOutSamples();
int GetSourcePos();
int GetAudioCodecID(int audioType); // Get audioCodecId from audioType
virtual int GetOutSamples() const = 0;
virtual int GetSourcePos() const = 0;
virtual PSPAudioType GetAudioType() const = 0;
// Not save stated, only used by UI. Used for ATRAC3 (non+) files.
void SetExtraData(const u8 *data, int size, int wav_bytes_per_packet);
void SetChannels(int channels);
// These two are only here because of save states.
int GetAudioType() const { return audioType; }
void SetResampleFrequency(int freq) { wanted_resample_freq = freq; }
virtual void SetChannels(int channels) = 0;
virtual void SetExtraData(const uint8_t *data, int size, int wav_bytes_per_packet) = 0;
// Just metadata.
void SetCtxPtr(u32 ptr) { ctxPtr = ptr; }
u32 GetCtxPtr() const { return ctxPtr; }
void SetCtxPtr(uint32_t ptr) { ctxPtr = ptr; }
uint32_t GetCtxPtr() const { return ctxPtr; }
private:
void Init();
bool OpenCodec(int block_align);
u32 ctxPtr;
int audioType;
int sample_rate_;
int channels_;
int outSamples; // output samples per frame
int srcPos; // bytes consumed in source during the last decoding
int wanted_resample_freq; // wanted resampling rate/frequency
AVFrame *frame_;
#if HAVE_LIBAVCODEC_CONST_AVCODEC // USE_FFMPEG is implied
const
#endif
AVCodec *codec_;
AVCodecContext *codecCtx_;
SwrContext *swrCtx_;
bool codecOpen_;
uint32_t ctxPtr = 0xFFFFFFFF;
};
void AudioClose(SimpleAudio **ctx);
void AudioClose(AudioDecoder **ctx);
const char *GetCodecName(int codec); // audioType
bool IsValidCodec(int codec);
bool IsValidCodec(PSPAudioType codec);
AudioDecoder *CreateAudioDecoder(PSPAudioType audioType, int sampleRateHz = 44100, int channels = 2);
class AuCtx {
public:
@ -118,13 +78,6 @@ public:
u32 AuGetLoopNum();
u32 AuGetInfoToAddStreamData(u32 bufPtr, u32 sizePtr, u32 srcPosPtr);
u32 AuGetMaxOutputSample() const { return MaxOutputSample; }
u32 AuGetSumDecodedSample() const { return SumDecodedSamples; }
int AuGetChannelNum() const { return Channels; }
int AuGetBitRate() const { return BitRate; }
int AuGetSamplingRate() const { return SamplingRate; }
int AuGetVersion() const { return Version; }
int AuGetFrameNum() const { return FrameNum; }
void SetReadPos(int pos) { readPos = pos; }
int ReadPos() { return readPos; }
@ -146,7 +99,8 @@ public:
u32 AuBufSize = 0;
u32 PCMBuf = 0;
u32 PCMBufSize = 0;
int freq = -1;
int freq = -1; // used by AAC only?
int BitRate = 0;
int SamplingRate = -1;
int Channels = 0;
@ -159,10 +113,7 @@ public:
int FrameNum = 0;
// Au decoder
SimpleAudio *decoder = nullptr;
// Au type
int audioType = 0;
AudioDecoder *decoder = nullptr;
private:
size_t FindNextMp3Sync();
@ -171,7 +122,7 @@ private:
// buffers informations
int AuBufAvailable = 0; // the available buffer of AuBuf to be able to recharge data
int readPos; // read position in audio source file
int readPos = 0; // read position in audio source file
int askedReadSize = 0; // the size of data requied to be read from file by the game
int nextOutputHalf = 0;
};

View File

@ -189,7 +189,7 @@ public:
wave_.Read(file_);
decoder_ = new SimpleAudio(wave_.codec, wave_.sample_rate, wave_.num_channels);
decoder_ = CreateAudioDecoder((PSPAudioType)wave_.codec, wave_.sample_rate, wave_.num_channels);
if (wave_.codec == PSP_CODEC_AT3) {
decoder_->SetExtraData(&wave_.at3_extradata[2], 14, wave_.raw_bytes_per_frame);
}
@ -256,7 +256,7 @@ private:
int skip_next_samples_ = 0;
FixedSizeQueue<s16, 128 * 1024> bgQueue;
short *buffer_ = nullptr;
SimpleAudio *decoder_ = nullptr;
AudioDecoder *decoder_ = nullptr;
};
BackgroundAudio g_BackgroundAudio;
@ -433,7 +433,7 @@ Sample *Sample::Load(const std::string &path) {
// mp3_info contains the decoded data.
int16_t *sample_data = new int16_t[mp3_info.samples];
memcpy(sample_data, mp3_info.buffer, mp3_info.samples * sizeof(int16_t));
Sample *sample = new Sample(sample_data, mp3_info.channels, mp3_info.samples, mp3_info.hz);
Sample *sample = new Sample(sample_data, mp3_info.channels, (int)mp3_info.samples, mp3_info.hz);
free(mp3_info.buffer);
delete[] data;
return sample;