Add an option for the lower latency audio mode we had in an #ifdef before

This commit is contained in:
Henrik Rydgard 2013-08-24 02:16:10 +02:00
parent 441a4e406b
commit 507050e966
4 changed files with 34 additions and 25 deletions

View File

@ -151,7 +151,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
sound->Get("EnableAtrac3plus", &bEnableAtrac3plus, true); sound->Get("EnableAtrac3plus", &bEnableAtrac3plus, true);
sound->Get("VolumeBGM", &iBGMVolume, 7); sound->Get("VolumeBGM", &iBGMVolume, 7);
sound->Get("VolumeSFX", &iSFXVolume, 7); sound->Get("VolumeSFX", &iSFXVolume, 7);
sound->Get("LowLatency", &bLowLatencyAudio, false);
IniFile::Section *control = iniFile.GetOrCreateSection("Control"); IniFile::Section *control = iniFile.GetOrCreateSection("Control");
control->Get("ShowAnalogStick", &bShowAnalogStick, true); control->Get("ShowAnalogStick", &bShowAnalogStick, true);
#ifdef BLACKBERRY #ifdef BLACKBERRY
@ -295,6 +296,7 @@ void Config::Save() {
sound->Set("EnableAtrac3plus", bEnableAtrac3plus); sound->Set("EnableAtrac3plus", bEnableAtrac3plus);
sound->Set("VolumeBGM", iBGMVolume); sound->Set("VolumeBGM", iBGMVolume);
sound->Set("VolumeSFX", iSFXVolume); sound->Set("VolumeSFX", iSFXVolume);
sound->Set("LowLatency", bLowLatencyAudio);
IniFile::Section *control = iniFile.GetOrCreateSection("Control"); IniFile::Section *control = iniFile.GetOrCreateSection("Control");
control->Set("ShowAnalogStick", bShowAnalogStick); control->Set("ShowAnalogStick", bShowAnalogStick);

View File

@ -25,8 +25,7 @@
extern const char *PPSSPP_GIT_VERSION; extern const char *PPSSPP_GIT_VERSION;
struct Config struct Config {
{
public: public:
Config(); Config();
~Config(); ~Config();
@ -100,6 +99,7 @@ public:
// Sound // Sound
bool bEnableSound; bool bEnableSound;
bool bEnableAtrac3plus; bool bEnableAtrac3plus;
bool bLowLatencyAudio;
int iSFXVolume; int iSFXVolume;
int iBGMVolume; int iBGMVolume;

View File

@ -40,16 +40,13 @@ int mixFrequency = 44100;
const int hwSampleRate = 44100; const int hwSampleRate = 44100;
#ifdef LOW_LATENCY_AUDIO int hwBlockSize = 64;
const int hwBlockSize = 16; int hostAttemptBlockSize = 512;
const int hostAttemptBlockSize = 256;
#else
const int hwBlockSize = 64;
const int hostAttemptBlockSize = 512;
#endif
const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate); static int audioIntervalUs;
const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate); static int audioHostIntervalUs;
static s32 *mixBuffer;
// High and low watermarks, basically. For perfect emulation, the correct values are 0 and 1, respectively. // High and low watermarks, basically. For perfect emulation, the correct values are 0 and 1, respectively.
// TODO: Tweak // TODO: Tweak
@ -63,7 +60,7 @@ const int chanQueueMinSizeFactor = 1;
// TODO: Need to replace this with something lockless. Mutexes in the audio pipeline // TODO: Need to replace this with something lockless. Mutexes in the audio pipeline
// is bad mojo. // is bad mojo.
FixedSizeQueue<s16, hostAttemptBlockSize * 16> outAudioQueue; FixedSizeQueue<s16, 512 * 16> outAudioQueue;
static inline s16 clamp_s16(int i) { static inline s16 clamp_s16(int i) {
if (i > 32767) if (i > 32767)
@ -77,25 +74,33 @@ static inline s16 adjustvolume(s16 sample, int vol) {
return clamp_s16((sample * vol) >> 15); return clamp_s16((sample * vol) >> 15);
} }
void hleAudioUpdate(u64 userdata, int cyclesLate) void hleAudioUpdate(u64 userdata, int cyclesLate) {
{
__AudioUpdate(); __AudioUpdate();
CoreTiming::ScheduleEvent(usToCycles(audioIntervalUs) - cyclesLate, eventAudioUpdate, 0); CoreTiming::ScheduleEvent(usToCycles(audioIntervalUs) - cyclesLate, eventAudioUpdate, 0);
} }
void hleHostAudioUpdate(u64 userdata, int cyclesLate) void hleHostAudioUpdate(u64 userdata, int cyclesLate) {
{
// Not all hosts need this call to poke their audio system once in a while, but those that don't // Not all hosts need this call to poke their audio system once in a while, but those that don't
// can just ignore it. // can just ignore it.
host->UpdateSound(); host->UpdateSound();
CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0); CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0);
} }
void __AudioInit() void __AudioInit() {
{
mixFrequency = 44100; mixFrequency = 44100;
if (g_Config.bLowLatencyAudio) {
hwBlockSize = 16;
hostAttemptBlockSize = 256;
} else {
hwBlockSize = 64;
hostAttemptBlockSize = 512;
}
audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate);
audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate);
eventAudioUpdate = CoreTiming::RegisterEvent("AudioUpdate", &hleAudioUpdate); eventAudioUpdate = CoreTiming::RegisterEvent("AudioUpdate", &hleAudioUpdate);
eventHostAudioUpdate = CoreTiming::RegisterEvent("AudioUpdateHost", &hleHostAudioUpdate); eventHostAudioUpdate = CoreTiming::RegisterEvent("AudioUpdateHost", &hleHostAudioUpdate);
@ -103,6 +108,9 @@ void __AudioInit()
CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs), eventHostAudioUpdate, 0); CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs), eventHostAudioUpdate, 0);
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
chans[i].clear(); chans[i].clear();
mixBuffer = new s32[hwBlockSize * 2];
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
} }
void __AudioDoState(PointerWrap &p) void __AudioDoState(PointerWrap &p)
@ -132,14 +140,14 @@ void __AudioDoState(PointerWrap &p)
p.DoMarker("sceAudio"); p.DoMarker("sceAudio");
} }
void __AudioShutdown() void __AudioShutdown() {
{ delete [] mixBuffer;
mixBuffer = 0;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
chans[i].clear(); chans[i].clear();
} }
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
{
u32 ret = chan.sampleCount; u32 ret = chan.sampleCount;
if (chan.sampleAddress == 0) { if (chan.sampleAddress == 0) {
@ -281,7 +289,6 @@ void __AudioUpdate() {
// Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied // 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 // to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
// if the buffer somehow gets full. // if the buffer somehow gets full.
s32 mixBuffer[hwBlockSize * 2];
bool firstChannel = true; bool firstChannel = true;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) { for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
@ -340,7 +347,6 @@ void __AudioUpdate() {
} else { } else {
// This happens quite a lot. There's still something slightly off // This happens quite a lot. There's still something slightly off
// about the amount of audio we produce. // about the amount of audio we produce.
DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity());
} }
} }
} }

View File

@ -302,6 +302,7 @@ void GameSettingsScreen::CreateViews() {
audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound"))); audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound")));
audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, a->T("Enable Atrac3+"))); audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, a->T("Enable Atrac3+")));
audioSettings->Add(new CheckBox(&g_Config.bLowLatencyAudio, a->T("Low latency (may stutter)")));
// Control // Control
ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));