mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-30 03:40:32 +00:00
Add an option for the lower latency audio mode we had in an #ifdef before
This commit is contained in:
parent
441a4e406b
commit
507050e966
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user