diff --git a/src/common/ConfigManager.cpp b/src/common/ConfigManager.cpp
index dafdb72..06752e4 100644
--- a/src/common/ConfigManager.cpp
+++ b/src/common/ConfigManager.cpp
@@ -220,6 +220,7 @@ int speedupToggle;
int sunBars;
int surfaceSizeX;
int surfaceSizeY;
+int synchronize = false;
int threadPriority;
int tripleBuffering;
int useBios = 0;
@@ -522,6 +523,7 @@ void LoadConfig()
soundFiltering = (float)ReadPref("gbaSoundFiltering", 50) / 100.0f;
soundInterpolation = ReadPref("gbaSoundInterpolation", 1);
soundRecordDir = ReadPrefString("soundRecordDir");
+ synchronize = ReadPref("synchronize", 1);
threadPriority = ReadPref("priority", 2);
throttle = ReadPref("throttle", 100);
tripleBuffering = ReadPref("tripleBuffering", 0);
@@ -1038,6 +1040,13 @@ int ReadOpts(int argc, char ** argv)
}
break;
+ case OPT_SYNCHRONIZE:
+ // --synchronize
+ if (optarg) {
+ synchronize = atoi(optarg);
+ }
+ break;
+
case OPT_VIDEO_OPTION:
// --video-option
if (optarg) {
diff --git a/src/common/ConfigManager.h b/src/common/ConfigManager.h
index e6a1008..034ceed 100644
--- a/src/common/ConfigManager.h
+++ b/src/common/ConfigManager.h
@@ -119,6 +119,7 @@ extern int speedupToggle;
extern int sunBars;
extern int surfaceSizeX;
extern int surfaceSizeY;
+extern int synchronize;
extern int threadPriority;
extern int tripleBuffering;
extern int useBios;
diff --git a/src/common/SoundSDL.cpp b/src/common/SoundSDL.cpp
index 9713d44..09c46a7 100644
--- a/src/common/SoundSDL.cpp
+++ b/src/common/SoundSDL.cpp
@@ -18,17 +18,15 @@
#include "SoundSDL.h"
#include "ConfigManager.h"
#include "../gba/Globals.h"
-#include "../gba/Sound.h"
extern int emulating;
-// Hold up to 32 ms of data in the ring buffer
-const float SoundSDL::_delay = 0.032f;
+// Hold up to 100 ms of data in the ring buffer
+const float SoundSDL::_delay = 0.1f;
SoundSDL::SoundSDL():
_rbuf(0),
_dev(-1),
- current_rate(0),
_initialized(false)
{
@@ -48,7 +46,7 @@ void SoundSDL::read(uint16_t * stream, int length)
/* since this is running in a different thread, speedup and
* throttle can change at any time; save the value so locks
* stay in sync */
- bool lock = (emulating && !speedup && throttle && !gba_joybus_active) ? true : false;
+ bool lock = (emulating && !speedup && synchronize && !gba_joybus_active) ? true : false;
if (lock)
SDL_SemWait (_semBufferFull);
@@ -77,7 +75,7 @@ void SoundSDL::write(uint16_t * finalWave, int length)
std::size_t avail;
while ((avail = _rbuf.avail() / 2) < samples)
{
- bool lock = (emulating && !speedup && throttle && !gba_joybus_active) ? true : false;
+ bool lock = (emulating && !speedup && synchronize && !gba_joybus_active) ? true : false;
_rbuf.write(finalWave, avail * 2);
@@ -89,12 +87,6 @@ void SoundSDL::write(uint16_t * finalWave, int length)
if (lock)
{
SDL_SemWait(_semBufferEmpty);
- if (throttle > 0 && throttle != current_rate)
- {
- SDL_CloseAudio();
- init(soundGetSampleRate() * throttle / 100);
- current_rate = throttle;
- }
}
else
{
@@ -131,13 +123,10 @@ bool SoundSDL::init(long sampleRate)
_rbuf.reset(_delay * sampleRate * 2);
- if (!_initialized)
- {
- _mutex = SDL_CreateMutex();
- _semBufferFull = SDL_CreateSemaphore (0);
- _semBufferEmpty = SDL_CreateSemaphore (1);
- _initialized = true;
- }
+ _mutex = SDL_CreateMutex();
+ _semBufferFull = SDL_CreateSemaphore (0);
+ _semBufferEmpty = SDL_CreateSemaphore (1);
+ _initialized = true;
return true;
}
@@ -165,8 +154,6 @@ SoundSDL::~SoundSDL()
SDL_CloseAudioDevice(_dev);
emulating = iSave;
-
- _initialized = false;
}
void SoundSDL::pause()
diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp
index c083678..5e31c1d 100644
--- a/src/wx/cmdevents.cpp
+++ b/src/wx/cmdevents.cpp
@@ -2625,6 +2625,12 @@ EVT_HANDLER(SkipIntro, "Skip BIOS initialization")
update_opts();
}
+EVT_HANDLER(SyncGameAudio, "Synchronize game to audio")
+{
+ GetMenuOptionInt("SyncGameAudio", synchronize, 1);
+ update_opts();
+}
+
EVT_HANDLER(BootRomEn, "Use the specified BIOS file for GBA")
{
GetMenuOptionInt("BootRomEn", useBiosFileGBA, 1);
diff --git a/src/wx/dsound.cpp b/src/wx/dsound.cpp
index 2ed26e2..062b1b2 100644
--- a/src/wx/dsound.cpp
+++ b/src/wx/dsound.cpp
@@ -233,7 +233,7 @@ void DirectSound::write(uint16_t* finalWave, int length)
LPVOID lpvPtr2;
DWORD dwBytes2 = 0;
- if (!speedup && throttle && !gba_joybus_active) {
+ if (!speedup && synchronize && !throttle && !gba_joybus_active) {
hr = dsbSecondary->GetStatus(&status);
if (status & DSBSTATUS_PLAYING) {
diff --git a/src/wx/openal.cpp b/src/wx/openal.cpp
index a3a08da..82e2f72 100644
--- a/src/wx/openal.cpp
+++ b/src/wx/openal.cpp
@@ -286,7 +286,7 @@ void OpenAL::write(uint16_t* finalWave, int length)
}
}
- if (!speedup && throttle && !gba_joybus_active) {
+ if (!speedup && synchronize && !throttle && !gba_joybus_active) {
// wait until at least one buffer has finished
while (nBuffersProcessed == 0) {
winlog(" waiting...\n");
diff --git a/src/wx/opts.cpp b/src/wx/opts.cpp
index 68198c4..f96cffe 100644
--- a/src/wx/opts.cpp
+++ b/src/wx/opts.cpp
@@ -246,6 +246,7 @@ opt_desc opts[] = {
INTOPT("preferences/skipBios", "SkipIntro", wxTRANSLATE("Skip BIOS initialization"), skipBios, 0, 1),
INTOPT("preferences/skipSaveGameCheats", "", wxTRANSLATE("Do not overwrite cheat list when loading state"), skipSaveGameCheats, 0, 1),
INTOPT("preferences/skipSaveGameBattery", "", wxTRANSLATE("Do not overwrite native (battery) save when loading state"), skipSaveGameBattery, 0, 1),
+ INTOPT ("preferences/synchronize", "SyncGameAudio", wxTRANSLATE("Synchronize game to audio"), synchronize, 0, 1),
INTOPT("preferences/throttle", "", wxTRANSLATE("Throttle game speed, even when accelerated (0-1000%, 0 = disabled)"), throttle, 0, 1000),
INTOPT("preferences/useBiosGB", "BootRomGB", wxTRANSLATE("Use the specified BIOS file for GB"), useBiosFileGB, 0, 1),
INTOPT("preferences/useBiosGBA", "BootRomEn", wxTRANSLATE("Use the specified BIOS file"), useBiosFileGBA, 0, 1),
diff --git a/src/wx/xrc/MainMenu.xrc b/src/wx/xrc/MainMenu.xrc
index 5313057..b778ab2 100644
--- a/src/wx/xrc/MainMenu.xrc
+++ b/src/wx/xrc/MainMenu.xrc
@@ -242,6 +242,10 @@
<label>_VSync</label>
<checkable>1</checkable>
</object>
+ <object class="wxMenuItem" name="SyncGameAudio">
+ <label>_Audio sync</label>
+ <checkable>1</checkable>
+ </object>
<object class="wxMenuItem" name="FrameSkipAuto">
<label>_Auto skip frames</label>
<checkable>1</checkable>