From 936a39f6245526926a4ca9184b0e0c8dac76e7a0 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Mon, 27 Apr 2020 21:12:30 +0300 Subject: [PATCH] Move the audio code to a different file --- Makefile | 3 +- SDL/audio/audio.h | 16 +++++++++ SDL/audio/sdl.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ SDL/main.c | 81 ++++++++----------------------------------- 4 files changed, 119 insertions(+), 68 deletions(-) create mode 100644 SDL/audio/audio.h create mode 100644 SDL/audio/sdl.c diff --git a/Makefile b/Makefile index 49e24b5..9df7eb8 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ endif VERSION := 0.12.3 export VERSION CONF ?= debug +SDL_AUDIO_DRIVER ?= sdl BIN := build/bin OBJ := build/obj @@ -172,7 +173,7 @@ all: cocoa sdl tester libretro # Get a list of our source files and their respective object file targets CORE_SOURCES := $(shell ls Core/*.c) -SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) +SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) SDL/audio/$(SDL_AUDIO_DRIVER).c TESTER_SOURCES := $(shell ls Tester/*.c) ifeq ($(PLATFORM),Darwin) diff --git a/SDL/audio/audio.h b/SDL/audio/audio.h new file mode 100644 index 0000000..acaa011 --- /dev/null +++ b/SDL/audio/audio.h @@ -0,0 +1,16 @@ +#ifndef sdl_audio_h +#define sdl_audio_h + +#include +#include +#include + +bool GB_audio_is_playing(void); +void GB_audio_set_paused(bool paused); +void GB_audio_clear_queue(void); +unsigned GB_audio_get_frequency(void); +size_t GB_audio_get_queue_length(void); +void GB_audio_queue_sample(GB_sample_t *sample); +void GB_audio_init(void); + +#endif /* sdl_audio_h */ diff --git a/SDL/audio/sdl.c b/SDL/audio/sdl.c new file mode 100644 index 0000000..1f8a529 --- /dev/null +++ b/SDL/audio/sdl.c @@ -0,0 +1,87 @@ +#include "audio.h" +#include + +#ifndef _WIN32 +#define AUDIO_FREQUENCY 96000 +#include +#else +#include +/* Windows (well, at least my VM) can't handle 96KHz sound well :( */ + +/* 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 + +/* Compatibility with older SDL versions */ +#ifndef SDL_AUDIO_ALLOW_SAMPLES_CHANGE +#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0 +#endif + +static SDL_AudioDeviceID device_id; +static SDL_AudioSpec want_aspec, have_aspec; + +bool GB_audio_is_playing(void) +{ + return SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; +} + +void GB_audio_set_paused(bool paused) +{ + GB_audio_clear_queue(); + SDL_PauseAudioDevice(device_id, paused); +} + +void GB_audio_clear_queue(void) +{ + SDL_ClearQueuedAudio(device_id); +} + +unsigned GB_audio_get_frequency(void) +{ + return have_aspec.freq; +} + +size_t GB_audio_get_queue_length(void) +{ + return SDL_GetQueuedAudioSize(device_id); +} + +void GB_audio_queue_sample(GB_sample_t *sample) +{ + SDL_QueueAudio(device_id, sample, sizeof(*sample)); +} + +void GB_audio_init(void) +{ + /* Configure Audio */ + memset(&want_aspec, 0, sizeof(want_aspec)); + want_aspec.freq = AUDIO_FREQUENCY; + want_aspec.format = AUDIO_S16SYS; + want_aspec.channels = 2; + want_aspec.samples = 512; + + SDL_version _sdl_version; + SDL_GetVersion(&_sdl_version); + unsigned sdl_version = _sdl_version.major * 1000 + _sdl_version.minor * 100 + _sdl_version.patch; + +#ifndef _WIN32 + /* SDL 2.0.5 on macOS and Linux introduced a bug where certain combinations of buffer lengths and frequencies + fail to produce audio correctly. */ + if (sdl_version >= 2005) { + want_aspec.samples = 2048; + } +#else + if (sdl_version < 2006) { + /* 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.*/ + want_aspec.freq = 44100; + } +#endif + + device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE); +} diff --git a/SDL/main.c b/SDL/main.c index e27c0f2..c4a4d0f 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -8,27 +8,12 @@ #include "utils.h" #include "gui.h" #include "shader.h" - +#include "audio/audio.h" #ifndef _WIN32 -#define AUDIO_FREQUENCY 96000 #include #else #include -/* Windows (well, at least my VM) can't handle 96KHz sound well :( */ - -/* 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 - -/* Compatibility with older SDL versions */ -#ifndef SDL_AUDIO_ALLOW_SAMPLES_CHANGE -#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0 #endif GB_gameboy_t gb; @@ -42,7 +27,6 @@ static char *filename = NULL; static typeof(free) *free_function = NULL; static char *battery_save_path_ptr; -SDL_AudioDeviceID device_id; void set_filename(const char *new_filename, typeof(free) *new_free_function) { @@ -53,8 +37,6 @@ void set_filename(const char *new_filename, typeof(free) *new_free_function) free_function = new_free_function; } -static SDL_AudioSpec want_aspec, have_aspec; - static char *captured_log = NULL; static void log_capture_callback(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes) @@ -127,16 +109,15 @@ static void screen_size_changed(void) static void open_menu(void) { - bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; + bool audio_playing = GB_audio_is_playing(); if (audio_playing) { - SDL_PauseAudioDevice(device_id, 1); + GB_audio_set_paused(true); } size_t previous_width = GB_get_screen_width(&gb); run_gui(true); SDL_ShowCursor(SDL_DISABLE); if (audio_playing) { - SDL_ClearQueuedAudio(device_id); - SDL_PauseAudioDevice(device_id, 0); + GB_audio_set_paused(false); } GB_set_color_correction_mode(&gb, configuration.color_correction_mode); GB_set_border_mode(&gb, configuration.border_mode); @@ -176,7 +157,7 @@ static void handle_events(GB_gameboy_t *gb) GB_set_key_state(gb, (GB_key_t) button, event.type == SDL_JOYBUTTONDOWN); } else if (button == JOYPAD_BUTTON_TURBO) { - SDL_ClearQueuedAudio(device_id); + GB_audio_clear_queue(); turbo_down = event.type == SDL_JOYBUTTONDOWN; GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); } @@ -294,14 +275,7 @@ static void handle_events(GB_gameboy_t *gb) break; } #endif - bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; - if (audio_playing) { - SDL_PauseAudioDevice(device_id, 1); - } - else if (!audio_playing) { - SDL_ClearQueuedAudio(device_id); - SDL_PauseAudioDevice(device_id, 0); - } + GB_audio_set_paused(GB_audio_is_playing()); } break; @@ -336,7 +310,7 @@ static void handle_events(GB_gameboy_t *gb) case SDL_KEYUP: // Fallthrough if (event.key.keysym.scancode == configuration.keys[8]) { turbo_down = event.type == SDL_KEYDOWN; - SDL_ClearQueuedAudio(device_id); + GB_audio_clear_queue(); GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); } else if (event.key.keysym.scancode == configuration.keys_2[0]) { @@ -409,15 +383,15 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) if (turbo_down) { static unsigned skip = 0; skip++; - if (skip == have_aspec.freq / 8) { + if (skip == GB_audio_get_frequency() / 8) { skip = 0; } - if (skip > have_aspec.freq / 16) { + if (skip > GB_audio_get_frequency() / 16) { return; } } - if (SDL_GetQueuedAudioSize(device_id) / sizeof(*sample) > have_aspec.freq / 4) { + if (GB_audio_get_queue_length() / sizeof(*sample) > GB_audio_get_frequency() / 4) { return; } @@ -426,7 +400,7 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) sample->right = sample->right * configuration.volume / 100; } - SDL_QueueAudio(device_id, sample, sizeof(*sample)); + GB_audio_queue_sample(sample); } @@ -514,7 +488,7 @@ restart: GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank); GB_set_pixels_output(&gb, active_pixel_buffer); GB_set_rgb_encode_callback(&gb, rgb_encode); - GB_set_sample_rate(&gb, have_aspec.freq); + GB_set_sample_rate(&gb, GB_audio_get_frequency()); GB_set_color_correction_mode(&gb, configuration.color_correction_mode); update_palette(); if ((unsigned)configuration.border_mode <= GB_BORDER_ALWAYS) { @@ -675,34 +649,7 @@ int main(int argc, char **argv) pixel_format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888); } - - /* Configure Audio */ - memset(&want_aspec, 0, sizeof(want_aspec)); - want_aspec.freq = AUDIO_FREQUENCY; - want_aspec.format = AUDIO_S16SYS; - want_aspec.channels = 2; - want_aspec.samples = 512; - - SDL_version _sdl_version; - SDL_GetVersion(&_sdl_version); - unsigned sdl_version = _sdl_version.major * 1000 + _sdl_version.minor * 100 + _sdl_version.patch; - -#ifndef _WIN32 - /* SDL 2.0.5 on macOS and Linux introduced a bug where certain combinations of buffer lengths and frequencies - fail to produce audio correctly. */ - if (sdl_version >= 2005) { - want_aspec.samples = 2048; - } -#else - if (sdl_version < 2006) { - /* 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.*/ - want_aspec.freq = 44100; - } -#endif - - device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE); - /* Start Audio */ + GB_audio_init(); SDL_EventState(SDL_DROPFILE, SDL_ENABLE); @@ -735,7 +682,7 @@ int main(int argc, char **argv) else { connect_joypad(); } - SDL_PauseAudioDevice(device_id, 0); + GB_audio_set_paused(false); run(); // Never returns return 0; }