diff options
-rw-r--r-- | examples/test.c | 114 | ||||
-rw-r--r-- | include/xas/audio.h | 2 | ||||
-rw-r--r-- | include/xas/mixer.h | 7 | ||||
-rw-r--r-- | include/xas/synth.h | 23 | ||||
-rw-r--r-- | src/audio.c | 6 | ||||
-rw-r--r-- | src/mixer.c | 38 | ||||
-rw-r--r-- | src/synth.c | 60 |
7 files changed, 174 insertions, 76 deletions
diff --git a/examples/test.c b/examples/test.c index e1da192..49937aa 100644 --- a/examples/test.c +++ b/examples/test.c @@ -8,6 +8,7 @@ #include <xas/synth.h> #include <xas/audio.h> +#include <xas/mixer.h> #include <xas/riff.h> #define SYNTH_STATUS_CLEAR 0 @@ -51,61 +52,112 @@ static int16_t sine_sample(xas_synth *synth, synth_sine *sine) { return ret; } -static void sine_destroy(xas_synth *synth, synth_sine *sine) { +static void sine_cleanup(xas_synth *synth, synth_sine *sine) { return; } int main(int argc, char **argv) { - xas_audio_stream *stream; - xas_synth *synth; + xas_mixer *mixer; - synth_sine sine = { - .flags = SYNTH_STATUS_ON, - .phase = 0.0f, - .frequency = 220 + xas_audio_stream *synth_l, + *synth_r, + *wave; + + synth_sine sine_channels[2] = { + { SYNTH_STATUS_ON, 0.0f, 220 }, + { SYNTH_STATUS_ON, 0.0f, 420 }, }; size_t sample_rate = 44100, - duration_s = 60; - - int i; + duration_s = 60, + i; if (argc != 2) { usage(argc, argv, "No output file provided"); } - if ((stream = xas_riff_file_open(argv[1], - 2, - sample_rate, - 1, - O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { + if ((wave = xas_riff_file_open(argv[1], + XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + XAS_AUDIO_STREAM_STEREO, + O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_file_open; } - if ((synth = xas_synth_new(sample_rate, - (xas_synth_callback_sample)sine_sample, - (xas_synth_callback_destroy)sine_destroy, - &sine)) == NULL) { - goto error_synth_new; + if ((synth_l = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + sample_rate, + (xas_synth_callback_sample)sine_sample, + (xas_synth_callback_cleanup)sine_cleanup, + &sine_channels[0])) == NULL) { + goto error_synth_new_l; } - for (i=0; i < duration_s * sample_rate; i++) { - int16_t samples[1] = { - xas_synth_sample(synth) - }; + if ((synth_r = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + sample_rate, + (xas_synth_callback_sample)sine_sample, + (xas_synth_callback_cleanup)sine_cleanup, + &sine_channels[1])) == NULL) { + goto error_synth_new_r; + } + + if ((mixer = xas_mixer_new(XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + XAS_AUDIO_STREAM_STEREO, + sample_rate)) == NULL) { + goto error_mixer_new; + } - xas_audio_stream_write(stream, - samples, - 1); + if (xas_mixer_input_add(mixer, synth_l, 0.3, -1.0) == NULL) { + goto error_mixer_input_add; } - xas_audio_stream_flush(stream); - xas_audio_stream_destroy(stream); + if (xas_mixer_input_add(mixer, synth_r, 0.3, 1.0) == NULL) { + goto error_mixer_input_add; + } + + printf("Good here\n"); + + for (i=0; i<duration_s; i++) { + int16_t *buf; + ssize_t readlen; + + printf("one second\n"); + + if ((readlen = xas_audio_stream_read(mixer->output, + (void **)&buf, + sample_rate)) < 0) { + goto error_audio_stream_read; + } + + if (xas_audio_stream_write(wave, buf, readlen) < 0) { + goto error_audio_stream_write; + } + } + + xas_audio_stream_flush(wave); + + xas_mixer_destroy(mixer); + xas_audio_stream_destroy(synth_r); + xas_audio_stream_destroy(synth_l); + xas_audio_stream_destroy(wave); return EX_OK; -error_synth_new: - xas_audio_stream_destroy(stream); +error_audio_stream_write: +error_audio_stream_read: +error_mixer_input_add: + xas_mixer_destroy(mixer); + +error_mixer_new: + xas_audio_stream_destroy(synth_r); + +error_synth_new_r: + xas_audio_stream_destroy(synth_l); + +error_synth_new_l: + xas_audio_stream_destroy(wave); error_riff_file_open: return EX_OSERR; diff --git a/include/xas/audio.h b/include/xas/audio.h index 76d1e68..9c40dd8 100644 --- a/include/xas/audio.h +++ b/include/xas/audio.h @@ -74,7 +74,7 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream, size_t count); ssize_t xas_audio_stream_read(xas_audio_stream *stream, - void *samples, + void **samples, size_t count); int xas_audio_stream_flush(xas_audio_stream *stream); diff --git a/include/xas/mixer.h b/include/xas/mixer.h index ca60976..9fd77cb 100644 --- a/include/xas/mixer.h +++ b/include/xas/mixer.h @@ -25,10 +25,15 @@ typedef struct _xas_mixer { size_t buffer_size; } xas_mixer; -xas_mixer *xas_mixer_new(xas_audio_stream *output); +xas_mixer *xas_mixer_new(size_t sample_size, + size_t sample_rate, + size_t channels, + size_t buffer_size); void xas_mixer_destroy(xas_mixer *mixer); +xas_audio_stream *xas_mixer_output(xas_mixer *mixer); + xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer, xas_audio_stream *stream, float gain, diff --git a/include/xas/synth.h b/include/xas/synth.h index fe3ce9f..1d070aa 100644 --- a/include/xas/synth.h +++ b/include/xas/synth.h @@ -10,23 +10,22 @@ typedef struct _xas_synth xas_synth; typedef int16_t (*xas_synth_callback_sample)(xas_synth *synth, void *ctx); -typedef void (*xas_synth_callback_destroy)(xas_synth *synth, void *ctx); +typedef void (*xas_synth_callback_cleanup)(xas_synth *synth, void *ctx); struct _xas_synth { - size_t sample_rate; + size_t sample_size, + sample_rate; - xas_synth_callback_sample sample; - xas_synth_callback_destroy destroy; + xas_synth_callback_sample sample; + xas_synth_callback_cleanup cleanup; void *ctx; }; -xas_synth *xas_synth_new(size_t sample_rate, - xas_synth_callback_sample sample, - xas_synth_callback_destroy destroy, - void *ctx); - -void xas_synth_destroy(xas_synth *synth); - -int16_t xas_synth_sample(xas_synth *synth); +xas_audio_stream *xas_synth_new(size_t sample_size, + size_t sample_rate, + size_t buffer_size, + xas_synth_callback_sample sample, + xas_synth_callback_cleanup cleanup, + void *ctx); #endif /* _XAS_SYNTH_H */ diff --git a/src/audio.c b/src/audio.c index 85f417d..d0a1e63 100644 --- a/src/audio.c +++ b/src/audio.c @@ -161,10 +161,12 @@ error_stream_flush: } ssize_t xas_audio_stream_read(xas_audio_stream *stream, - void *samples, + void **samples, size_t count) { + *samples = stream + 1; + return stream->fill(stream->ctx, - samples, + *samples, count, stream); } diff --git a/src/mixer.c b/src/mixer.c index 8007cae..3fc1ac9 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -34,11 +34,11 @@ static void mixer_apply_int16_t_stereo(int16_t *dest, static ssize_t mixer_fill(xas_mixer *mixer, void *samples, - size_t count) { - ssize_t ret = 0; + size_t count, + xas_audio_stream *output) { + ssize_t total = 0; - xas_mixer_input *input = mixer->inputs, - *output = mixer->output; + xas_mixer_input *input = mixer->inputs; void (*mixer_apply)(int16_t *, int16_t *, @@ -54,29 +54,34 @@ static ssize_t mixer_fill(xas_mixer *mixer, while (input) { xas_mixer_input *next = input->next; + int16_t *buf; ssize_t readlen; if ((readlen = xas_audio_stream_read(input->stream, - mixer->buf, + (void **)&buf, count)) < 0) { goto error_audio_read_stream; } - mixer_apply((int16_t *)mixer->buf, - (int16_t *)(input + 1), + mixer_apply((int16_t *)(mixer->buf), + buf, readlen, input->bias_l, input->bias_r); - if (ret < readlen) { - ret = readlen; + if (total < readlen) { + total = readlen; } input = next; } - return ret; + memcpy(samples, + mixer->buf, + total * output->sample_size * output->channels); + + return total; error_audio_read_stream: return -1; @@ -126,7 +131,7 @@ void xas_mixer_destroy(xas_mixer *mixer) { xas_mixer_input *input = mixer->inputs; while (input) { - xas_mixer_input *next = input; + xas_mixer_input *next = input->next; free(input); @@ -138,6 +143,10 @@ void xas_mixer_destroy(xas_mixer *mixer) { free(mixer); } +xas_audio_stream *xas_mixer_output(xas_mixer *mixer) { + return mixer->output; +} + static inline void input_set_pan(xas_mixer_input *input, float pan) { float angle, term, @@ -165,7 +174,6 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer, if (stream->sample_size != mixer->output->sample_size || stream->sample_rate != mixer->output->sample_rate - || stream->channels != mixer->output->channels || stream->buffer_size != mixer->buffer_size) { errno = EINVAL; @@ -178,12 +186,16 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer, input->stream = stream; input->gain = gain; + input->next = NULL; input_set_pan(input, pan); if (mixer->inputs == NULL) { mixer->inputs = input; - mixer->last = NULL; + mixer->last = input; + } else { + mixer->last->next = input; + mixer->last = input; } return input; diff --git a/src/synth.c b/src/synth.c index 9b18daf..a482875 100644 --- a/src/synth.c +++ b/src/synth.c @@ -2,33 +2,61 @@ #include <xas/synth.h> -xas_synth *xas_synth_new(size_t sample_rate, - xas_synth_callback_sample sample, - xas_synth_callback_destroy destroy, - void *ctx) { +static ssize_t synth_fill(xas_synth *synth, + int16_t *samples, + size_t count, + xas_audio_stream *stream) { + size_t i; + + for (i=0; i<count; i++) { + samples[i] = synth->sample(synth, synth->ctx); + } + + return count; +} + +static void synth_cleanup(xas_synth *synth, xas_audio_stream *stream) { + if (synth->cleanup) { + synth->cleanup(synth, synth->ctx); + } + + free(synth); +} + +xas_audio_stream *xas_synth_new(size_t sample_size, + size_t sample_rate, + size_t buffer_size, + xas_synth_callback_sample sample, + xas_synth_callback_cleanup cleanup, + void *ctx) { + xas_audio_stream *stream; xas_synth *synth; if ((synth = malloc(sizeof(*synth))) == NULL) { goto error_malloc_synth; } + synth->sample_size = sample_size; synth->sample_rate = sample_rate; synth->sample = sample; - synth->destroy = destroy; + synth->cleanup = cleanup; synth->ctx = ctx; - return synth; + if ((stream = xas_audio_stream_new_source((xas_audio_fill)synth_fill, + (xas_audio_cleanup)synth_cleanup, + synth, + sample_size, + sample_rate, + XAS_AUDIO_STREAM_MONO, + buffer_size)) == NULL) { + goto error_audio_stream_new_source; + } -error_malloc_synth: - return NULL; -} + return stream; -void xas_synth_destroy(xas_synth *synth) { - if (synth->destroy) { - synth->destroy(synth, synth->ctx); - } -} +error_audio_stream_new_source: + free(synth); -int16_t xas_synth_sample(xas_synth *synth) { - return synth->sample(synth, synth->ctx); +error_malloc_synth: + return NULL; } |