mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-10 12:45:46 +00:00
Changed OpenAL latency setting to really reflect how much time it is.
Before these changes each value of latency were actually 5ms, with a minimum latency of ~10 ms. If it was set to 4 ms on the UI, the actual latency was 10 + 5 * 4 = 30 ms. Now 30 ms on the UI means 30 ms on the backend.
This commit is contained in:
parent
94ba78d717
commit
8fd1af6783
@ -138,7 +138,7 @@ void OpenALStream::Stop()
|
|||||||
// Clean up buffers and sources
|
// Clean up buffers and sources
|
||||||
palDeleteSources(1, &uiSource);
|
palDeleteSources(1, &uiSource);
|
||||||
uiSource = 0;
|
uiSource = 0;
|
||||||
palDeleteBuffers(numBuffers, uiBuffers);
|
palDeleteBuffers(OAL_BUFFERS, uiBuffers.data());
|
||||||
|
|
||||||
ALCcontext* pContext = palcGetCurrentContext();
|
ALCcontext* pContext = palcGetCurrentContext();
|
||||||
ALCdevice* pDevice = palcGetContextsDevice(pContext);
|
ALCdevice* pDevice = palcGetContextsDevice(pContext);
|
||||||
@ -230,16 +230,43 @@ void OpenALStream::SoundLoop()
|
|||||||
bool fixed32_capable = IsCreativeXFi();
|
bool fixed32_capable = IsCreativeXFi();
|
||||||
|
|
||||||
u32 ulFrequency = m_mixer->GetSampleRate();
|
u32 ulFrequency = m_mixer->GetSampleRate();
|
||||||
numBuffers = SConfig::GetInstance().iLatency + 2; // OpenAL requires a minimum of two buffers
|
|
||||||
|
|
||||||
memset(uiBuffers, 0, numBuffers * sizeof(ALuint));
|
u32 frames_per_buffer;
|
||||||
|
// Can't have zero samples per buffer
|
||||||
|
if (SConfig::GetInstance().iLatency > 0)
|
||||||
|
{
|
||||||
|
frames_per_buffer = ulFrequency / 1000 * SConfig::GetInstance().iLatency / OAL_BUFFERS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frames_per_buffer = ulFrequency / 1000 * 1 / OAL_BUFFERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frames_per_buffer > OAL_MAX_FRAMES)
|
||||||
|
{
|
||||||
|
frames_per_buffer = OAL_MAX_FRAMES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DPL2 needs a minimum number of samples to work (FWRDURATION)
|
||||||
|
if (use_surround && frames_per_buffer < 240)
|
||||||
|
{
|
||||||
|
frames_per_buffer = 240;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO_LOG(AUDIO, "Using %d buffers, each with %d audio frames for a total of %d.", OAL_BUFFERS,
|
||||||
|
frames_per_buffer, frames_per_buffer * OAL_BUFFERS);
|
||||||
|
|
||||||
|
// Should we make these larger just in case the mixer ever sends more samples
|
||||||
|
// than what we request?
|
||||||
|
realtimeBuffer.resize(frames_per_buffer * STEREO_CHANNELS);
|
||||||
|
sampleBuffer.resize(frames_per_buffer * STEREO_CHANNELS);
|
||||||
uiSource = 0;
|
uiSource = 0;
|
||||||
|
|
||||||
// Clear error state before querying or else we get false positives.
|
// Clear error state before querying or else we get false positives.
|
||||||
ALenum err = palGetError();
|
ALenum err = palGetError();
|
||||||
|
|
||||||
// Generate some AL Buffers for streaming
|
// Generate some AL Buffers for streaming
|
||||||
palGenBuffers(numBuffers, (ALuint*)uiBuffers);
|
palGenBuffers(OAL_BUFFERS, (ALuint*)uiBuffers.data());
|
||||||
err = CheckALError("generating buffers");
|
err = CheckALError("generating buffers");
|
||||||
|
|
||||||
// Generate a Source to playback the Buffers
|
// Generate a Source to playback the Buffers
|
||||||
@ -261,7 +288,7 @@ void OpenALStream::SoundLoop()
|
|||||||
// Block until we have a free buffer
|
// Block until we have a free buffer
|
||||||
int numBuffersProcessed;
|
int numBuffersProcessed;
|
||||||
palGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed);
|
palGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed);
|
||||||
if (numBuffers == numBuffersQueued && !numBuffersProcessed)
|
if (OAL_BUFFERS == numBuffersQueued && !numBuffersProcessed)
|
||||||
{
|
{
|
||||||
soundSyncEvent.Wait();
|
soundSyncEvent.Wait();
|
||||||
continue;
|
continue;
|
||||||
@ -270,21 +297,21 @@ void OpenALStream::SoundLoop()
|
|||||||
// Remove the Buffer from the Queue.
|
// Remove the Buffer from the Queue.
|
||||||
if (numBuffersProcessed)
|
if (numBuffersProcessed)
|
||||||
{
|
{
|
||||||
ALuint unqueuedBufferIds[OAL_MAX_BUFFERS];
|
ALuint unqueuedBufferIds[OAL_BUFFERS];
|
||||||
palSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds);
|
palSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds);
|
||||||
err = CheckALError("unqueuing buffers");
|
err = CheckALError("unqueuing buffers");
|
||||||
|
|
||||||
numBuffersQueued -= numBuffersProcessed;
|
numBuffersQueued -= numBuffersProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int numSamples = OAL_MAX_SAMPLES;
|
unsigned int numSamples = frames_per_buffer;
|
||||||
|
|
||||||
if (use_surround)
|
if (use_surround)
|
||||||
{
|
{
|
||||||
// DPL2 accepts 240 samples minimum (FWRDURATION)
|
// DPL2 accepts 240 samples minimum (FWRDURATION)
|
||||||
unsigned int minSamples = 240;
|
unsigned int minSamples = 240;
|
||||||
|
|
||||||
float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS];
|
float dpl2[OAL_MAX_FRAMES * SURROUND_CHANNELS];
|
||||||
numSamples = m_mixer->MixSurround(dpl2, numSamples);
|
numSamples = m_mixer->MixSurround(dpl2, numSamples);
|
||||||
|
|
||||||
if (numSamples < minSamples)
|
if (numSamples < minSamples)
|
||||||
@ -306,7 +333,7 @@ void OpenALStream::SoundLoop()
|
|||||||
}
|
}
|
||||||
else if (fixed32_capable)
|
else if (fixed32_capable)
|
||||||
{
|
{
|
||||||
int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
int surround_int32[OAL_MAX_FRAMES * SURROUND_CHANNELS];
|
||||||
|
|
||||||
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
@ -327,7 +354,7 @@ void OpenALStream::SoundLoop()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
short surround_short[OAL_MAX_FRAMES * SURROUND_CHANNELS];
|
||||||
|
|
||||||
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
@ -355,7 +382,7 @@ void OpenALStream::SoundLoop()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
numSamples = m_mixer->Mix(realtimeBuffer, numSamples);
|
numSamples = m_mixer->Mix(realtimeBuffer.data(), numSamples);
|
||||||
|
|
||||||
// Convert the samples from short to float
|
// Convert the samples from short to float
|
||||||
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
@ -366,7 +393,7 @@ void OpenALStream::SoundLoop()
|
|||||||
|
|
||||||
if (float32_capable)
|
if (float32_capable)
|
||||||
{
|
{
|
||||||
palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer,
|
palBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer.data(),
|
||||||
numSamples * FRAME_STEREO_FLOAT, ulFrequency);
|
numSamples * FRAME_STEREO_FLOAT, ulFrequency);
|
||||||
|
|
||||||
err = CheckALError("buffering float32 data");
|
err = CheckALError("buffering float32 data");
|
||||||
@ -378,7 +405,7 @@ void OpenALStream::SoundLoop()
|
|||||||
else if (fixed32_capable)
|
else if (fixed32_capable)
|
||||||
{
|
{
|
||||||
// Clamping is not necessary here, samples are always between (-1,1)
|
// Clamping is not necessary here, samples are always between (-1,1)
|
||||||
int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
int stereo_int32[OAL_MAX_FRAMES * STEREO_CHANNELS];
|
||||||
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31));
|
stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31));
|
||||||
|
|
||||||
@ -388,7 +415,7 @@ void OpenALStream::SoundLoop()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Convert the samples from float to short
|
// Convert the samples from float to short
|
||||||
short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
short stereo[OAL_MAX_FRAMES * STEREO_CHANNELS];
|
||||||
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15));
|
stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15));
|
||||||
|
|
||||||
@ -401,7 +428,7 @@ void OpenALStream::SoundLoop()
|
|||||||
err = CheckALError("queuing buffers");
|
err = CheckALError("queuing buffers");
|
||||||
|
|
||||||
numBuffersQueued++;
|
numBuffersQueued++;
|
||||||
nextBuffer = (nextBuffer + 1) % numBuffers;
|
nextBuffer = (nextBuffer + 1) % OAL_BUFFERS;
|
||||||
|
|
||||||
palGetSourcei(uiSource, AL_SOURCE_STATE, &iState);
|
palGetSourcei(uiSource, AL_SOURCE_STATE, &iState);
|
||||||
if (iState != AL_PLAYING)
|
if (iState != AL_PLAYING)
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
#include <OpenAL/include/alc.h>
|
#include <OpenAL/include/alc.h>
|
||||||
#include <OpenAL/include/alext.h>
|
#include <OpenAL/include/alext.h>
|
||||||
|
|
||||||
#define SFX_MAX_SOURCE 1
|
// OpenAL requires a minimum of two buffers, three or more recommended
|
||||||
#define OAL_MAX_BUFFERS 32
|
#define OAL_BUFFERS 3
|
||||||
#define OAL_MAX_SAMPLES 256
|
#define OAL_MAX_FRAMES 4096
|
||||||
#define STEREO_CHANNELS 2
|
#define STEREO_CHANNELS 2
|
||||||
#define SURROUND_CHANNELS 6 // number of channels in surround mode
|
#define SURROUND_CHANNELS 6 // number of channels in surround mode
|
||||||
#define SIZE_SHORT 2
|
#define SIZE_SHORT 2
|
||||||
@ -72,12 +72,11 @@ private:
|
|||||||
|
|
||||||
Common::Event soundSyncEvent;
|
Common::Event soundSyncEvent;
|
||||||
|
|
||||||
short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS];
|
std::vector<short> realtimeBuffer;
|
||||||
float sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
std::vector<float> sampleBuffer;
|
||||||
ALuint uiBuffers[OAL_MAX_BUFFERS];
|
std::array<ALuint, OAL_BUFFERS> uiBuffers;
|
||||||
ALuint uiSource;
|
ALuint uiSource;
|
||||||
ALfloat fVolume;
|
ALfloat fVolume;
|
||||||
|
|
||||||
u8 numBuffers;
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
};
|
};
|
||||||
|
@ -254,7 +254,7 @@ void SConfig::SaveCoreSettings(IniFile& ini)
|
|||||||
core->Set("SelectedLanguage", SelectedLanguage);
|
core->Set("SelectedLanguage", SelectedLanguage);
|
||||||
core->Set("OverrideGCLang", bOverrideGCLanguage);
|
core->Set("OverrideGCLang", bOverrideGCLanguage);
|
||||||
core->Set("DPL2Decoder", bDPL2Decoder);
|
core->Set("DPL2Decoder", bDPL2Decoder);
|
||||||
core->Set("Latency", iLatency);
|
core->Set("AudioLatency", iLatency);
|
||||||
core->Set("AudioStretch", m_audio_stretch);
|
core->Set("AudioStretch", m_audio_stretch);
|
||||||
core->Set("AudioStretchMaxLatency", m_audio_stretch_max_latency);
|
core->Set("AudioStretchMaxLatency", m_audio_stretch_max_latency);
|
||||||
core->Set("MemcardAPath", m_strMemoryCardA);
|
core->Set("MemcardAPath", m_strMemoryCardA);
|
||||||
@ -568,7 +568,7 @@ void SConfig::LoadCoreSettings(IniFile& ini)
|
|||||||
core->Get("SelectedLanguage", &SelectedLanguage, 0);
|
core->Get("SelectedLanguage", &SelectedLanguage, 0);
|
||||||
core->Get("OverrideGCLang", &bOverrideGCLanguage, false);
|
core->Get("OverrideGCLang", &bOverrideGCLanguage, false);
|
||||||
core->Get("DPL2Decoder", &bDPL2Decoder, false);
|
core->Get("DPL2Decoder", &bDPL2Decoder, false);
|
||||||
core->Get("Latency", &iLatency, 5);
|
core->Get("AudioLatency", &iLatency, 20);
|
||||||
core->Get("AudioStretch", &m_audio_stretch, false);
|
core->Get("AudioStretch", &m_audio_stretch, false);
|
||||||
core->Get("AudioStretchMaxLatency", &m_audio_stretch_max_latency, 80);
|
core->Get("AudioStretchMaxLatency", &m_audio_stretch_max_latency, 80);
|
||||||
core->Get("MemcardAPath", &m_strMemoryCardA);
|
core->Get("MemcardAPath", &m_strMemoryCardA);
|
||||||
@ -831,7 +831,7 @@ void SConfig::LoadDefaults()
|
|||||||
bOverrideGCLanguage = false;
|
bOverrideGCLanguage = false;
|
||||||
bWii = false;
|
bWii = false;
|
||||||
bDPL2Decoder = false;
|
bDPL2Decoder = false;
|
||||||
iLatency = 14;
|
iLatency = 20;
|
||||||
m_audio_stretch = false;
|
m_audio_stretch = false;
|
||||||
m_audio_stretch_max_latency = 80;
|
m_audio_stretch_max_latency = 80;
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ struct SConfig : NonCopyable
|
|||||||
bool bCopyWiiSaveNetplay = true;
|
bool bCopyWiiSaveNetplay = true;
|
||||||
|
|
||||||
bool bDPL2Decoder = false;
|
bool bDPL2Decoder = false;
|
||||||
int iLatency = 14;
|
int iLatency = 20;
|
||||||
bool m_audio_stretch = false;
|
bool m_audio_stretch = false;
|
||||||
int m_audio_stretch_max_latency = 80;
|
int m_audio_stretch_max_latency = 80;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ void AudioConfigPane::InitializeGUI()
|
|||||||
m_audio_backend_choice =
|
m_audio_backend_choice =
|
||||||
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_audio_backend_strings);
|
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_audio_backend_strings);
|
||||||
m_audio_latency_spinctrl =
|
m_audio_latency_spinctrl =
|
||||||
new wxSpinCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 30);
|
new wxSpinCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 200);
|
||||||
m_audio_latency_label = new wxStaticText(this, wxID_ANY, _("Latency:"));
|
m_audio_latency_label = new wxStaticText(this, wxID_ANY, _("Latency (ms):"));
|
||||||
|
|
||||||
m_stretch_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Audio Stretching"));
|
m_stretch_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Audio Stretching"));
|
||||||
m_stretch_label = new wxStaticText(this, wxID_ANY, _("Buffer Size:"));
|
m_stretch_label = new wxStaticText(this, wxID_ANY, _("Buffer Size:"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user