SDL2: Update to SDL_OpenAudioDevice()

Instead of the legacy SDL_OpenAudio() method, we now use the newer
SDL_OpenAudioDevice() functions. This fixes audio in Windows if the SDL
version is 2.0.6 or higher.

It also allows us to use 48kHz audio for Windows (96kHz somewhat works
too, but since we don't get absolutely smooth audio with it, I'd stick
with 48kHz for now until we find a solution. 44.1Khz is available as
fallback for SDL 2.0.5 and lower. Yes, the 2.0.5 to 2.0.6 transition was
quite harsh in terms of Windows audio support...
This commit is contained in:
Lothar Serra Mari 2018-04-22 15:22:10 +02:00
parent be9df4d658
commit ca571c6fa5

View File

@ -10,8 +10,15 @@
#ifndef _WIN32 #ifndef _WIN32
#define AUDIO_FREQUENCY 96000 #define AUDIO_FREQUENCY 96000
#else #else
/* Windows (well, at least my VM) can't handle 96KHz sound well :( */ /* LIJI32 says: Windows (well, at least my VM) can't handle 96KHz sound well :(
#define AUDIO_FREQUENCY 44100
felsqualle says: For SDL 2.0.6+ using the WASAPI driver, the highest freq.
we can get is 48000. 96000 also works, but always has some faint crackling in
the audio, no matter how high or low I set the buffer length...
Not quite satisfied with that solution, because acc. to SDL2 docs,
96k + WASAPI *should* work. */
#define AUDIO_FREQUENCY 48000
#endif #endif
GB_gameboy_t gb; GB_gameboy_t gb;
@ -24,6 +31,8 @@ static char *filename = NULL;
static bool should_free_filename = false; static bool should_free_filename = false;
static char *battery_save_path_ptr; static char *battery_save_path_ptr;
SDL_AudioDeviceID deviceId;
void set_filename(const char *new_filename, bool new_should_free) void set_filename(const char *new_filename, bool new_should_free)
{ {
if (filename && should_free_filename) { if (filename && should_free_filename) {
@ -132,13 +141,13 @@ static void handle_events(GB_gameboy_t *gb)
} }
else { else {
bool audio_playing = SDL_GetAudioStatus() == SDL_AUDIO_PLAYING; bool audio_playing = SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PLAYING;
if (audio_playing) { if (audio_playing) {
SDL_PauseAudio(true); SDL_PauseAudioDevice(deviceId, 1);
} }
run_gui(true); run_gui(true);
if (audio_playing) { if (!audio_playing) {
SDL_PauseAudio(false); SDL_PauseAudioDevice(deviceId, 0);
} }
GB_set_color_correction_mode(gb, configuration.color_correction_mode); GB_set_color_correction_mode(gb, configuration.color_correction_mode);
GB_set_highpass_filter_mode(gb, configuration.highpass_mode); GB_set_highpass_filter_mode(gb, configuration.highpass_mode);
@ -160,13 +169,13 @@ static void handle_events(GB_gameboy_t *gb)
case SDL_KEYDOWN: case SDL_KEYDOWN:
switch (event.key.keysym.scancode) { switch (event.key.keysym.scancode) {
case SDL_SCANCODE_ESCAPE: { case SDL_SCANCODE_ESCAPE: {
bool audio_playing = SDL_GetAudioStatus() == SDL_AUDIO_PLAYING; bool audio_playing = SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PLAYING;
if (audio_playing) { if (audio_playing) {
SDL_PauseAudio(true); SDL_PauseAudioDevice(deviceId, 1);
} }
run_gui(true); run_gui(true);
if (audio_playing) { if (!audio_playing) {
SDL_PauseAudio(false); SDL_PauseAudioDevice(deviceId, 0);
} }
GB_set_color_correction_mode(gb, configuration.color_correction_mode); GB_set_color_correction_mode(gb, configuration.color_correction_mode);
GB_set_highpass_filter_mode(gb, configuration.highpass_mode); GB_set_highpass_filter_mode(gb, configuration.highpass_mode);
@ -199,9 +208,14 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
} }
#endif #endif
SDL_PauseAudio(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING? true : false); bool audio_playing = SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PLAYING;
if (audio_playing) {
SDL_PauseAudioDevice(deviceId, 1);
} }
break; else if (!audio_playing) {
SDL_PauseAudioDevice(deviceId, 0);
}
break;
default: default:
/* Save states */ /* Save states */
@ -218,6 +232,7 @@ static void handle_events(GB_gameboy_t *gb)
} }
} }
break; break;
}
} }
case SDL_KEYUP: // Fallthrough case SDL_KEYUP: // Fallthrough
if (event.key.keysym.scancode == configuration.keys[8]) { if (event.key.keysym.scancode == configuration.keys[8]) {
@ -233,9 +248,9 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
default: default:
break; break;
}
} }
} }
}
static void vblank(GB_gameboy_t *gb) static void vblank(GB_gameboy_t *gb)
{ {
@ -456,9 +471,24 @@ int main(int argc, char **argv)
#else #else
want_aspec.samples = 512; want_aspec.samples = 512;
#endif #endif
#if SDL_COMPILEDVERSION > 2006 && defined(_WIN32)
/* SDL 2.0.6 offers WASAPI support which allows for much lower audio buffer lengths which at least
theoretically reduces lagging. */
printf("SDL 2.0.6+ detected, reducing audio buffer to 32 samples\n");
want_aspec.samples = 32;
#endif
#if SDL_COMPILEDVERSION <= 2005 && defined(_WIN32)
/* Since WASAPI audio was introduced in SDL 2.0.6, we have to lower the audio frequency
to 44100 because otherwise we would get garbled audio output.*/
printf("Fallback: SDL 2.0.5 detected, lowering audio freqency to 44100\n");
want_aspec.freq = 44100;
#endif
want_aspec.callback = audio_callback; want_aspec.callback = audio_callback;
want_aspec.userdata = &gb; want_aspec.userdata = &gb;
SDL_OpenAudio(&want_aspec, &have_aspec); deviceId = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
/* Start Audio */ /* Start Audio */
@ -484,7 +514,7 @@ int main(int argc, char **argv)
if (filename == NULL) { if (filename == NULL) {
run_gui(false); run_gui(false);
} }
SDL_PauseAudio(false); SDL_PauseAudioDevice(deviceId, 0);
run(); // Never returns run(); // Never returns
return 0; return 0;
} }