diff options
Diffstat (limited to 'src/bank.c')
-rw-r--r-- | src/bank.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/bank.c b/src/bank.c new file mode 100644 index 0000000..8c17bb3 --- /dev/null +++ b/src/bank.c @@ -0,0 +1,109 @@ +#include <stdlib.h> +#include <string.h> + +#include <xas/bank.h> + +xas_bank *xas_bank_new(size_t sample_size, + size_t sample_rate, + size_t entry_size, + size_t entry_count) { + xas_bank *bank; + + size_t entry_size_total = sizeof(xas_bank_entry) + entry_size; + + size_t total = sizeof(xas_bank) + sample_size + * entry_size_total + * entry_count; + + if ((bank = malloc(total)) == NULL) { + goto error_malloc_bank; + } + + memset(bank, '\0', total); + + bank->sample_size = sample_size; + bank->sample_rate = sample_rate; + bank->entry_size = entry_size; + bank->entry_count = entry_count; + + return bank; + +error_malloc_bank: + return NULL; +} + +void xas_bank_destroy(xas_bank *bank) { + free(bank); +} + +int xas_bank_play(xas_bank *bank, size_t entry, float force) { + bank->flags |= XAS_BANK_ACTIVE; + bank->force = force; + bank->entry = entry; + bank->index = 0; + + return 0; +} + +void xas_bank_stop(xas_bank *bank) { + bank->flags &= ~XAS_BANK_ACTIVE; + bank->force = 0.0; + bank->entry = 0; + bank->index = 0; +} + +static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) { + return ((uint8_t *)buf) + stream->channels * stream->sample_size * index; +} + +static ssize_t bank_fill(xas_bank *bank, + int16_t *samples, + size_t count, + xas_audio_stream *stream) { + size_t index_o = 0, + left = count; + + if (!(bank->flags & XAS_BANK_ACTIVE)) { + memset(samples, '\0', count * bank->sample_size); + + return count; + } + + while (left) { + xas_bank_entry *entry = + &((xas_bank_entry *)(bank + 1))[bank->entry]; + + size_t remaining = bank->entry_size - bank->index, + amount = remaining < left? remaining: left; + + memcpy(ptr(stream, samples, index_o), + ptr(stream, entry + 1, bank->index), + amount * stream->channels * stream->sample_size); + + left -= amount; + index_o += amount; + + bank->index += amount; + + if (bank->index == entry->duration) { + bank->index = 0; + } + } + + return count; +} + +void bank_cleanup(xas_bank *bank, + xas_audio_stream *stream) { + return; +} + +xas_audio_stream *xas_bank_stream_new(xas_bank *bank) { + return xas_audio_stream_new_source((xas_audio_fill)bank_fill, + (xas_audio_cleanup)bank_cleanup, + bank, + XAS_AUDIO_STREAM_MONO, + bank->sample_size, + bank->sample_rate, + bank->entry_size); +} |