diff --git a/Core/HLE/sceAudio.h b/Core/HLE/sceAudio.h index 0ae242b3ea..bf8af1e62b 100644 --- a/Core/HLE/sceAudio.h +++ b/Core/HLE/sceAudio.h @@ -90,4 +90,3 @@ extern AudioChannel chans[PSP_AUDIO_CHANNEL_MAX + 1]; void Register_sceAudio(); -u32 sceAudioSetFrequency(u32 freq); \ No newline at end of file diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index ce33c666b9..86d7976d02 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -127,7 +127,8 @@ void __Mp3DoState(PointerWrap &p) { mp3->MaxOutputSample = mp3_old->mp3MaxSamples; mp3->readPos = mp3_old->readPosition; mp3->AuBufAvailable = 0; // reset to read from file - mp3->writePos = 0; // reset to read from buffer + mp3->askedReadSize = 0; + mp3->realReadSize = 0; mp3->audioType = PSP_CODEC_MP3; mp3->decoder = new SimpleAudio(mp3->audioType); @@ -331,18 +332,17 @@ int sceMp3Init(u32 mp3) { ctx->decoder->setResampleFrequency(ctx->freq); } - // For mp3 file, if ID3 tag is detected, we must move startPos and writePos to 0x400 (stream start position), and reduce the available buffer size by 0x400 + // For mp3 file, if ID3 tag is detected, we must move startPos to 0x400 (stream start position), remove 0x400 bytes of the sourcebuff, and reduce the available buffer size by 0x400 // this is very important for ID3 tag mp3, since our universal audio decoder is for decoding stream part only. if (isID3){ // if get ID3 tage, we will decode from 0x400 ctx->startPos = 0x400; - ctx->writePos = 0x400; + ctx->sourcebuff.erase(0, 0x400); ctx->AuBufAvailable -= 0x400; } else{ // if no ID3 tag, we will decode from the begining of the file ctx->startPos = 0; - ctx->writePos = 0; } return 0; @@ -350,6 +350,8 @@ int sceMp3Init(u32 mp3) { int sceMp3GetLoopNum(u32 mp3) { DEBUG_LOG(ME, "sceMp3GetLoopNum(%08x)", mp3); + INFO_LOG(ME, "sceMp3GetLoopNum(%08x)", mp3); + AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); @@ -372,7 +374,7 @@ int sceMp3GetMaxOutputSample(u32 mp3) } int sceMp3GetSumDecodedSample(u32 mp3) { - DEBUG_LOG_REPORT(ME, "sceMp3GetSumDecodedSample(%08X)", mp3); + INFO_LOG_REPORT(ME, "sceMp3GetSumDecodedSample(%08X)", mp3); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -395,7 +397,7 @@ int sceMp3SetLoopNum(u32 mp3, int loop) { return ctx->AuSetLoopNum(loop); } int sceMp3GetMp3ChannelNum(u32 mp3) { - DEBUG_LOG(ME, "sceMp3GetMp3ChannelNum(%08X)", mp3); + INFO_LOG(ME, "sceMp3GetMp3ChannelNum(%08X)", mp3); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -406,7 +408,7 @@ int sceMp3GetMp3ChannelNum(u32 mp3) { return ctx->AuGetChannelNum(); } int sceMp3GetBitRate(u32 mp3) { - DEBUG_LOG(ME, "sceMp3GetBitRate(%08X)", mp3); + INFO_LOG(ME, "sceMp3GetBitRate(%08X)", mp3); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -417,7 +419,7 @@ int sceMp3GetBitRate(u32 mp3) { return ctx->AuGetBitRate(); } int sceMp3GetSamplingRate(u32 mp3) { - DEBUG_LOG(ME, "sceMp3GetSamplingRate(%08X)", mp3); + INFO_LOG(ME, "sceMp3GetSamplingRate(%08X)", mp3); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -429,7 +431,7 @@ int sceMp3GetSamplingRate(u32 mp3) { } int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) { - DEBUG_LOG(ME, "sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); + INFO_LOG(ME, "sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -441,7 +443,7 @@ int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcpos } int sceMp3NotifyAddStreamData(u32 mp3, int size) { - DEBUG_LOG(ME, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); + INFO_LOG(ME, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { @@ -453,7 +455,7 @@ int sceMp3NotifyAddStreamData(u32 mp3, int size) { } int sceMp3ReleaseMp3Handle(u32 mp3) { - DEBUG_LOG(ME, "sceMp3ReleaseMp3Handle(%08X)", mp3); + INFO_LOG(ME, "sceMp3ReleaseMp3Handle(%08X)", mp3); AuCtx *ctx = getMp3Ctx(mp3); if (!ctx) { diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index 18e714a3e6..a7ea92d074 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "Core/Config.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HW/SimpleAudioDec.h" @@ -302,57 +303,40 @@ u32 AuCtx::AuDecode(u32 pcmAddr) return -1; } - auto inbuff = Memory::GetPointer(AuBuf); auto outbuf = Memory::GetPointer(PCMBuf); u32 outpcmbufsize = 0; - // move inbuff to writePos of buffer - inbuff += writePos; - - // decode frames in AuBuf and output into PCMBuf if it is not exceed - while (AuBufAvailable > 0 && outpcmbufsize < PCMBufSize){ + int repeat = 1; + if (g_Config.bSoundSpeedHack){ + repeat = 2; + } + int i = 0; + // decode frames in sourcebuff and output into PCMBuf (each time, we decode one or two frames) + // some games as Miku like one frame each time, some games like DOA like two frames each time + while (sourcebuff.size() > 0 && outpcmbufsize < PCMBufSize && i < repeat){ + i++; int pcmframesize; // decode - decoder->Decode(inbuff, AuBufAvailable, outbuf, &pcmframesize); + decoder->Decode((void*)sourcebuff.c_str(), (int)sourcebuff.size(), outbuf, &pcmframesize); if (pcmframesize == 0){ - // no output pcm, we have either no data or no enough data to decode - // move back audio source readPos to the begin of the last incomplete frame if we not start looping and reset available AuBuf - if (readPos > startPos) { // this means we are not begin to loop yet - readPos -= AuBufAvailable; - } - AuBufAvailable = 0; + // no output pcm, we are at the end of the stream break; } // count total output pcm size outpcmbufsize += pcmframesize; // count total output samples SumDecodedSamples += decoder->getOutSamples(); - // move inbuff position to next frame + // get consumed source length int srcPos = decoder->getSourcePos(); - inbuff += srcPos; - // decrease available AuBuf + // remove the consumed source + sourcebuff.erase(0, srcPos); + // reduce the available Aubuff size AuBufAvailable -= srcPos; - // modify the writePos value - writePos += srcPos; // move outbuff position to the current end of output outbuf += pcmframesize; - // audio hack, default we will not do while and break here - if (!g_Config.bSoundSpeedHack){ - break; - } } Memory::Write_U32(PCMBuf, pcmAddr); - - // if we got zero pcm, and we still haven't reach endPos. - // some game like "Miku" will stop playing if we return 0, but some others will recharge buffer. - // so we did a hack here, clear output buff and just return a nonzero value to continue - if (outpcmbufsize == 0 && readPos < endPos){ - // clear output buffer will avoid noise - memset(outbuf, 0, PCMBufSize); - return FF_INPUT_BUFFER_PADDING_SIZE; // return a padding size seems very good and almost unsensible latency. - } - return outpcmbufsize; } @@ -371,7 +355,7 @@ u32 AuCtx::AuSetLoopNum(int loop) int AuCtx::AuCheckStreamDataNeeded() { // if we have no available Au buffer, and the current read position in source file is not the end of stream, then we can read - if (AuBufAvailable == 0 && readPos < endPos){ + if (AuBufAvailable < AuBufSize && readPos < endPos){ return 1; } return 0; @@ -387,6 +371,9 @@ u32 AuCtx::AuNotifyAddStreamData(int size) AuBufAvailable += diffszie; } + // append AuBuf into sourcebuff + sourcebuff.append((const char*)Memory::GetPointer(AuBuf), size); + if (readPos >= endPos && LoopNum != 0){ // if we need loop, reset readPos readPos = startPos; @@ -403,18 +390,19 @@ u32 AuCtx::AuNotifyAddStreamData(int size) // buff, size and srcPos are all pointers u32 AuCtx::AuGetInfoToAddStreamData(u32 buff, u32 size, u32 srcPos) { + int readsize = std::min((int)AuBufSize - AuBufAvailable, (int)endPos - readPos); + // we can recharge AuBuf from its begining if (Memory::IsValidAddress(buff)) Memory::Write_U32(AuBuf, buff); if (Memory::IsValidAddress(size)) - Memory::Write_U32(AuBufSize, size); + Memory::Write_U32(readsize, size); if (Memory::IsValidAddress(srcPos)) Memory::Write_U32(readPos, srcPos); - askedReadSize = AuBufSize; + askedReadSize = readsize; readPos += askedReadSize; AuBufAvailable += askedReadSize; - writePos = 0; return 0; } diff --git a/Core/HW/SimpleAudioDec.h b/Core/HW/SimpleAudioDec.h index 7f12b5ff00..e8902b8edd 100644 --- a/Core/HW/SimpleAudioDec.h +++ b/Core/HW/SimpleAudioDec.h @@ -128,9 +128,9 @@ public: // buffers informations int AuBufAvailable; // the available buffer of AuBuf to be able to recharge data int readPos; // read position in audio source file - int writePos; // write position in AuBuf, i.e. the size of bytes decoded in AuBuf. int askedReadSize; // the size of data requied to be read from file by the game int realReadSize; // the really read size from file + std::string sourcebuff; // source buffer AuCtx() :decoder(NULL){}; ~AuCtx(){ @@ -172,15 +172,16 @@ public: p.Do(LoopNum); p.Do(Channels); p.Do(MaxOutputSample); - p.Do(AuBufAvailable); p.Do(readPos); - p.Do(writePos); p.Do(audioType); p.Do(BitRate); p.Do(SamplingRate); + p.Do(askedReadSize); + p.Do(realReadSize); if (p.mode == p.MODE_READ){ decoder = new SimpleAudio(audioType); + AuBufAvailable = 0; // reset to read from file at position readPos } }; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index baf6d46d71..15a9447ebb 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -249,7 +249,7 @@ void GameSettingsScreen::CreateViews() { lowAudio->SetEnabledPtr(&g_Config.bEnableSound); audioSettings->Add(new ItemHeader(ms->T("Audio hacks"))); - audioSettings->Add(new CheckBox(&g_Config.bSoundSpeedHack, a->T("Sound speed hack (fill pcm buffer)"))); + audioSettings->Add(new CheckBox(&g_Config.bSoundSpeedHack, a->T("Sound speed hack (DOA etc.)"))); // Control ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));