summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/xas/riff.h7
-rw-r--r--src/audio.c145
-rw-r--r--src/riff.c8
3 files changed, 156 insertions, 4 deletions
diff --git a/include/xas/riff.h b/include/xas/riff.h
index 07ed0f2..4e600da 100644
--- a/include/xas/riff.h
+++ b/include/xas/riff.h
@@ -8,6 +8,9 @@
#define XAS_RIFF_WAVE_DEFAULT_TYPE 1
+#pragma pack(1)
+#pragma pack(push)
+
typedef struct _xas_riff_chunk {
char id[4];
uint32_t size;
@@ -18,7 +21,7 @@ typedef struct _xas_riff_main_chunk {
char type[4];
} xas_riff_main_chunk;
-typedef struct _xas_riff_wave_format_chunk {
+typedef struct _xas_riff_wave_chunk {
xas_riff_chunk header;
uint16_t type,
@@ -39,6 +42,8 @@ typedef struct _xas_riff_wave_header {
typedef struct _xas_riff xas_riff;
+#pragma pack(pop)
+
xas_audio_stream *xas_riff_file_open(const char *path,
size_t sample_size,
size_t sample_rate,
diff --git a/src/audio.c b/src/audio.c
new file mode 100644
index 0000000..8922698
--- /dev/null
+++ b/src/audio.c
@@ -0,0 +1,145 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <xas/audio.h>
+
+static xas_audio_stream *stream_new(enum xas_audio_stream_type type,
+ void *callback,
+ xas_audio_cleanup cleanup,
+ void *ctx,
+ size_t sample_size,
+ size_t sample_rate,
+ size_t channels,
+ size_t buffer_size) {
+ xas_audio_stream *stream;
+
+ size_t total = sizeof(xas_audio_stream)
+ + sample_size * channels * buffer_size;
+
+ if ((stream = malloc(total)) == NULL) {
+ goto error_malloc_stream;
+ }
+
+ stream->type = type;
+ stream->sample_size = sample_size;
+ stream->sample_rate = sample_rate;
+ stream->channels = channels;
+ stream->buffer_size = buffer_size;
+ stream->buffer_count = 0;
+ stream->callback = callback;
+ stream->cleanup = cleanup;
+ stream->ctx = ctx;
+
+ return stream;
+
+error_malloc_stream:
+ return NULL;
+}
+
+xas_audio_stream *xas_audio_stream_new_sink(xas_audio_drain drain,
+ xas_audio_cleanup cleanup,
+ void *ctx,
+ size_t sample_size,
+ size_t sample_rate,
+ size_t channels,
+ size_t buffer_size) {
+ return stream_new(XAS_AUDIO_STREAM_SINK,
+ drain,
+ cleanup,
+ ctx,
+ sample_size,
+ sample_rate,
+ channels,
+ buffer_size);
+}
+
+xas_audio_stream *xas_audio_stream_new_source(xas_audio_fill fill,
+ xas_audio_cleanup cleanup,
+ void *ctx,
+ size_t sample_size,
+ size_t sample_rate,
+ size_t channels,
+ size_t buffer_size) {
+ return stream_new(XAS_AUDIO_STREAM_SOURCE,
+ fill,
+ cleanup,
+ ctx,
+ sample_size,
+ sample_rate,
+ channels,
+ buffer_size);
+}
+
+void xas_audio_stream_destroy(xas_audio_stream *stream) {
+ if (stream->cleanup) {
+ stream->cleanup(stream->ctx, stream);
+ }
+
+ free(stream);
+}
+
+static inline int stream_flush(xas_audio_stream *stream) {
+ printf("Flushing stream\n");
+ if (stream->buffer_count == 0) {
+ return 0;
+ }
+
+ if (stream->drain(stream->ctx,
+ stream + 1,
+ stream->buffer_count,
+ stream) < 0) {
+ goto error_stream_drain;
+ }
+
+ stream->buffer_count = 0;
+
+ return 0;
+
+error_stream_drain:
+ return -1;
+}
+
+ssize_t xas_audio_stream_write(xas_audio_stream *stream,
+ void *samples,
+ size_t count) {
+ size_t total = stream->buffer_count + count,
+ offset = stream->sample_size * stream->channels * stream->buffer_count;
+
+ if (total > stream->buffer_size) {
+ if (stream_flush(stream) < 0) {
+ goto error_stream_flush;
+ }
+ }
+
+ memcpy((uint8_t *)(stream + 1) + offset,
+ samples,
+ stream->sample_size * stream->channels * count);
+
+ stream->buffer_count += count;
+
+ return count;
+
+error_stream_flush:
+ return -1;
+}
+
+ssize_t xas_audio_stream_read(xas_audio_stream *stream,
+ void *samples,
+ size_t count) {
+ return stream->fill(stream->ctx,
+ samples,
+ count,
+ stream);
+}
+
+int xas_audio_stream_flush(xas_audio_stream *stream) {
+ if (stream->type == XAS_AUDIO_STREAM_SINK) {
+ return stream_flush(stream);
+ }
+
+ errno = EINVAL;
+
+ return -1;
+}
diff --git a/src/riff.c b/src/riff.c
index 3a4933f..cae821e 100644
--- a/src/riff.c
+++ b/src/riff.c
@@ -20,8 +20,8 @@ static int header_write(xas_riff *riff) {
.riff = {
{
.id = "RIFF",
- .size = sizeof(xas_riff_wave_chunk)
- + sizeof(xas_riff_chunk)
+ .size = sizeof(xas_riff_main_chunk)
+ + sizeof(xas_riff_wave_chunk)
+ riff->size
},
@@ -89,7 +89,7 @@ static xas_riff *file_open(const char *path,
goto error_open;
}
- riff->size = 0;
+ riff->size = 0;
riff->sample_size = sample_size;
riff->sample_rate = sample_rate;
riff->channels = channels;
@@ -141,6 +141,8 @@ static int audio_drain(xas_riff *riff,
goto error_write;
}
+ riff->size += wrlen;
+
return wrlen / stream->sample_size / stream->channels;
error_write: