implement repeat in libxm

This commit is contained in:
veclavtalica 2024-07-08 18:00:38 +03:00
parent c539473021
commit c07aa3c9a8
2 changed files with 34 additions and 16 deletions

View File

@ -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;

View File

@ -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;