mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-30 20:01:00 +00:00
Remove audio rate throttling, it's better to frame rate throttle. Gets rid of the slowdown that audio caused.
This commit is contained in:
parent
a385ec6056
commit
f3aeadedfa
@ -46,10 +46,9 @@ const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate);
|
||||
const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate);
|
||||
|
||||
// High and low watermarks, basically.
|
||||
const int chanQueueMaxSizeFactor = 4;
|
||||
const int chanQueueMinSizeFactor = 2;
|
||||
const int chanQueueMaxSizeFactor = 2;
|
||||
const int chanQueueMinSizeFactor = 1;
|
||||
|
||||
// A whole second, should be enough for anything.
|
||||
FixedSizeQueue<s16, hwBlockSize * 8> outAudioQueue;
|
||||
|
||||
|
||||
@ -131,25 +130,9 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking)
|
||||
// just sleep the main emulator thread a little.
|
||||
void __AudioUpdate()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// HACK - TODO: Remove
|
||||
bool noThrottle = GetAsyncKeyState(VK_TAB) != 0;
|
||||
#else
|
||||
bool noThrottle = false;
|
||||
#endif
|
||||
// Sleep here until the host audio hardware is ready to receive samples.
|
||||
// This will effectively throttle the frame rate.
|
||||
|
||||
if (!noThrottle && g_Config.bEnableSound) {
|
||||
while (true)
|
||||
{
|
||||
if (outAudioQueue.size() < hwBlockSize * 4)
|
||||
break; // room can only increase without us pushing, so there's no race condition between here and section.lock()
|
||||
Common::SleepCurrentThread(0);
|
||||
}
|
||||
}
|
||||
|
||||
section.lock();
|
||||
// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied
|
||||
// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
|
||||
// if the buffer somehow gets full.
|
||||
|
||||
s32 mixBuffer[hwBlockSize * 2];
|
||||
memset(mixBuffer, 0, sizeof(mixBuffer));
|
||||
@ -193,7 +176,9 @@ void __AudioUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
if (!noThrottle && g_Config.bEnableSound) {
|
||||
section.lock();
|
||||
|
||||
if (g_Config.bEnableSound && outAudioQueue.room() >= hwBlockSize * 2) {
|
||||
// Push the mixed samples onto the output audio queue.
|
||||
for (int i = 0; i < hwBlockSize; i++) {
|
||||
s32 sampleL = mixBuffer[i * 2] >> 2; // TODO - what factor?
|
||||
@ -233,7 +218,7 @@ int __AudioMix(short *outstereo, int numFrames)
|
||||
outstereo[i * 2 + 1] = sampleR;
|
||||
anythingToPlay = true;
|
||||
} else {
|
||||
underrun = i;
|
||||
if (underrun == -1) underrun = i;
|
||||
outstereo[i * 2] = sampleL; // repeat last sample, can reduce clicking
|
||||
outstereo[i * 2 + 1] = sampleR; // repeat last sample, can reduce clicking
|
||||
}
|
||||
|
@ -307,14 +307,17 @@ void sceAudioOutput2OutputBlocking()
|
||||
chans[0].leftVolume = vol;
|
||||
chans[0].rightVolume = vol;
|
||||
chans[0].sampleAddress = dataPtr;
|
||||
RETURN(chans[0].sampleCount);
|
||||
__AudioEnqueue(chans[0], 0, true);
|
||||
RETURN(0);
|
||||
u32 retval = __AudioEnqueue(chans[0], 0, true);
|
||||
if (retval < 0)
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
void sceAudioOutput2ChangeLength()
|
||||
u32 sceAudioOutput2ChangeLength(u32 sampleCount)
|
||||
{
|
||||
ERROR_LOG(HLE,"UNIMPL sceAudioOutput2ChangeLength");
|
||||
RETURN(0);
|
||||
WARN_LOG(HLE,"sceAudioOutput2ChangeLength(%i)");
|
||||
chans[0].sampleCount = sampleCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceAudioOutput2GetRestSample()
|
||||
@ -343,20 +346,22 @@ u32 sceAudioSetFrequency(u32 freq) {
|
||||
|
||||
const HLEFunction sceAudio[] =
|
||||
{
|
||||
{0x01562ba3, sceAudioOutput2Reserve, "sceAudioOutput2Reserve"}, // N+, Super Stardust Portable uses these
|
||||
// Newer simplified single channel audio output. Presumably for games that use Atrac3
|
||||
// directly from Sas instead of playing it on a separate audio channel.
|
||||
{0x01562ba3, sceAudioOutput2Reserve, "sceAudioOutput2Reserve"},
|
||||
{0x2d53f36e, sceAudioOutput2OutputBlocking, "sceAudioOutput2OutputBlocking"},
|
||||
{0x63f2889c, sceAudioOutput2ChangeLength, "sceAudioOutput2ChangeLength"},
|
||||
{0x63f2889c, WrapU_U<sceAudioOutput2ChangeLength>, "sceAudioOutput2ChangeLength"},
|
||||
{0x647cef33, WrapU_V<sceAudioOutput2GetRestSample>, "sceAudioOutput2GetRestSample"},
|
||||
{0x43196845, sceAudioOutput2Release, "sceAudioOutput2Release"},
|
||||
|
||||
{0x38553111, 0, "sceAudioSRCChReserve"},
|
||||
{0x5C37C0AE, 0, "sceAudioSRCChRelease"},
|
||||
{0x80F1F7E0, sceAudioInit, "sceAudioInit"},
|
||||
{0x80F1F7E0, sceAudioInit, "sceAudioInit"},
|
||||
{0x210567F7, sceAudioEnd, "sceAudioEnd"},
|
||||
{0x927AC32B, 0, "sceAudioSetVolumeOffset"},
|
||||
|
||||
{0xA2BEAA6C, WrapU_U<sceAudioSetFrequency>, "sceAudioSetFrequency"},
|
||||
{0xE0727056, 0, "sceAudioSRCOutputBlocking"},
|
||||
{0x8c1009b2, WrapU_UUU<sceAudioOutput>, "sceAudioOutput"},
|
||||
{0x927AC32B, 0, "sceAudioSetVolumeOffset"},
|
||||
|
||||
// The oldest and standard audio interface. Supports 8 channels, most games use 1-2.
|
||||
{0x8c1009b2, WrapU_UUU<sceAudioOutput>, "sceAudioOutput"},
|
||||
{0x136CAF51, WrapV_UUU<sceAudioOutputBlocking>, "sceAudioOutputBlocking"},
|
||||
{0xE2D56B2D, WrapU_UUUU<sceAudioOutputPanned>, "sceAudioOutputPanned"},
|
||||
{0x13F592BC, WrapV_UUUU<sceAudioOutputPannedBlocking>, "sceAudioOutputPannedBlocking"}, //(u32, u32, u32, void *)Output sound, blocking
|
||||
@ -367,8 +372,17 @@ const HLEFunction sceAudio[] =
|
||||
{0xCB2E439E, WrapU_UU<sceAudioSetChannelDataLen>, "sceAudioSetChannelDataLen"}, //(u32, u32)
|
||||
{0x95FD0C2D, WrapU_UU<sceAudioChangeChannelConfig>, "sceAudioChangeChannelConfig"},
|
||||
{0xB7E1D8E7, WrapU_UUU<sceAudioChangeChannelVolume>, "sceAudioChangeChannelVolume"},
|
||||
|
||||
// I guess these are like the others but do sample rate conversion?
|
||||
{0x38553111, 0, "sceAudioSRCChReserve"},
|
||||
{0x5C37C0AE, 0, "sceAudioSRCChRelease"},
|
||||
{0xE0727056, 0, "sceAudioSRCOutputBlocking"},
|
||||
|
||||
// Never seen these used
|
||||
{0x41efade7, 0, "sceAudioOneshotOutput"},
|
||||
{0xB61595C0, 0, "sceAudioLoopbackTest"},
|
||||
|
||||
// Microphone interface
|
||||
{0x7de61688, 0, "sceAudioInputInit"},
|
||||
{0xE926D3FB, 0, "sceAudioInputInitEx"},
|
||||
{0x6d4bec68, 0, "sceAudioInput"},
|
||||
|
@ -17,8 +17,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
//#include "base/timeutil.h"
|
||||
// TODO: Move the relevant parts into common. Don't want the core
|
||||
// to be dependent on "native", I think. Or maybe should get rid of common
|
||||
// and move everything into native...
|
||||
#include "base/timeutil.h"
|
||||
|
||||
#include "Thread.h"
|
||||
#include "../Core/CoreTiming.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../HLE/HLE.h"
|
||||
@ -63,6 +67,7 @@ static int hCountTotal = 0; //unused
|
||||
static int vCount = 0;
|
||||
static int isVblank = 0;
|
||||
static bool hasSetMode = false;
|
||||
double lastFrameTime = 0;
|
||||
|
||||
// STATE END
|
||||
|
||||
@ -165,15 +170,29 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
|
||||
// anything to draw here.
|
||||
gpu->CopyDisplayToOutput();
|
||||
|
||||
{
|
||||
host->EndFrame();
|
||||
host->EndFrame();
|
||||
|
||||
host->BeginFrame();
|
||||
gpu->BeginFrame();
|
||||
|
||||
shaderManager.DirtyShader();
|
||||
shaderManager.DirtyUniform(DIRTY_ALL);
|
||||
#ifdef _WIN32
|
||||
static double lastFrameTime = 0.0;
|
||||
// Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it.
|
||||
time_update();
|
||||
if (lastFrameTime == 0.0)
|
||||
lastFrameTime = time_now_d();
|
||||
if (!GetAsyncKeyState(VK_TAB)) {
|
||||
while (time_now_d() < lastFrameTime + 1.0 / 60.0f) {
|
||||
Common::SleepCurrentThread(1);
|
||||
time_update();
|
||||
}
|
||||
lastFrameTime = time_now_d();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
host->BeginFrame();
|
||||
gpu->BeginFrame();
|
||||
|
||||
shaderManager.DirtyShader();
|
||||
shaderManager.DirtyUniform(DIRTY_ALL);
|
||||
|
||||
// Tell the emu core that it's time to stop emulating
|
||||
// Win32 doesn't need this.
|
||||
|
@ -47,7 +47,12 @@ u32 sceWlanGetEtherAddr(u32 addrAddr)
|
||||
|
||||
u32 sceWlanDevIsPowerOn()
|
||||
{
|
||||
DEBUG_LOG(HLE, "0=sceWlanDevIsPowerOn()");
|
||||
DEBUG_LOG(HLE, "UNTESTED 0=sceWlanDevIsPowerOn()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceWlanGetSwitchState() {
|
||||
DEBUG_LOG(HLE, "UNTESTED sceWlanGetSwitchState()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -179,7 +184,7 @@ const HLEFunction sceNetApctl[] =
|
||||
|
||||
const HLEFunction sceWlanDrv[] =
|
||||
{
|
||||
{0xd7763699, 0, "sceWlanGetSwitchState"},
|
||||
{0xd7763699, WrapU_V<sceWlanGetSwitchState>, "sceWlanGetSwitchState"},
|
||||
{0x0c622081, WrapU_U<sceWlanGetEtherAddr>, "sceWlanGetEtherAddr"},
|
||||
{0x93440B11, WrapU_V<sceWlanDevIsPowerOn>, "sceWlanDevIsPowerOn"},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user