From c07aa3c9a8a45f6d9159426dd297774daeaa36a2 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Mon, 8 Jul 2024 18:00:38 +0300 Subject: [PATCH] implement repeat in libxm --- src/audio.c | 45 +++++++++++++++++++++++++++------------- src/game/scenes/ingame.c | 5 +++-- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/audio.c b/src/audio.c index 8868697..b85e1ce 100644 --- a/src/audio.c +++ b/src/audio.c @@ -130,6 +130,8 @@ static union audio_context init_audio_context(const char *path, t_audio_file_typ break; } + xm_set_max_loop_count(handle, 1); + return (union audio_context) { .xm = { .handle = handle } }; @@ -250,19 +252,21 @@ static void audio_sample_and_mixin_channel(const struct audio_channel *channel, /* handle end of file */ if (samples_per_channel == 0) { - if (channel->args.repeat) + if (channel->args.repeat) { /* seek to start and try sampling some more */ stb_vorbis_seek_start(channel->context.vorbis.handle); - else + continue; + } else /* leave silence */ break; } /* panning and mixing */ - audio_mixin_streams(channel, &stream[i * sizeof(int16_t)], buffer, - samples_per_channel * ctx.audio_stream_channel_count); + audio_mixin_streams(channel, + &stream[i * sizeof(int16_t)], buffer, + samples_per_channel * 2); - i += samples_per_channel * ctx.audio_stream_channel_count; + i += samples_per_channel * 2; } break; @@ -273,19 +277,32 @@ static void audio_sample_and_mixin_channel(const struct audio_channel *channel, const int n_frames = (stream_frames - i) > float_buffer_frames ? float_buffer_frames : stream_frames - i; - /* TODO: make it report generated frame count and stop right before looping */ - xm_generate_samples(channel->context.xm.handle, (float *)buffer, n_frames / 2); + const int samples_per_channel = xm_generate_samples(channel->context.xm.handle, + (float *)buffer, + n_frames / 2); - /* convert floats to int16_t */ - for (int p = 0; p < n_frames; ++p) { - const int16_t value = (int16_t)(((float *)buffer)[p] * 32768.0f); - ((int16_t *)buffer)[p] = value; + /* handle end of file */ + if (samples_per_channel == 0) { + if (channel->args.repeat) { + /* seek to start and try sampling some more */ + xm_restart(channel->context.xm.handle); + continue; + } else + /* leave silence */ + break; } - /* panning and mixing */ - audio_mixin_streams(channel, &stream[i * sizeof(int16_t)], buffer, n_frames); + /* convert floats to int16_t */ + for (int p = 0; p < samples_per_channel * 2; ++p) + ((int16_t *)buffer)[p] = (int16_t)(((float *)buffer)[p] * 32768.0f); - i += n_frames; + /* panning and mixing */ + audio_mixin_streams(channel, + &stream[i * sizeof(int16_t)], + buffer, + samples_per_channel * 2); + + i += samples_per_channel * 2; } break; diff --git a/src/game/scenes/ingame.c b/src/game/scenes/ingame.c index 749f3a3..00cb944 100644 --- a/src/game/scenes/ingame.c +++ b/src/game/scenes/ingame.c @@ -30,9 +30,10 @@ struct scene *ingame_scene(struct state *state) { new_scene->world = world_create(); new_scene->player = player_create(new_scene->world); - play_audio_ex("music/test.ogg", "soundtrack", (t_play_audio_args){ + play_audio_ex("music/repeat-test.xm", "soundtrack", (t_play_audio_args){ .volume = 0.8f, - .panning = -0.5f + .panning = -0.5f, + .repeat = true, }); return (struct scene *)new_scene;