Added a latency setting to the audio settings.

Removed the Sample Rate setting.  It is now hardcoded to 48000hz (accurate audio timing).

Fixes issue 5672.
This commit is contained in:
skidau 2013-01-13 00:05:30 +11:00
parent 73140c7da7
commit 1c462a1eca
11 changed files with 57 additions and 39 deletions

View file

@ -42,7 +42,6 @@ void AudioCommonConfig::Load()
#else
file.Get("Config", "Backend", &sBackend, BACKEND_NULLSOUND);
#endif
file.Get("Config", "Frequency", &iFrequency, 48000);
file.Get("Config", "Volume", &m_Volume, 100);
}
@ -55,7 +54,6 @@ void AudioCommonConfig::SaveSettings()
file.Set("Config", "EnableJIT", m_EnableJIT);
file.Set("Config", "DumpAudio", m_DumpAudio);
file.Set("Config", "Backend", sBackend);
file.Set("Config", "Frequency", iFrequency);
file.Set("Config", "Volume", m_Volume);
file.Save(File::GetUserPath(F_DSPCONFIG_IDX));

View file

@ -37,7 +37,6 @@ struct AudioCommonConfig
bool m_DumpAudio;
int m_Volume;
std::string sBackend;
int iFrequency;
// Load from given file
void Load();

View file

@ -46,6 +46,11 @@ bool OpenALStream::Start()
pContext = alcCreateContext(pDevice, NULL);
if (pContext)
{
// Used to determine an appropriate period size (2x period = total buffer size)
//ALCint refresh;
//alcGetIntegerv(pDevice, ALC_REFRESH, 1, &refresh);
//period_size_in_millisec = 1000 / refresh;
alcMakeContextCurrent(pContext);
thread = std::thread(std::mem_fun(&OpenALStream::SoundLoop), this);
bReturn = true;
@ -90,7 +95,7 @@ void OpenALStream::Stop()
// Clean up buffers and sources
alDeleteSources(1, &uiSource);
uiSource = 0;
alDeleteBuffers(OAL_NUM_BUFFERS, uiBuffers);
alDeleteBuffers(numBuffers, uiBuffers);
ALCcontext *pContext = alcGetCurrentContext();
ALCdevice *pDevice = alcGetContextsDevice(pContext);
@ -133,19 +138,20 @@ void OpenALStream::SoundLoop()
Common::SetCurrentThreadName("Audio thread - openal");
u32 ulFrequency = m_mixer->GetSampleRate();
numBuffers = Core::g_CoreStartupParameter.iLatency + 2; // OpenAL requires a minimum of two buffers
memset(uiBuffers, 0, OAL_NUM_BUFFERS * sizeof(ALuint));
memset(uiBuffers, 0, numBuffers * sizeof(ALuint));
uiSource = 0;
// Generate some AL Buffers for streaming
alGenBuffers(OAL_NUM_BUFFERS, (ALuint *)uiBuffers);
alGenBuffers(numBuffers, (ALuint *)uiBuffers);
// Generate a Source to playback the Buffers
alGenSources(1, &uiSource);
// Short Silence
memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS);
memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * numBuffers);
memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4);
for (int i = 0; i < OAL_NUM_BUFFERS; i++)
for (int i = 0; i < numBuffers; i++)
{
#if !defined(__APPLE__)
if (Core::g_CoreStartupParameter.bDPL2Decoder)
@ -154,7 +160,7 @@ void OpenALStream::SoundLoop()
#endif
alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * 2 * 2, ulFrequency);
}
alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers);
alSourceQueueBuffers(uiSource, numBuffers, uiBuffers);
alSourcePlay(uiSource);
// Set the default sound volume as saved in the config file.
@ -166,7 +172,7 @@ void OpenALStream::SoundLoop()
ALint iBuffersFilled = 0;
ALint iBuffersProcessed = 0;
ALint iState = 0;
ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0};
ALuint uiBufferTemp[OAL_MAX_BUFFERS] = {0};
soundTouch.setChannels(2);
soundTouch.setSampleRate(ulFrequency);
@ -216,7 +222,7 @@ void OpenALStream::SoundLoop()
soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate)));
soundTouch.setTempo(rate);
}
unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS);
unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS);
if (nSamples > 0)
{
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
@ -236,14 +242,14 @@ void OpenALStream::SoundLoop()
if (surround_capable)
{
// Convert the samples from short to float for the dpl2 decoder
float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_NUM_BUFFERS];
float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS];
for (u32 i = 0; i < nSamples; ++i)
{
dest[i * 2 + 0] = (float)sampleBuffer[i * 2 + 0] / (1<<16);
dest[i * 2 + 1] = (float)sampleBuffer[i * 2 + 1] / (1<<16);
}
float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS];
float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
dpl2decode(dest, nSamples, dpl2);
alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency);
@ -273,7 +279,7 @@ void OpenALStream::SoundLoop()
}
iBuffersFilled++;
if (iBuffersFilled == OAL_NUM_BUFFERS)
if (iBuffersFilled == numBuffers)
{
alSourcePlay(uiSource);
ALenum err = alGetError();

View file

@ -44,8 +44,8 @@
// 16 bit Stereo
#define SFX_MAX_SOURCE 1
#define OAL_NUM_BUFFERS 16
#define OAL_MAX_SAMPLES 512
#define OAL_MAX_BUFFERS 32
#define OAL_MAX_SAMPLES 256
#define SURROUND_CHANNELS 6 // number of channels in surround mode
#define SIZE_FLOAT 4 // size of a float in bytes
#endif
@ -75,10 +75,12 @@ private:
Common::Event soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * 2];
soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_NUM_BUFFERS];
ALuint uiBuffers[OAL_NUM_BUFFERS];
soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
ALuint uiBuffers[OAL_MAX_BUFFERS];
ALuint uiSource;
ALfloat fVolume;
u8 numBuffers;
#else
public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}

