From 52b99333c5e8cf3b757cd6e88fca13d420b54979 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 23 Feb 2022 00:21:38 -0500 Subject: Implement xas_bank_player type Changes: * Implement xas_bank_player type to decouple player state from sample storage, to allow multiple concurrent players against a single sample bank * Refactor examples/say.c to use xas_bank_player --- examples/say.c | 27 ++++++++----- include/xas/bank.h | 34 ++++++++++------ src/bank.c | 111 +++++++++++++++++++++++++++++++++++------------------ 3 files changed, 115 insertions(+), 57 deletions(-) diff --git a/examples/say.c b/examples/say.c index e0aea9a..8741a10 100644 --- a/examples/say.c +++ b/examples/say.c @@ -75,8 +75,10 @@ int main(int argc, char **argv) { xas_bank *bank; xas_vox *vox; + xas_bank_player *player; + xas_audio_stream *voice, - *bank_stream, + *player_stream, *synth_l, *synth_r, *output; @@ -105,6 +107,10 @@ int main(int argc, char **argv) { goto error_bank_new; } + if ((player = xas_bank_player_new(bank)) == NULL) { + goto error_bank_player_new; + } + if ((output = xas_riff_new_file(argv[1], format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { @@ -115,8 +121,8 @@ int main(int argc, char **argv) { goto error_vox_stream_new; } - if ((bank_stream = xas_bank_stream_new(bank)) == NULL) { - goto error_bank_stream_new; + if ((player_stream = xas_bank_player_stream_new(player)) == NULL) { + goto error_bank_player_stream_new; } if ((synth_l = xas_synth_new((xas_synth_callback_sample)sine_sample, @@ -139,7 +145,7 @@ int main(int argc, char **argv) { goto error_mixer_new; } - if (xas_mixer_input_add(mixer, bank_stream, 1.0, 0.0) == NULL) { + if (xas_mixer_input_add(mixer, player_stream, 1.0, 0.0) == NULL) { goto error_mixer_input_add; } @@ -166,8 +172,8 @@ int main(int argc, char **argv) { void *buf; ssize_t readlen; - if (i >= 300 && !xas_bank_active(bank)) { - xas_bank_play(bank, 0, 1.0); + if (i >= 300 && !xas_bank_player_playing(player)) { + xas_bank_player_start(player, 0, 1.0); } if ((readlen = xas_audio_stream_read(mixer->output, @@ -186,7 +192,7 @@ int main(int argc, char **argv) { xas_mixer_destroy(mixer); xas_audio_stream_destroy(synth_r); xas_audio_stream_destroy(synth_l); - xas_audio_stream_destroy(bank_stream); + xas_audio_stream_destroy(player_stream); xas_audio_stream_destroy(voice); xas_audio_stream_destroy(output); @@ -208,15 +214,18 @@ error_synth_new_r: xas_audio_stream_destroy(synth_l); error_synth_new_l: - xas_audio_stream_destroy(bank_stream); + xas_audio_stream_destroy(player_stream); -error_bank_stream_new: +error_bank_player_stream_new: xas_audio_stream_destroy(voice); error_vox_stream_new: xas_audio_stream_destroy(output); error_riff_new_file: + xas_bank_player_destroy(player); + +error_bank_player_new: xas_bank_destroy(bank); error_bank_new: diff --git a/include/xas/bank.h b/include/xas/bank.h index 9f877d0..be623f0 100644 --- a/include/xas/bank.h +++ b/include/xas/bank.h @@ -5,8 +5,10 @@ #include -#define XAS_BANK_IDLE 0 -#define XAS_BANK_ACTIVE (1 << 0) +enum xas_bank_player_status { + XAS_BANK_PLAYER_STOPPED, + XAS_BANK_PLAYER_PLAYING, +}; typedef struct _xas_bank_entry { size_t duration; @@ -17,13 +19,17 @@ typedef struct _xas_bank { size_t entry_size, entry_count; +} xas_bank; + +typedef struct _xas_bank_player { + xas_bank *bank; + enum xas_bank_player_status status; - int flags; float gain; size_t entry, index; -} xas_bank; +} xas_bank_player; xas_bank *xas_bank_new(xas_audio_format format, size_t entry_size, @@ -31,17 +37,23 @@ xas_bank *xas_bank_new(xas_audio_format format, void xas_bank_destroy(xas_bank *bank); -int xas_bank_play(xas_bank *bank, size_t entry, float gain); - -void xas_bank_stop(xas_bank *bank); - -int xas_bank_active(xas_bank *bank); - ssize_t xas_bank_record(xas_bank *bank, xas_audio_stream *input, size_t entry_index, size_t count); -xas_audio_stream *xas_bank_stream_new(xas_bank *bank); +xas_bank_player *xas_bank_player_new(xas_bank *bank); + +void xas_bank_player_destroy(xas_bank_player *player); + +int xas_bank_player_start(xas_bank_player *player, + size_t entry, + float gain); + +int xas_bank_player_stop(xas_bank_player *player); + +int xas_bank_player_playing(xas_bank_player *player); + +xas_audio_stream *xas_bank_player_stream_new(xas_bank_player *player); #endif /* _XAS_BANK_H */ diff --git a/src/bank.c b/src/bank.c index ff7c071..19e3514 100644 --- a/src/bank.c +++ b/src/bank.c @@ -37,26 +37,6 @@ void xas_bank_destroy(xas_bank *bank) { free(bank); } -int xas_bank_play(xas_bank *bank, size_t entry, float gain) { - bank->flags |= XAS_BANK_ACTIVE; - bank->gain = gain; - bank->entry = entry; - bank->index = 0; - - return 0; -} - -void xas_bank_stop(xas_bank *bank) { - bank->flags &= ~XAS_BANK_ACTIVE; - bank->gain = 0.0; - bank->entry = 0; - bank->index = 0; -} - -int xas_bank_active(xas_bank *bank) { - return bank->flags & XAS_BANK_ACTIVE; -} - ssize_t xas_bank_record(xas_bank *bank, xas_audio_stream *input, size_t entry_index, @@ -97,35 +77,92 @@ error_audio_stream_read: return -1; } -static ssize_t stream_fill(xas_bank *bank, +xas_bank_player *xas_bank_player_new(xas_bank *bank) { + xas_bank_player *player; + + if ((player = malloc(sizeof(*player))) == NULL) { + goto error_malloc_player; + } + + player->bank = bank; + player->status = XAS_BANK_PLAYER_STOPPED; + player->gain = 0.0f; + player->entry = 0; + player->index = 0; + + return player; + +error_malloc_player: + return NULL; +} + +void xas_bank_player_destroy(xas_bank_player *player) { + free(player); +} + +int xas_bank_player_start(xas_bank_player *player, + size_t entry, + float gain) { + if (player->status == XAS_BANK_PLAYER_PLAYING) { + return 0; + } + + player->status = XAS_BANK_PLAYER_PLAYING; + player->gain = gain; + player->entry = entry; + player->index = 0; + + return 0; +} + +int xas_bank_player_stop(xas_bank_player *player) { + if (player->status == XAS_BANK_PLAYER_STOPPED) { + return 0; + } + + player->status = XAS_BANK_PLAYER_STOPPED; + player->gain = 0.0; + player->entry = 0; + player->index = 0; + + return 1; +} + +int xas_bank_player_playing(xas_bank_player *player) { + return player->status == XAS_BANK_PLAYER_PLAYING; +} + +static ssize_t stream_fill(xas_bank_player *player, int16_t *dest, size_t count, xas_audio_stream *stream) { - size_t index_o = 0, - left = count; + xas_bank *bank = player->bank; + + size_t index_o = 0, + left = count; while (left) { - if (bank->flags & XAS_BANK_ACTIVE) { + if (player->status == XAS_BANK_PLAYER_PLAYING) { xas_bank_entry *entry = - &((xas_bank_entry *)(bank + 1))[bank->entry]; + &((xas_bank_entry *)(bank + 1))[player->entry]; int16_t *src = (int16_t *)(entry + 1); - size_t remaining = entry->duration - bank->index, + size_t remaining = entry->duration - player->index, amount = remaining < left? remaining: left; size_t i; for (i=0; igain * src[bank->index + i]; + dest[index_o + i] = player->gain * src[player->index + i]; } - left -= amount; - bank->index += amount; - index_o += amount; + left -= amount; + player->index += amount; + index_o += amount; - if (bank->index == entry->duration) { - xas_bank_stop(bank); + if (player->index == entry->duration) { + xas_bank_player_stop(player); } } else { xas_audio_zero(bank->format, dest, index_o, left); @@ -138,14 +175,14 @@ static ssize_t stream_fill(xas_bank *bank, return count; } -void stream_cleanup(xas_bank *bank, xas_audio_stream *stream) { +void stream_cleanup(xas_bank_player *player, xas_audio_stream *stream) { return; } -xas_audio_stream *xas_bank_stream_new(xas_bank *bank) { +xas_audio_stream *xas_bank_player_stream_new(xas_bank_player *player) { return xas_audio_stream_new_source((xas_audio_fill)stream_fill, (xas_audio_cleanup)stream_cleanup, - bank->format, - bank->entry_size, - bank); + player->bank->format, + player->bank->entry_size, + player); } -- cgit v1.2.3