diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index b4e56d32aa..25339506c7 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -326,6 +326,11 @@ int sceMp3Init(u32 mp3) { INFO_LOG(ME, "sceMp3Init(): channels=%i, samplerate=%iHz, bitrate=%ikbps", ctx->Channels, ctx->SamplingRate, ctx->BitRate); + // Read information from source via ffmpeg and re-create codec context + // This is an automatic method without knowledge in audio file format + // ctx->AuCreateCodecContextFromSource(); + // INFO_LOG(ME, "sceMp3Init() ffmpeg: channels=%i, samplerate=%iHz, bitrate=%ikbps", ctx->Channels, ctx->SamplingRate, ctx->BitRate); + // for mp3, if required freq is 48000, reset resampling Frequency to 48000 seems get better sound quality (e.g. Miku Custom BGM) if (ctx->freq == 48000){ ctx->decoder->setResampleFrequency(ctx->freq); diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index de561ece54..ca0471cada 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -458,4 +458,86 @@ int AuCtx::AuGetVersion(){ int AuCtx::AuGetFrameNum(){ return FrameNum; -} \ No newline at end of file +} + +static int _Readbuffer(void *opaque, uint8_t *buf, int buf_size) { + auto ctx = (AuCtx *)opaque; + int toread = std::min((int)ctx->AuBufSize, buf_size); + memcpy(buf, Memory::GetPointer(ctx->AuBuf), toread); + return toread; +} + +static void closeAvioCtxandFormatCtx(AVIOContext* pAVIOCtx, AVFormatContext* pFormatCtx){ + if (pAVIOCtx && pAVIOCtx->buffer) + av_free(pAVIOCtx->buffer); + if (pAVIOCtx) + av_free(pAVIOCtx); + if (pFormatCtx) + avformat_close_input(&pFormatCtx); +} + +// you need at least have initialized AuBuf, AuBufSize and decoder +bool AuCtx::AuCreateCodecContextFromSource(){ + u8* tempbuf = (u8*)av_malloc(AuBufSize); + + auto pFormatCtx = avformat_alloc_context(); + auto pAVIOCtx = avio_alloc_context(tempbuf, AuBufSize, 0, (void*)this, _Readbuffer, NULL, NULL); + pFormatCtx->pb = pAVIOCtx; + + int ret; + // Load audio buffer + if ((ret = avformat_open_input((AVFormatContext**)&pFormatCtx, NULL, NULL, NULL)) != 0) { + ERROR_LOG(ME, "avformat_open_input: Cannot open input %d", ret); + closeAvioCtxandFormatCtx(pAVIOCtx,pFormatCtx); + return false; + } + + if ((ret = avformat_find_stream_info(pFormatCtx, NULL)) < 0) { + ERROR_LOG(ME, "avformat_find_stream_info: Cannot find stream information %d", ret); + closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx); + return false; + } + // reset decoder context + if (decoder->codecCtx_){ + avcodec_close(decoder->codecCtx_); + av_free(decoder->codecCtx_); + } + decoder->codecCtx_ = pFormatCtx->streams[ret]->codec; + + if (decoder->codec_){ + decoder->codec_ = 0; + } + // select the audio stream + ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &decoder->codec_, 0); + if (ret < 0) { + if (ret == AVERROR_DECODER_NOT_FOUND) { + ERROR_LOG(HLE, "av_find_best_stream: No appropriate decoder found"); + } + else { + ERROR_LOG(HLE, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret); + } + closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx); + return false; + } + + // close and free AVIO and AVFormat + // closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx); + + // open codec + if ((ret = avcodec_open2(decoder->codecCtx_, decoder->codec_, NULL)) < 0) { + avcodec_close(decoder->codecCtx_); + av_free(decoder->codecCtx_); + decoder->codecCtx_ = 0; + decoder->codec_ = 0; + ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret); + return false; + } + + // set audio informations + SamplingRate = decoder->codecCtx_->sample_rate; + Channels = decoder->codecCtx_->channels; + BitRate = decoder->codecCtx_->bit_rate/1000; + freq = SamplingRate; + + return true; +} diff --git a/Core/HW/SimpleAudioDec.h b/Core/HW/SimpleAudioDec.h index 321602cc84..f636199f7e 100644 --- a/Core/HW/SimpleAudioDec.h +++ b/Core/HW/SimpleAudioDec.h @@ -63,7 +63,6 @@ public: int srcPos; // bytes consumed in source during the last decoding int wanted_resample_freq; // wanted resampling rate/frequency -private: #ifdef USE_FFMPEG AVFrame *frame_; AVCodec *codec_; @@ -178,6 +177,7 @@ public: u32 AuResetPlayPositionByFrame(int position); int AuGetVersion(); int AuGetFrameNum(); + bool AuCreateCodecContextFromSource(); void DoState(PointerWrap &p) { auto s = p.Section("AuContext", 0, 1);