View file

@ -228,6 +228,7 @@ void SConfig::SaveSettings()
ini.Set("Core", "EnableCheats", m_LocalCoreStartupParameter.bEnableCheats);
ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage);
ini.Set("Core", "DPL2Decoder", m_LocalCoreStartupParameter.bDPL2Decoder);
ini.Set("Core", "Latency", m_LocalCoreStartupParameter.iLatency);
ini.Set("Core", "MemcardA", m_strMemoryCardA);
ini.Set("Core", "MemcardB", m_strMemoryCardB);
ini.Set("Core", "SlotA", m_EXIDevice[0]);
@ -369,6 +370,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "EnableCheats", &m_LocalCoreStartupParameter.bEnableCheats, false);
ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0);
ini.Get("Core", "DPL2Decoder", &m_LocalCoreStartupParameter.bDPL2Decoder, true);
ini.Get("Core", "Latency", &m_LocalCoreStartupParameter.iLatency, 14);
ini.Get("Core", "MemcardA", &m_strMemoryCardA);
ini.Get("Core", "MemcardB", &m_strMemoryCardB);
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD);

View file

@ -49,7 +49,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bEnableCheats(false),
bMergeBlocks(false),
bRunCompareServer(false), bRunCompareClient(false),
bDPL2Decoder(true),
bDPL2Decoder(true), iLatency(14),
bMMU(false), bMMUBAT(false), iTLBHack(0), bVBeam(false),
bFastDiscSpeed(false),
SelectedLanguage(0), bWii(false), bDisableWiimoteSpeaker(false),
@ -86,6 +86,7 @@ void SCoreStartupParameter::LoadDefaults()
SelectedLanguage = 0;
bWii = false;
bDPL2Decoder = true;
iLatency = 14;
iPosX = 100;
iPosY = 100;

View file

@ -108,6 +108,7 @@ struct SCoreStartupParameter
bool bMergeBlocks;
bool bDPL2Decoder;
int iLatency;
bool bRunCompareServer;
bool bRunCompareClient;

View file

@ -251,7 +251,7 @@ void DSPHLE::InitMixer()
unsigned int AISampleRate, DACSampleRate;
AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate);
delete soundStream;
soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, ac_Config.iFrequency), m_hWnd);
soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000), m_hWnd);
if(!soundStream) PanicAlert("Error starting up sound stream");
// Mixer is initialized
m_InitMixer = true;

View file

@ -204,7 +204,7 @@ void DSPLLE::InitMixer()
unsigned int AISampleRate, DACSampleRate;
AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate);
delete soundStream;
soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, ac_Config.iFrequency), m_hWnd);
soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd);
if(!soundStream) PanicAlert("Error starting up sound stream");
// Mixer is initialized
m_InitMixer = true;

View file

