#include #include #include xas_bank *xas_bank_new(xas_audio_format format, size_t entry_size, size_t entry_count) { xas_bank *bank; size_t entry_size_total = sizeof(xas_bank_entry) + format.sample_size * entry_size; size_t total = sizeof(xas_bank) + entry_count * entry_size_total; if ((bank = malloc(total)) == NULL) { goto error_malloc_bank; } memset(bank, '\0', total); bank->format.channels = XAS_AUDIO_MONO; bank->format.sample_size = format.sample_size; bank->format.sample_rate = format.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 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, size_t count) { xas_bank_entry *entry = &((xas_bank_entry *)(bank + 1))[entry_index]; size_t left = count, index_o = 0; if (count > bank->entry_size) { count = bank->entry_size; } while (left) { ssize_t readlen, amount = left > count? count: left; void *buf; if ((readlen = xas_audio_stream_read(input, &buf, amount)) < 0) { goto error_audio_stream_read; } xas_audio_copy(bank->format, entry + 1, buf, index_o, 0, readlen); left -= readlen; index_o += readlen; } return entry->duration = index_o; error_audio_stream_read: return -1; } static ssize_t stream_fill(xas_bank *bank, int16_t *dest, size_t count, xas_audio_stream *stream) { size_t index_o = 0, left = count; while (left) { if (bank->flags & XAS_BANK_ACTIVE) { xas_bank_entry *entry = &((xas_bank_entry *)(bank + 1))[bank->entry]; int16_t *src = (int16_t *)(entry + 1); size_t remaining = entry->duration - bank->index, amount = remaining < left? remaining: left; size_t i; for (i=0; igain * src[bank->index + i]; } left -= amount; bank->index += amount; index_o += amount; if (bank->index == entry->duration) { xas_bank_stop(bank); } } else { xas_audio_zero(bank->format, dest, index_o, left); index_o += left; left = 0; } } return count; } void stream_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)stream_fill, (xas_audio_cleanup)stream_cleanup, bank->format, bank->entry_size, bank); }