[GTK3] Use the audio abstraction of the SDL UI
This commit is contained in:
parent
15d949e338
commit
8780aafe99
10
Makefile
10
Makefile
@ -120,7 +120,13 @@ ifneq ($(findstring gtk3,$(MAKECMDGOALS)),)
|
|||||||
$(error The gtk3 target requires pkg-config)
|
$(error The gtk3 target requires pkg-config)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy sdl2) -DGTK_DISABLE_DEPRECATED=1 -DG_DISABLE_DEPRECATED=1 -DG_LOG_DOMAIN=\"SameBoy\" -DRESOURCE_PREFIX=\"/io/github/sameboy/\" -DAPP_ID=\"io.github.sameboy\"
|
GTK_OPTIONS := -DGTK_DISABLE_DEPRECATED=1 -DG_DISABLE_DEPRECATED=1 -DG_LOG_DOMAIN=\"SameBoy\" -DRESOURCE_PREFIX=\"/io/github/sameboy/\" -DAPP_ID=\"io.github.sameboy\"
|
||||||
|
|
||||||
|
ifeq ($(SDL_AUDIO_DRIVER),sdl)
|
||||||
|
GTK_OPTIONS += -DUSE_SDL_AUDIO
|
||||||
|
endif
|
||||||
|
|
||||||
|
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy sdl2) $(GTK_OPTIONS)
|
||||||
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy sdl2)
|
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy sdl2)
|
||||||
|
|
||||||
# TODO: REMOVE DISABLE UNUSED WARNINGS
|
# TODO: REMOVE DISABLE UNUSED WARNINGS
|
||||||
@ -198,7 +204,7 @@ all: cocoa sdl tester libretro
|
|||||||
|
|
||||||
CORE_SOURCES := $(shell ls Core/*.c)
|
CORE_SOURCES := $(shell ls Core/*.c)
|
||||||
SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) SDL/audio/$(SDL_AUDIO_DRIVER).c
|
SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) SDL/audio/$(SDL_AUDIO_DRIVER).c
|
||||||
GTK3_SOURCES := $(shell ls gtk3/*.c) gtk3/sameboy-gtk3-resources.c
|
GTK3_SOURCES := $(shell ls gtk3/*.c) gtk3/sameboy-gtk3-resources.c SDL/audio/$(SDL_AUDIO_DRIVER).c
|
||||||
TESTER_SOURCES := $(shell ls Tester/*.c)
|
TESTER_SOURCES := $(shell ls Tester/*.c)
|
||||||
|
|
||||||
ifeq ($(PLATFORM),Darwin)
|
ifeq ($(PLATFORM),Darwin)
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <Core/gb.h>
|
#include <Core/gb.h>
|
||||||
|
|
||||||
|
unsigned GB_audio_default_sample_rate(void);
|
||||||
bool GB_audio_is_playing(void);
|
bool GB_audio_is_playing(void);
|
||||||
void GB_audio_set_paused(bool paused);
|
void GB_audio_set_paused(bool paused);
|
||||||
void GB_audio_clear_queue(void);
|
void GB_audio_clear_queue(void);
|
||||||
unsigned GB_audio_get_frequency(void);
|
unsigned GB_audio_get_sample_rate(void);
|
||||||
size_t GB_audio_get_queue_length(void);
|
size_t GB_audio_get_queue_length(void);
|
||||||
void GB_audio_queue_sample(GB_sample_t *sample);
|
void GB_audio_queue_sample(GB_sample_t *sample);
|
||||||
void GB_audio_init(void);
|
void GB_audio_init(unsigned sample_rate);
|
||||||
|
void GB_audio_destroy(void);
|
||||||
|
|
||||||
#endif /* sdl_audio_h */
|
#endif /* sdl_audio_h */
|
||||||
|
@ -29,6 +29,11 @@ static SDL_AudioSpec want_aspec, have_aspec;
|
|||||||
static unsigned buffer_pos = 0;
|
static unsigned buffer_pos = 0;
|
||||||
static GB_sample_t audio_buffer[AUDIO_BUFFER_SIZE];
|
static GB_sample_t audio_buffer[AUDIO_BUFFER_SIZE];
|
||||||
|
|
||||||
|
unsigned GB_audio_default_sample_rate(void)
|
||||||
|
{
|
||||||
|
return AUDIO_FREQUENCY;
|
||||||
|
}
|
||||||
|
|
||||||
bool GB_audio_is_playing(void)
|
bool GB_audio_is_playing(void)
|
||||||
{
|
{
|
||||||
return SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING;
|
return SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING;
|
||||||
@ -45,7 +50,7 @@ void GB_audio_clear_queue(void)
|
|||||||
SDL_ClearQueuedAudio(device_id);
|
SDL_ClearQueuedAudio(device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GB_audio_get_frequency(void)
|
unsigned GB_audio_get_sample_rate(void)
|
||||||
{
|
{
|
||||||
return have_aspec.freq;
|
return have_aspec.freq;
|
||||||
}
|
}
|
||||||
@ -65,11 +70,11 @@ void GB_audio_queue_sample(GB_sample_t *sample)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GB_audio_init(void)
|
void GB_audio_init(unsigned sample_rate)
|
||||||
{
|
{
|
||||||
/* Configure Audio */
|
/* Configure Audio */
|
||||||
memset(&want_aspec, 0, sizeof(want_aspec));
|
memset(&want_aspec, 0, sizeof(want_aspec));
|
||||||
want_aspec.freq = AUDIO_FREQUENCY;
|
want_aspec.freq = sample_rate == 0 ? GB_audio_default_sample_rate() : sample_rate;
|
||||||
want_aspec.format = AUDIO_S16SYS;
|
want_aspec.format = AUDIO_S16SYS;
|
||||||
want_aspec.channels = 2;
|
want_aspec.channels = 2;
|
||||||
want_aspec.samples = 512;
|
want_aspec.samples = 512;
|
||||||
@ -94,3 +99,9 @@ void GB_audio_init(void)
|
|||||||
|
|
||||||
device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
|
device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GB_audio_destroy() {
|
||||||
|
GB_audio_set_paused(true);
|
||||||
|
|
||||||
|
SDL_CloseAudioDevice(device_id);
|
||||||
|
}
|
||||||
|
10
SDL/main.c
10
SDL/main.c
@ -383,15 +383,15 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample)
|
|||||||
if (turbo_down) {
|
if (turbo_down) {
|
||||||
static unsigned skip = 0;
|
static unsigned skip = 0;
|
||||||
skip++;
|
skip++;
|
||||||
if (skip == GB_audio_get_frequency() / 8) {
|
if (skip == GB_audio_get_sample_rate() / 8) {
|
||||||
skip = 0;
|
skip = 0;
|
||||||
}
|
}
|
||||||
if (skip > GB_audio_get_frequency() / 16) {
|
if (skip > GB_audio_get_sample_rate() / 16) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GB_audio_get_queue_length() / sizeof(*sample) > GB_audio_get_frequency() / 4) {
|
if (GB_audio_get_queue_length() / sizeof(*sample) > GB_audio_get_sample_rate() / 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +488,7 @@ restart:
|
|||||||
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
|
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
|
||||||
GB_set_pixels_output(&gb, active_pixel_buffer);
|
GB_set_pixels_output(&gb, active_pixel_buffer);
|
||||||
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
||||||
GB_set_sample_rate(&gb, GB_audio_get_frequency());
|
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
|
||||||
GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
|
GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
|
||||||
update_palette();
|
update_palette();
|
||||||
if ((unsigned)configuration.border_mode <= GB_BORDER_ALWAYS) {
|
if ((unsigned)configuration.border_mode <= GB_BORDER_ALWAYS) {
|
||||||
@ -649,7 +649,7 @@ int main(int argc, char **argv)
|
|||||||
pixel_format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
|
pixel_format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_audio_init();
|
GB_audio_init(GB_audio_default_sample_rate());
|
||||||
|
|
||||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||||
|
|
||||||
|
102
gtk3/main.c
102
gtk3/main.c
@ -1,27 +1,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "../SDL/audio/audio.h"
|
||||||
#ifndef _WIN32
|
|
||||||
#define DEFAULT_AUDIO_SAMPLE_RATE 96000
|
|
||||||
#else
|
|
||||||
/* 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 DEFAULT_AUDIO_SAMPLE_RATE 48000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Compatibility with older SDL versions */
|
|
||||||
#ifndef SDL_AUDIO_ALLOW_SAMPLES_CHANGE
|
|
||||||
#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static SDL_GameController *controller = NULL;
|
static SDL_GameController *controller = NULL;
|
||||||
static SDL_AudioSpec want_aspec, have_aspec;
|
|
||||||
static SDL_AudioDeviceID device_id;
|
|
||||||
|
|
||||||
static const GThread *main_thread;
|
static const GThread *main_thread;
|
||||||
|
|
||||||
@ -324,49 +304,28 @@ static gboolean init_controllers() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool audio_initialized = false;
|
||||||
static gboolean init_audio() {
|
static gboolean init_audio() {
|
||||||
bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING;
|
bool audio_playing = GB_audio_is_playing();
|
||||||
SDL_PauseAudioDevice(device_id, 1);
|
|
||||||
SDL_ClearQueuedAudio(device_id);
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
|
||||||
|
|
||||||
|
if (audio_initialized) {
|
||||||
|
GB_audio_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SDL_AUDIO
|
||||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||||
g_warning("Failed to initialize audio: %s", SDL_GetError());
|
g_warning("Failed to initialize audio: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&want_aspec, 0, sizeof(want_aspec));
|
|
||||||
want_aspec.freq = gui_data.sample_rate;
|
|
||||||
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
|
#endif
|
||||||
|
|
||||||
device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
|
GB_audio_init(gui_data.sample_rate);
|
||||||
|
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
|
||||||
|
|
||||||
|
// restore playing state
|
||||||
|
GB_audio_set_paused(!audio_playing);
|
||||||
|
|
||||||
g_debug("Requested Sample Rate: %d Hz\nUsed Sample Rate: %d Hz", want_aspec.freq, have_aspec.freq);
|
return audio_initialized = true;
|
||||||
|
|
||||||
SDL_PauseAudioDevice(device_id, audio_playing? 0 : 1);
|
|
||||||
GB_set_sample_rate(&gb, have_aspec.freq);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GB_model_t get_model() {
|
static GB_model_t get_model() {
|
||||||
@ -395,19 +354,21 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) {
|
|||||||
if (turbo_down) {
|
if (turbo_down) {
|
||||||
static unsigned skip = 0;
|
static unsigned skip = 0;
|
||||||
skip++;
|
skip++;
|
||||||
if (skip == have_aspec.freq / 8) {
|
|
||||||
|
if (skip == GB_audio_get_sample_rate() / 8) {
|
||||||
skip = 0;
|
skip = 0;
|
||||||
}
|
}
|
||||||
if (skip > have_aspec.freq / 16) {
|
|
||||||
|
if (skip > GB_audio_get_sample_rate() / 16) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_GetQueuedAudioSize(device_id) / sizeof(*sample) > have_aspec.freq / 4) {
|
if (GB_audio_get_queue_length() / sizeof(*sample) > GB_audio_get_sample_rate() / 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_QueueAudio(device_id, sample, sizeof(*sample));
|
GB_audio_queue_sample(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Console TODO:
|
// Console TODO:
|
||||||
@ -826,7 +787,7 @@ static void startup(GApplication *app, gpointer gui_data_gptr) {
|
|||||||
printer = GTK_WINDOW(get_object("printer"));
|
printer = GTK_WINDOW(get_object("printer"));
|
||||||
|
|
||||||
if (config.sample_rate == -1) {
|
if (config.sample_rate == -1) {
|
||||||
gui_data->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
|
gui_data->sample_rate = GB_audio_default_sample_rate();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gui_data->sample_rate = config.sample_rate;
|
gui_data->sample_rate = config.sample_rate;
|
||||||
@ -1058,7 +1019,7 @@ static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
|
|||||||
|
|
||||||
case GDK_KEY_space: {
|
case GDK_KEY_space: {
|
||||||
turbo_down = event->type == GDK_KEY_PRESS;
|
turbo_down = event->type == GDK_KEY_PRESS;
|
||||||
SDL_ClearQueuedAudio(device_id);
|
GB_audio_clear_queue();
|
||||||
GB_set_turbo_mode(&gb, turbo_down, turbo_down && rewind_down);
|
GB_set_turbo_mode(&gb, turbo_down, turbo_down && rewind_down);
|
||||||
break; }
|
break; }
|
||||||
|
|
||||||
@ -1259,14 +1220,7 @@ static void on_model_changed(GSimpleAction *action, GVariant *value, gpointer us
|
|||||||
static void on_mute_changed(GSimpleAction *action, GVariant *value, gpointer user_data) {
|
static void on_mute_changed(GSimpleAction *action, GVariant *value, gpointer user_data) {
|
||||||
gboolean do_mute = g_variant_get_boolean(value);
|
gboolean do_mute = g_variant_get_boolean(value);
|
||||||
|
|
||||||
if (do_mute) {
|
GB_audio_set_paused(do_mute);
|
||||||
SDL_PauseAudioDevice(device_id, 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SDL_ClearQueuedAudio(device_id);
|
|
||||||
SDL_PauseAudioDevice(device_id, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_simple_action_set_state(action, value);
|
g_simple_action_set_state(action, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1705,7 +1659,7 @@ G_MODULE_EXPORT void on_sample_rate_changed(GtkWidget *w, gpointer user_data_gpt
|
|||||||
config.sample_rate = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
|
config.sample_rate = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
|
||||||
|
|
||||||
if (config.sample_rate == -1) {
|
if (config.sample_rate == -1) {
|
||||||
gui_data.sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
|
gui_data.sample_rate = GB_audio_default_sample_rate();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gui_data.sample_rate = config.sample_rate;
|
gui_data.sample_rate = config.sample_rate;
|
||||||
@ -2198,7 +2152,7 @@ static void init(GuiData *gui_data) {
|
|||||||
GB_set_vblank_callback(&gb, vblank);
|
GB_set_vblank_callback(&gb, vblank);
|
||||||
GB_set_pixels_output(&gb, get_current_buffer());
|
GB_set_pixels_output(&gb, get_current_buffer());
|
||||||
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
GB_set_rgb_encode_callback(&gb, rgb_encode);
|
||||||
GB_set_sample_rate(&gb, gui_data->sample_rate);
|
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
|
||||||
GB_set_color_correction_mode(&gb, get_color_correction_mode());
|
GB_set_color_correction_mode(&gb, get_color_correction_mode());
|
||||||
GB_set_highpass_filter_mode(&gb, get_highpass_mode());
|
GB_set_highpass_filter_mode(&gb, get_highpass_mode());
|
||||||
GB_set_rewind_length(&gb, config.rewind_duration);
|
GB_set_rewind_length(&gb, config.rewind_duration);
|
||||||
@ -2280,7 +2234,7 @@ static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type) {
|
|||||||
static void stop(GuiData *gui_data) {
|
static void stop(GuiData *gui_data) {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
|
|
||||||
SDL_PauseAudioDevice(device_id, 1);
|
GB_audio_set_paused(true);
|
||||||
GB_debugger_set_disabled(&gb, true);
|
GB_debugger_set_disabled(&gb, true);
|
||||||
|
|
||||||
if (GB_debugger_is_stopped(&gb)) {
|
if (GB_debugger_is_stopped(&gb)) {
|
||||||
@ -2341,8 +2295,8 @@ static void start(GuiData *gui_data) {
|
|||||||
running = true;
|
running = true;
|
||||||
gui_data->stopped = false;
|
gui_data->stopped = false;
|
||||||
|
|
||||||
SDL_ClearQueuedAudio(device_id);
|
GB_audio_clear_queue();
|
||||||
SDL_PauseAudioDevice(device_id, 0);
|
GB_audio_set_paused(false);
|
||||||
|
|
||||||
/* Run emulation */
|
/* Run emulation */
|
||||||
while (running) {
|
while (running) {
|
||||||
|
Loading…
Reference in New Issue
Block a user