@ -121,7 +121,7 @@ EVT_CHECKBOX(ID_DSPTHREAD, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_ENABLE_THROTTLE, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_DUMP_AUDIO, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_DPL2DECODER, CConfigMain::AudioSettingsChanged)
EVT_CHOICE(ID_FREQUENCY, CConfigMain::AudioSettingsChanged)
EVT_SLIDER(ID_LATENCY, CConfigMain::AudioSettingsChanged)
EVT_CHOICE(ID_BACKEND, CConfigMain::AudioSettingsChanged)
EVT_SLIDER(ID_VOLUME, CConfigMain::AudioSettingsChanged)
@ -218,6 +218,8 @@ void CConfigMain::UpdateGUI()
// Disable stuff on AudioPage
DSPEngine->Disable();
DSPThread->Disable();
DPL2Decoder->Disable();
LatencySlider->Disable();
// Disable stuff on GamecubePage
GCSystemLang->Disable();
@ -365,8 +367,9 @@ void CConfigMain::InitializeGUIValues()
DSPThread->SetValue(startup_params.bDSPThread);
DumpAudio->SetValue(ac_Config.m_DumpAudio ? true : false);
DPL2Decoder->SetValue(startup_params.bDPL2Decoder);
FrequencySelection->SetSelection(
FrequencySelection->FindString(wxString::Format(_("%d Hz"), ac_Config.iFrequency)));
LatencySlider->Enable(std::string(ac_Config.sBackend) == BACKEND_OPENAL);
LatencySlider->SetValue(startup_params.iLatency);
LatencyText->SetLabel(wxString::Format(wxT("%d"), startup_params.iLatency));
// add backends to the list
AddAudioBackends();
@ -511,7 +514,6 @@ void CConfigMain::InitializeGUITooltips()
// Audio tooltips
DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended)."));
FrequencySelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
// Gamecube - Devices
@ -527,6 +529,8 @@ void CConfigMain::InitializeGUITooltips()
#elif defined(_WIN32)
DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL backend only. May need to rename soft_oal.dll to OpenAL32.dll to make it work."));
#endif
LatencySlider->SetToolTip(_("Sets the latency (in ms). Higher values may reduce audio crackling. OpenAL backend only."));
}
void CConfigMain::CreateGUIControls()
@ -630,13 +634,14 @@ void CConfigMain::CreateGUIControls()
wxDefaultPosition, wxDefaultSize, 0);
BackendSelection = new wxChoice(AudioPage, ID_BACKEND, wxDefaultPosition,
wxDefaultSize, wxArrayBackends, 0, wxDefaultValidator, wxEmptyString);
FrequencySelection = new wxChoice(AudioPage, ID_FREQUENCY);
FrequencySelection->Append(wxString::Format(_("%d Hz"), 48000));
FrequencySelection->Append(wxString::Format(_("%d Hz"), 32000));
LatencySlider = new wxSlider(AudioPage, ID_LATENCY, 0, 0, 30,
wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
LatencyText = new wxStaticText(AudioPage, wxID_ANY, wxT(""),
wxDefaultPosition, wxDefaultSize, 0);
if (Core::GetState() != Core::CORE_UNINITIALIZED)
{
FrequencySelection->Disable();
LatencySlider->Disable();
BackendSelection->Disable();
DPL2Decoder->Disable();
}
@ -655,8 +660,9 @@ void CConfigMain::CreateGUIControls()
wxGridBagSizer *sBackend = new wxGridBagSizer();
sBackend->Add(TEXT_BOX(AudioPage, _("Audio Backend:")), wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sBackend->Add(BackendSelection, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5);
sBackend->Add(TEXT_BOX(AudioPage, _("Sample Rate:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sBackend->Add(FrequencySelection, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
sBackend->Add(TEXT_BOX(AudioPage, _("Latency:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sBackend->Add(LatencySlider, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
sBackend->Add(LatencyText, wxGBPosition(1, 2), wxDefaultSpan, wxALL, 5);
wxStaticBoxSizer *sbBackend = new wxStaticBoxSizer(wxHORIZONTAL, AudioPage, _("Backend Settings"));
sbBackend->Add(sBackend, 0, wxEXPAND);
@ -946,17 +952,19 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event)
case ID_BACKEND:
VolumeSlider->Enable(SupportsVolumeChanges(std::string(BackendSelection->GetStringSelection().mb_str())));
LatencySlider->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL);
DPL2Decoder->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL);
ac_Config.sBackend = BackendSelection->GetStringSelection().mb_str();
ac_Config.Update();
break;
case ID_LATENCY:
SConfig::GetInstance().m_LocalCoreStartupParameter.iLatency = LatencySlider->GetValue();
LatencyText->SetLabel(wxString::Format(wxT("%d"), LatencySlider->GetValue()));
break;
default:
ac_Config.m_DumpAudio = DumpAudio->GetValue();
long int frequency;
FrequencySelection->GetStringSelection().ToLong(&frequency);
ac_Config.iFrequency = frequency;
ac_Config.Update();
break;
}
}

View file

@ -80,7 +80,7 @@ private:
ID_ENABLE_THROTTLE,
ID_DUMP_AUDIO,
ID_DPL2DECODER,
ID_FREQUENCY,
ID_LATENCY,
ID_BACKEND,
ID_VOLUME,
@ -156,12 +156,13 @@ private:
wxBoxSizer* sAudioPage; // GC settings
wxRadioBox* DSPEngine;
wxSlider* VolumeSlider;
wxStaticText* VolumeText;
wxStaticText* VolumeText;
wxCheckBox* DumpAudio;
wxCheckBox* DPL2Decoder;
wxArrayString wxArrayBackends;
wxChoice* BackendSelection;
wxChoice* FrequencySelection;
wxSlider* LatencySlider;
wxStaticText* LatencyText;
// Interface
wxCheckBox* ConfirmStop;