summaryrefslogtreecommitdiffstats
path: root/src/bank.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bank.c')
-rw-r--r--src/bank.c109
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);
+}