diff --git a/src/twn_audio.c b/src/twn_audio.c index 53d236a..61b20f1 100644 --- a/src/twn_audio.c +++ b/src/twn_audio.c @@ -247,6 +247,35 @@ void audio_play(const char *path, float volume, float panning) { + if (!ctx.audio_initialized) { + profile_start("audio initialization"); + + SDL_AudioSpec request, got; + SDL_zero(request); + + request.freq = AUDIO_FREQUENCY; + request.format = AUDIO_F32; + request.channels = 2; + #ifndef TWN_FEATURE_PUSH_AUDIO + request.callback = audio_callback; + #endif + /* TODO: check for errors */ + ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0); + ctx.audio_stream_format = got.format; + ctx.audio_stream_frequency = got.freq; + ctx.audio_stream_channel_count = got.channels; + /* TODO: relax this */ + SDL_assert_always(got.freq == AUDIO_FREQUENCY); + SDL_assert_always(got.format == AUDIO_F32); + SDL_assert_always(got.channels == 2); + + SDL_PauseAudioDevice(ctx.audio_device, 0); + + profile_end("audio initialization"); + + ctx.audio_initialized = true; + } + if (channel) { AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel); diff --git a/src/twn_engine_context_c.h b/src/twn_engine_context_c.h index ddb9003..35d77db 100644 --- a/src/twn_engine_context_c.h +++ b/src/twn_engine_context_c.h @@ -79,6 +79,7 @@ typedef struct EngineContext { bool render_double_buffered; /* signals mouse focus, used to disable mouse capture */ bool window_mouse_resident; + bool audio_initialized; } EngineContext; /* TODO: does it need to be marked with TWN_API? */ diff --git a/src/twn_loop.c b/src/twn_loop.c index aea787e..fbadaa9 100644 --- a/src/twn_loop.c +++ b/src/twn_loop.c @@ -218,9 +218,11 @@ static void main_loop(void) { /* TODO: make it works when ctx.ticks_per_second != 60 */ #ifdef TWN_FEATURE_PUSH_AUDIO static uint8_t audio_buffer[(AUDIO_FREQUENCY / 60) * sizeof (float) * 2]; - 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.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() */ @@ -537,38 +539,6 @@ static bool initialize(void) { /* add a watcher for immediate updates on window size */ SDL_AddEventWatch(event_callback, NULL); - /* audio initialization */ - { - - /* TODO: try to delay it until actually used? */ - /* quite a lot of programs might start with silence of resource loading of initial frame */ - profile_start("audio initialization"); - - SDL_AudioSpec request, got; - SDL_zero(request); - - request.freq = AUDIO_FREQUENCY; - request.format = AUDIO_F32; - request.channels = 2; - #ifndef TWN_FEATURE_PUSH_AUDIO - request.callback = audio_callback; - #endif - /* TODO: check for errors */ - ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0); - ctx.audio_stream_format = got.format; - ctx.audio_stream_frequency = got.freq; - ctx.audio_stream_channel_count = got.channels; - /* TODO: relax this */ - SDL_assert_always(got.freq == AUDIO_FREQUENCY); - SDL_assert_always(got.format == AUDIO_F32); - SDL_assert_always(got.channels == 2); - - SDL_PauseAudioDevice(ctx.audio_device, 0); - - profile_end("audio initialization"); - - } - /* random seeding */ /* SDL_GetPerformanceCounter returns some platform-dependent number. */ /* it should vary between game instances. i checked! random enough for me. */