#include #include #include 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); }