diff --git a/CMakeLists.txt b/CMakeLists.txt index 478eeae..88d9cad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,6 @@ set(TWN_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") # feature configuration, set them with -DFEATURE=ON/OFF in cli option(TWN_FEATURE_DYNLIB_GAME "Enable dynamic library loading support" ON) -option(TWN_FEATURE_PUSH_AUDIO "Enable frame based audio push for easy realtime audio" ON) option(TWN_USE_AMALGAM "Enable use of twn_amalgam.c as a single compilation unit" ON) # todo: figure out how to compile for dynamic linking instead @@ -136,8 +135,6 @@ set_target_properties(${TWN_TARGET} PROPERTIES C_STANDARD_REQUIRED ON C_EXTENSIONS ON) # extensions are required by stb_ds.h -target_compile_definitions(${TWN_TARGET} PRIVATE $<$:TWN_FEATURE_PUSH_AUDIO>) - # precompile commonly used not-so-small headers target_precompile_headers(${TWN_TARGET} PRIVATE $<$>:third-party/glad/include/glad/glad.h> diff --git a/src/twn_audio.c b/src/twn_audio.c index af7e76a..50a8b6d 100644 --- a/src/twn_audio.c +++ b/src/twn_audio.c @@ -259,9 +259,8 @@ void audio_play(const char *path, request.format = AUDIO_F32; request.channels = 2; request.samples = 4096; - #ifndef TWN_FEATURE_PUSH_AUDIO - request.callback = audio_callback; - #endif + if (!ctx.push_audio_model) + request.callback = audio_callback; /* TODO: check for errors */ ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0); ctx.audio_stream_format = got.format; @@ -279,6 +278,8 @@ void audio_play(const char *path, ctx.audio_initialized = true; } + SDL_LockAudioDevice(ctx.audio_device); + if (channel) { AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel); @@ -331,6 +332,8 @@ void audio_play(const char *path, arrpush(ctx.unnamed_audio_channels, new_channel); } + + SDL_UnlockAudioDevice(ctx.audio_device); } diff --git a/src/twn_engine_context_c.h b/src/twn_engine_context_c.h index dac04b2..1d27fb7 100644 --- a/src/twn_engine_context_c.h +++ b/src/twn_engine_context_c.h @@ -83,6 +83,7 @@ typedef struct EngineContext { /* signals mouse focus, used to disable mouse capture */ bool window_mouse_resident; bool audio_initialized; + bool push_audio_model; bool cull_faces; } EngineContext; diff --git a/src/twn_loop.c b/src/twn_loop.c index 0c643db..86e5395 100644 --- a/src/twn_loop.c +++ b/src/twn_loop.c @@ -226,17 +226,18 @@ static void main_loop(void) { input_state_update_postframe(&ctx.input); /* TODO: make it works when ctx.ticks_per_second != 60 */ - #ifdef TWN_FEATURE_PUSH_AUDIO - uint64_t const queued_frames = SDL_GetQueuedAudioSize(ctx.audio_device) / sizeof (float) / 2; - if (queued_frames >= 4096 * 2) - SDL_ClearQueuedAudio(ctx.audio_device); - static uint8_t audio_buffer[(AUDIO_FREQUENCY / 60) * sizeof (float) * 2]; - if (ctx.audio_initialized) { - audio_callback(NULL, audio_buffer, sizeof audio_buffer); - if (SDL_QueueAudio(ctx.audio_device, audio_buffer, sizeof audio_buffer)) - CRY_SDL("Error queueing audio: "); + if (ctx.push_audio_model) { + uint64_t const queued_frames = SDL_GetQueuedAudioSize(ctx.audio_device) / sizeof (float) / 2; + /* note: this is here to reduce drift which sometimes appears */ + if (queued_frames >= 4096 * 2) + SDL_ClearQueuedAudio(ctx.audio_device); + static uint8_t audio_buffer[(AUDIO_FREQUENCY / 60) * sizeof (float) * 2]; + if (ctx.audio_initialized) { + audio_callback(NULL, audio_buffer, sizeof audio_buffer); + if (SDL_QueueAudio(ctx.audio_device, audio_buffer, sizeof audio_buffer)) + CRY_SDL("Error queueing audio: "); + } } - #endif /* TODO: ctx.game_copy = ctx.game should be placed after it, but it messes with state used in render() */ preserve_persistent_ctx_fields(); @@ -639,23 +640,24 @@ static bool initialize(void) { } else { ctx.cull_faces = datum_cull_faces.u.b; } - } - /* these are dynamic arrays and will be allocated lazily by stb_ds */ - ctx.render_queue_2d = NULL; - ctx.uncolored_mesh_batches = NULL; + toml_datum_t datum_audio_model = toml_string_in(engine, "audio_model"); + ctx.push_audio_model = datum_audio_model.ok ? SDL_strncmp(datum_audio_model.u.s, "push", sizeof "push" - 1) == 0 : false; + SDL_free(datum_audio_model.u.s); - /* input */ - toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots"); - if (!datum_keybind_slots.ok) { - ctx.keybind_slots = KEYBIND_SLOTS_DEFAULT; - } else { - if (datum_keybind_slots.u.i < 1) { + /* input */ + toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots"); + if (!datum_keybind_slots.ok) { ctx.keybind_slots = KEYBIND_SLOTS_DEFAULT; } else { - ctx.keybind_slots = datum_keybind_slots.u.i; + if (datum_keybind_slots.u.i < 1) { + ctx.keybind_slots = KEYBIND_SLOTS_DEFAULT; + } else { + ctx.keybind_slots = datum_keybind_slots.u.i; + } } } + input_state_init(&ctx.input); ctx.render_double_buffered = true;