From 77976d03699f95ea28278b5fdbba392f198b5f52 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 9 Feb 2022 00:00:51 -0500 Subject: Implement xas_audio_format type Changes: * Implement xas_audio_format struct to provide sample size, channels, and sample rate * Refactor argument order for most functions to allow a reasonable reading of argument types, when replacing three separate size_t arguments with one xas_audio_format object --- examples/open.c | 6 +-- examples/say.c | 50 ++++++++++----------- examples/test.c | 36 ++++++++------- include/xas/audio.h | 38 ++++++++++------ include/xas/bank.h | 13 +++--- include/xas/mixer.h | 5 +-- include/xas/riff.h | 4 +- include/xas/synth.h | 11 ++--- include/xas/vox.h | 12 ++--- src/audio.c | 107 +++++++++++++++++++++++++++------------------ src/bank.c | 44 +++++++++---------- src/mixer.c | 45 +++++++++---------- src/riff.c | 123 +++++++++++++++++++++++----------------------------- src/synth.c | 27 ++++++------ src/vox.c | 51 ++++++++++------------ 15 files changed, 279 insertions(+), 293 deletions(-) diff --git a/examples/open.c b/examples/open.c index 4bf036b..27ededd 100644 --- a/examples/open.c +++ b/examples/open.c @@ -37,9 +37,9 @@ int main(int argc, char **argv) { } printf("channels %zu sample rate %zu sample size %zu\n", - wave->channels, - wave->sample_rate, - wave->sample_size); + wave->format.channels, + wave->format.sample_rate, + wave->format.sample_size); xas_audio_stream_destroy(wave); diff --git a/examples/say.c b/examples/say.c index 19dcb08..e0aea9a 100644 --- a/examples/say.c +++ b/examples/say.c @@ -41,13 +41,14 @@ static void usage(int argc, char **argv, const char *message, ...) { } static int16_t sine_sample(xas_synth *synth, synth_sine *sine) { - int16_t ret; static float tau = 2.0f * M_PI; + int16_t ret; + if (sine->flags & SYNTH_STATUS_ON) { ret = (int16_t)roundf((INT16_MAX >> 2) * sinf(sine->phase)); - sine->phase += tau / (synth->sample_rate / sine->frequency); + sine->phase += tau / (synth->format.sample_rate / sine->frequency); if (sine->phase > tau) { sine->phase -= tau; @@ -80,9 +81,14 @@ int main(int argc, char **argv) { *synth_r, *output; - size_t sample_rate = 44100, - buffer_size = 735, - duration_frames = 3600, + xas_audio_format format = { + .channels = XAS_AUDIO_STEREO, + .sample_size = XAS_AUDIO_PCM_16_BIT, + .sample_rate = 44100 + }; + + size_t buffer_size = 735, + duration_frames = 3600, i; if (argc != 2) { @@ -90,24 +96,17 @@ int main(int argc, char **argv) { } if ((vox = xas_vox_new("/usr/bin/text2wave", - XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size, - NULL)) == NULL) { + format, + buffer_size)) == NULL) { goto error_vox_new; } - if ((bank = xas_bank_new(XAS_AUDIO_PCM_16_BIT, - 44100, - 2646000, - 4)) == NULL) { + if ((bank = xas_bank_new(format, 2646000, 4)) == NULL) { goto error_bank_new; } if ((output = xas_riff_new_file(argv[1], - XAS_AUDIO_STEREO, - XAS_AUDIO_PCM_16_BIT, - sample_rate, + format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_new_file; } @@ -120,28 +119,23 @@ int main(int argc, char **argv) { goto error_bank_stream_new; } - if ((synth_l = xas_synth_new(XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size, - (xas_synth_callback_sample)sine_sample, + if ((synth_l = xas_synth_new((xas_synth_callback_sample)sine_sample, (xas_synth_callback_cleanup)sine_cleanup, + format, + buffer_size, &sine_channels[0])) == NULL) { goto error_synth_new_l; } - if ((synth_r = xas_synth_new(XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size, - (xas_synth_callback_sample)sine_sample, + if ((synth_r = xas_synth_new((xas_synth_callback_sample)sine_sample, (xas_synth_callback_cleanup)sine_cleanup, + format, + buffer_size, &sine_channels[1])) == NULL) { goto error_synth_new_r; } - if ((mixer = xas_mixer_new(XAS_AUDIO_STEREO, - XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size)) == NULL) { + if ((mixer = xas_mixer_new(format, buffer_size)) == NULL) { goto error_mixer_new; } diff --git a/examples/test.c b/examples/test.c index 24e6ba1..1fbd8c4 100644 --- a/examples/test.c +++ b/examples/test.c @@ -45,7 +45,7 @@ static int16_t sine_sample(xas_synth *synth, synth_sine *sine) { if (sine->flags & SYNTH_STATUS_ON) { ret = (int16_t)roundf((INT16_MAX >> 2) * sinf(sine->phase)); - sine->phase += tau / (synth->sample_rate / sine->frequency); + sine->phase += tau / (synth->format.sample_rate / sine->frequency); if (sine->phase > tau) { sine->phase -= tau; @@ -73,8 +73,13 @@ int main(int argc, char **argv) { { SYNTH_STATUS_ON, 0.0f, 420 }, }; - size_t sample_rate = 44100, - buffer_size = 4096, + xas_audio_format format = { + .channels = XAS_AUDIO_STEREO, + .sample_size = XAS_AUDIO_PCM_16_BIT, + .sample_rate = 44100 + }; + + size_t buffer_size = 4096, duration_s = 60, i; @@ -83,35 +88,28 @@ int main(int argc, char **argv) { } if ((wave = xas_riff_new_file(argv[1], - XAS_AUDIO_STEREO, - XAS_AUDIO_PCM_16_BIT, - sample_rate, + format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_new_file; } - if ((synth_l = xas_synth_new(XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size, - (xas_synth_callback_sample)sine_sample, + if ((synth_l = xas_synth_new((xas_synth_callback_sample)sine_sample, (xas_synth_callback_cleanup)sine_cleanup, + format, + buffer_size, &sine_channels[0])) == NULL) { goto error_synth_new_l; } - if ((synth_r = xas_synth_new(XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size, - (xas_synth_callback_sample)sine_sample, + if ((synth_r = xas_synth_new((xas_synth_callback_sample)sine_sample, (xas_synth_callback_cleanup)sine_cleanup, + format, + buffer_size, &sine_channels[1])) == NULL) { goto error_synth_new_r; } - if ((mixer = xas_mixer_new(XAS_AUDIO_STEREO, - XAS_AUDIO_PCM_16_BIT, - sample_rate, - buffer_size)) == NULL) { + if ((mixer = xas_mixer_new(format, buffer_size)) == NULL) { goto error_mixer_new; } @@ -129,7 +127,7 @@ int main(int argc, char **argv) { if ((readlen = xas_audio_stream_read(mixer->output, &buf, - sample_rate)) < 0) { + buffer_size)) < 0) { goto error_audio_stream_read; } diff --git a/include/xas/audio.h b/include/xas/audio.h index 5a92a50..b18a2d2 100644 --- a/include/xas/audio.h +++ b/include/xas/audio.h @@ -30,12 +30,16 @@ typedef ssize_t (*xas_audio_fill)(void *ctx, typedef void (*xas_audio_cleanup)(void *ctx, xas_audio_stream *stream); -struct _xas_audio_stream { - enum xas_audio_stream_type type; - +typedef struct _xas_audio_format { size_t channels, sample_size, sample_rate; +} xas_audio_format; + +struct _xas_audio_stream { + enum xas_audio_stream_type type; + + xas_audio_format format; size_t buffer_size, buffer_count; @@ -51,21 +55,29 @@ struct _xas_audio_stream { void *ctx; }; +void xas_audio_zero(xas_audio_format format, + void *dest, + size_t index, + size_t count); + +void xas_audio_copy(xas_audio_format format, + void *dest, + void *src, + size_t index_dest, + size_t index_src, + size_t count); + xas_audio_stream *xas_audio_stream_new_sink(xas_audio_drain drain, xas_audio_cleanup cleanup, - void *ctx, - size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size); + xas_audio_format format, + size_t buffer_size, + void *ctx); xas_audio_stream *xas_audio_stream_new_source(xas_audio_fill fill, xas_audio_cleanup cleanup, - void *ctx, - size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size); + xas_audio_format format, + size_t buffer_size, + void *ctx); void xas_audio_stream_destroy(xas_audio_stream *stream); diff --git a/include/xas/bank.h b/include/xas/bank.h index ec3cb99..9f877d0 100644 --- a/include/xas/bank.h +++ b/include/xas/bank.h @@ -13,26 +13,25 @@ typedef struct _xas_bank_entry { } xas_bank_entry; typedef struct _xas_bank { - size_t sample_size, - sample_rate, - entry_size, + xas_audio_format format; + + size_t entry_size, entry_count; int flags; - float force; + float gain; size_t entry, index; } xas_bank; -xas_bank *xas_bank_new(size_t sample_size, - size_t sample_rate, +xas_bank *xas_bank_new(xas_audio_format format, size_t entry_size, size_t entry_count); void xas_bank_destroy(xas_bank *bank); -int xas_bank_play(xas_bank *bank, size_t entry, float force); +int xas_bank_play(xas_bank *bank, size_t entry, float gain); void xas_bank_stop(xas_bank *bank); diff --git a/include/xas/mixer.h b/include/xas/mixer.h index 73fd363..3769272 100644 --- a/include/xas/mixer.h +++ b/include/xas/mixer.h @@ -25,10 +25,7 @@ typedef struct _xas_mixer { size_t buffer_size; } xas_mixer; -xas_mixer *xas_mixer_new(size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size); +xas_mixer *xas_mixer_new(xas_audio_format format, size_t buffer_size); void xas_mixer_destroy(xas_mixer *mixer); diff --git a/include/xas/riff.h b/include/xas/riff.h index f78e9e9..5a5d4ed 100644 --- a/include/xas/riff.h +++ b/include/xas/riff.h @@ -50,9 +50,7 @@ typedef struct _xas_riff xas_riff; #pragma pack(pop) xas_audio_stream *xas_riff_new_file(const char *path, - size_t channels, - size_t sample_size, - size_t sample_rate, + xas_audio_format format, int flags); xas_audio_stream *xas_riff_open_file(const char *path, int flags); diff --git a/include/xas/synth.h b/include/xas/synth.h index 1d070aa..20446cd 100644 --- a/include/xas/synth.h +++ b/include/xas/synth.h @@ -13,19 +13,16 @@ typedef int16_t (*xas_synth_callback_sample)(xas_synth *synth, void *ctx); typedef void (*xas_synth_callback_cleanup)(xas_synth *synth, void *ctx); struct _xas_synth { - size_t sample_size, - sample_rate; - + xas_audio_format format; xas_synth_callback_sample sample; xas_synth_callback_cleanup cleanup; void *ctx; }; -xas_audio_stream *xas_synth_new(size_t sample_size, - size_t sample_rate, - size_t buffer_size, - xas_synth_callback_sample sample, +xas_audio_stream *xas_synth_new(xas_synth_callback_sample sample, xas_synth_callback_cleanup cleanup, + xas_audio_format format, + size_t buffer_size, void *ctx); #endif /* _XAS_SYNTH_H */ diff --git a/include/xas/vox.h b/include/xas/vox.h index 85d8d20..fd442a8 100644 --- a/include/xas/vox.h +++ b/include/xas/vox.h @@ -13,11 +13,9 @@ typedef struct _xas_vox { const char *text2wave_path; - size_t sample_size, - sample_rate, - buffer_size; + xas_audio_format format; - void *ctx; + size_t buffer_size; int flags; @@ -29,10 +27,8 @@ typedef struct _xas_vox { } xas_vox; xas_vox *xas_vox_new(const char *text2wave_path, - size_t sample_size, - size_t sample_rate, - size_t buffer_size, - void *ctx); + xas_audio_format format, + size_t buffer_size); void xas_vox_destroy(xas_vox *vox); diff --git a/src/audio.c b/src/audio.c index 001d449..561870f 100644 --- a/src/audio.c +++ b/src/audio.c @@ -4,32 +4,54 @@ #include +void xas_audio_copy(xas_audio_format format, + void *dest, + void *src, + size_t index_dest, + size_t index_src, + size_t count) { + size_t stride = format.channels * format.sample_size; + + memcpy(((uint8_t *)dest) + stride * index_dest, + ((uint8_t *)src) + stride * index_src, + stride * count); +} + +void xas_audio_zero(xas_audio_format format, + void *dest, + size_t index, + size_t count) { + size_t stride = format.channels * format.sample_size; + + memset((uint8_t *)dest + stride * index, + '\0', + stride * count); +} + static xas_audio_stream *stream_new(enum xas_audio_stream_type type, void *callback, xas_audio_cleanup cleanup, - void *ctx, - size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size) { + xas_audio_format format, + size_t buffer_size, + void *ctx) { xas_audio_stream *stream; size_t total = sizeof(xas_audio_stream) - + channels * sample_size * buffer_size; + + format.channels * format.sample_size * buffer_size; if ((stream = malloc(total)) == NULL) { goto error_malloc_stream; } - stream->type = type; - stream->channels = channels; - stream->sample_size = sample_size; - stream->sample_rate = sample_rate; - stream->buffer_size = buffer_size; - stream->buffer_count = 0; - stream->callback = callback; - stream->cleanup = cleanup; - stream->ctx = ctx; + stream->type = type; + stream->format.channels = format.channels; + stream->format.sample_size = format.sample_size; + stream->format.sample_rate = format.sample_rate; + stream->buffer_size = buffer_size; + stream->buffer_count = 0; + stream->callback = callback; + stream->cleanup = cleanup; + stream->ctx = ctx; return stream; @@ -39,36 +61,28 @@ error_malloc_stream: xas_audio_stream *xas_audio_stream_new_sink(xas_audio_drain drain, xas_audio_cleanup cleanup, - void *ctx, - size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size) { + xas_audio_format format, + size_t buffer_size, + void *ctx) { return stream_new(XAS_AUDIO_STREAM_SINK, drain, cleanup, - ctx, - channels, - sample_size, - sample_rate, - buffer_size); + format, + buffer_size, + ctx); } xas_audio_stream *xas_audio_stream_new_source(xas_audio_fill fill, xas_audio_cleanup cleanup, - void *ctx, - size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size) { + xas_audio_format format, + size_t buffer_size, + void *ctx) { return stream_new(XAS_AUDIO_STREAM_SOURCE, fill, cleanup, - ctx, - channels, - sample_size, - sample_rate, - buffer_size); + format, + buffer_size, + ctx); } void xas_audio_stream_destroy(xas_audio_stream *stream) { @@ -100,7 +114,8 @@ error_stream_drain: } static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) { - return ((uint8_t *)buf) + stream->channels * stream->sample_size * index; + return ((uint8_t *)buf) + + stream->format.channels * stream->format.sample_size * index; } ssize_t xas_audio_stream_write(xas_audio_stream *stream, @@ -116,12 +131,15 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream, */ size_t remaining = stream->buffer_size - stream->buffer_count; - memcpy(ptr(stream, stream + 1, stream->buffer_count), - ptr(stream, samples, index_i), - remaining * stream->channels * stream->sample_size); + xas_audio_copy(stream->format, + stream + 1, + samples, + stream->buffer_count, + index_i, + remaining); if (stream->drain(stream->ctx, - ptr(stream, stream + 1, 0), + stream + 1, stream->buffer_size, stream) < 0) { goto error_stream_drain; @@ -157,9 +175,12 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream, * Enough of the input has been drained that it can be copied to * the target buffer. */ - memcpy(ptr(stream, stream + 1, stream->buffer_count), - ptr(stream, samples, index_i), - remaining * stream->channels * stream->sample_size); + xas_audio_copy(stream->format, + stream + 1, + samples, + stream->buffer_count, + index_i, + remaining); index_i += remaining; diff --git a/src/bank.c b/src/bank.c index d38822f..ff7c071 100644 --- a/src/bank.c +++ b/src/bank.c @@ -3,13 +3,12 @@ #include -xas_bank *xas_bank_new(size_t sample_size, - size_t sample_rate, +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) + sample_size + size_t entry_size_total = sizeof(xas_bank_entry) + format.sample_size * entry_size; size_t total = sizeof(xas_bank) + entry_count @@ -21,8 +20,10 @@ xas_bank *xas_bank_new(size_t sample_size, memset(bank, '\0', total); - bank->sample_size = sample_size; - bank->sample_rate = sample_rate; + 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; @@ -36,9 +37,9 @@ void xas_bank_destroy(xas_bank *bank) { free(bank); } -int xas_bank_play(xas_bank *bank, size_t entry, float force) { +int xas_bank_play(xas_bank *bank, size_t entry, float gain) { bank->flags |= XAS_BANK_ACTIVE; - bank->force = force; + bank->gain = gain; bank->entry = entry; bank->index = 0; @@ -47,7 +48,7 @@ int xas_bank_play(xas_bank *bank, size_t entry, float force) { void xas_bank_stop(xas_bank *bank) { bank->flags &= ~XAS_BANK_ACTIVE; - bank->force = 0.0; + bank->gain = 0.0; bank->entry = 0; bank->index = 0; } @@ -56,10 +57,6 @@ int xas_bank_active(xas_bank *bank) { return bank->flags & XAS_BANK_ACTIVE; } -static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) { - return ((uint8_t *)buf) + stream->channels * stream->sample_size * index; -} - ssize_t xas_bank_record(xas_bank *bank, xas_audio_stream *input, size_t entry_index, @@ -83,9 +80,12 @@ ssize_t xas_bank_record(xas_bank *bank, goto error_audio_stream_read; } - memcpy(ptr(input, entry + 1, index_o), - ptr(input, buf, 0), - readlen * bank->sample_size); + xas_audio_copy(bank->format, + entry + 1, + buf, + index_o, + 0, + readlen); left -= readlen; index_o += readlen; @@ -117,7 +117,7 @@ static ssize_t stream_fill(xas_bank *bank, size_t i; for (i=0; iforce * src[bank->index + i]; + dest[index_o + i] = bank->gain * src[bank->index + i]; } left -= amount; @@ -128,9 +128,7 @@ static ssize_t stream_fill(xas_bank *bank, xas_bank_stop(bank); } } else { - memset(ptr(stream, dest, index_o), - '\0', - left * stream->channels * stream->sample_size); + xas_audio_zero(bank->format, dest, index_o, left); index_o += left; left = 0; @@ -147,9 +145,7 @@ void stream_cleanup(xas_bank *bank, xas_audio_stream *stream) { 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, - XAS_AUDIO_MONO, - bank->sample_size, - bank->sample_rate, - bank->entry_size); + bank->format, + bank->entry_size, + bank); } diff --git a/src/mixer.c b/src/mixer.c index b1f2e47..b4e3bf1 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -69,9 +69,7 @@ static ssize_t mixer_fill(xas_mixer *mixer, xas_mixer_input *input = mixer->inputs; - memset(mixer->buf, - '\0', - output->channels * output->sample_size * output->buffer_size); + xas_audio_zero(output->format, mixer->buf, 0, mixer->buffer_size); while (input) { void (*mixer_apply)(int16_t *, @@ -86,13 +84,16 @@ static ssize_t mixer_fill(xas_mixer *mixer, ssize_t readlen; - if (output->channels == 2 && input->stream->channels == 2) { + size_t channels_in = input->stream->format.channels, + channels_out = output->format.channels; + + if (channels_in == 2 && channels_out == 2) { mixer_apply = mixer_apply_stereo_to_stereo; - } else if (output->channels == 2 && input->stream->channels == 1) { + } else if (channels_in == 1 && channels_out == 2) { mixer_apply = mixer_apply_mono_to_stereo; - } else if (output->channels == 1 && input->stream->channels == 1) { + } else if (channels_in == 1 && channels_out == 1) { mixer_apply = mixer_apply_mono_to_mono; - } else if (output->channels == 1 && input->stream->channels == 2) { + } else if (channels_in == 2 && channels_out == 2) { mixer_apply = mixer_apply_stereo_to_mono; } else { goto error_invalid_input; @@ -118,9 +119,12 @@ static ssize_t mixer_fill(xas_mixer *mixer, input = next; } - memcpy(samples, - mixer->buf, - total * output->channels * output->sample_size); + xas_audio_copy(output->format, + samples, + mixer->buf, + 0, + 0, + total); return total; @@ -129,27 +133,24 @@ error_audio_read_stream: return -1; } -xas_mixer *xas_mixer_new(size_t channels, - size_t sample_size, - size_t sample_rate, - size_t buffer_size) { +xas_mixer *xas_mixer_new(xas_audio_format format, size_t buffer_size) { xas_mixer *mixer; + size_t total = buffer_size * format.channels * format.sample_size; + if ((mixer = malloc(sizeof(*mixer))) == NULL) { goto error_malloc_mixer; } - if ((mixer->buf = malloc(channels * sample_size * buffer_size)) == NULL) { + if ((mixer->buf = malloc(total)) == NULL) { goto error_malloc_buf; } if ((mixer->output = xas_audio_stream_new_source((xas_audio_fill)mixer_fill, NULL, - mixer, - channels, - sample_size, - sample_rate, - buffer_size)) == NULL) { + format, + buffer_size, + mixer)) == NULL) { goto error_audio_stream_new_source; } @@ -217,8 +218,8 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer, float pan) { xas_mixer_input *input; - if (stream->sample_size != mixer->output->sample_size - || stream->sample_rate != mixer->output->sample_rate) { + if (stream->format.sample_size != mixer->output->format.sample_size + || stream->format.sample_rate != mixer->output->format.sample_rate) { errno = EINVAL; goto error_invalid_stream; diff --git a/src/riff.c b/src/riff.c index ce788f5..5f63ff4 100644 --- a/src/riff.c +++ b/src/riff.c @@ -12,9 +12,7 @@ struct _xas_riff { int fd; size_t size; - size_t channels, - sample_size, - sample_rate; + xas_audio_format format; }; static int header_write(xas_riff *riff) { @@ -38,11 +36,13 @@ static int header_write(xas_riff *riff) { }, .type = XAS_RIFF_WAVE_DEFAULT_TYPE, - .channels = riff->channels, - .sample_rate = riff->sample_rate, - .byte_rate = riff->channels * riff->sample_size * riff->sample_rate, - .sample_size = riff->sample_size, - .sample_size_bits = riff->sample_size << 3 + .channels = riff->format.channels, + .sample_rate = riff->format.sample_rate, + .sample_size = riff->format.sample_size, + .sample_size_bits = riff->format.sample_size << 3, + .byte_rate = riff->format.channels + * riff->format.sample_size + * riff->format.sample_rate }, { @@ -70,9 +70,7 @@ error_io: } static xas_riff *new_file(const char *path, - size_t channels, - size_t sample_size, - size_t sample_rate, + xas_audio_format format, int flags) { xas_riff *riff; @@ -86,11 +84,12 @@ static xas_riff *new_file(const char *path, goto error_open; } - riff->file = path; - riff->size = 0; - riff->channels = channels; - riff->sample_size = sample_size; - riff->sample_rate = sample_rate; + riff->file = path; + riff->size = 0; + + riff->format.channels = format.channels; + riff->format.sample_size = format.sample_size; + riff->format.sample_rate = format.sample_rate; if (header_write(riff) < 0) { goto error_header_write; @@ -167,9 +166,9 @@ static int wave_header_parse(xas_riff *riff, goto error_invalid_wave_data_format_id; } - riff->channels = header->wave.channels; - riff->sample_size = header->wave.sample_size; - riff->sample_rate = header->wave.sample_rate; + riff->format.channels = header->wave.channels; + riff->format.sample_size = header->wave.sample_size; + riff->format.sample_rate = header->wave.sample_rate; return 0; @@ -196,12 +195,13 @@ static xas_riff *open_fd(int fd) { goto error_malloc_riff; } - riff->file = NULL; - riff->fd = fd; - riff->size = 0; - riff->channels = 0; - riff->sample_size = 0; - riff->sample_rate = 0; + riff->file = NULL; + riff->fd = fd; + riff->size = 0; + + riff->format.channels = 0; + riff->format.sample_size = 0; + riff->format.sample_rate = 0; if ((readlen = read(fd, &header, sizeof(header))) < 0) { goto error_read; @@ -244,11 +244,12 @@ static xas_riff *open_file(const char *path, int flags) { goto error_open; } - riff->file = path; - riff->size = 0; - riff->channels = 0; - riff->sample_size = 0; - riff->sample_rate = 0; + riff->file = path; + riff->size = 0; + + riff->format.channels = 0; + riff->format.sample_size = 0; + riff->format.sample_rate = 0; if (lseek(riff->fd, 0, SEEK_SET) < 0) { goto error_lseek; @@ -299,8 +300,8 @@ static ssize_t audio_drain(xas_riff *riff, void *samples, size_t count, xas_audio_stream *stream) { - size_t len = count * stream->channels - * stream->sample_size; + size_t stride = stream->format.channels * stream->format.sample_size, + len = stride * count; ssize_t wrlen; @@ -310,7 +311,7 @@ static ssize_t audio_drain(xas_riff *riff, riff->size += wrlen; - return wrlen / stream->channels / stream->sample_size; + return wrlen / stride; error_write: return -1; @@ -320,8 +321,8 @@ static ssize_t audio_fill(xas_riff *riff, void *samples, size_t count, xas_audio_stream *stream) { - size_t len = count * stream->channels - * stream->sample_size; + size_t stride = stream->format.channels * stream->format.sample_size, + len = count * stride; ssize_t rdlen; @@ -329,46 +330,36 @@ static ssize_t audio_fill(xas_riff *riff, goto error_read; } - return rdlen / stream->channels / stream->sample_size; + return rdlen / stride; error_read: return -1; } xas_audio_stream *xas_riff_new_file(const char *path, - size_t channels, - size_t sample_size, - size_t sample_rate, + xas_audio_format format, int flags) { xas_audio_stream *stream; xas_riff *riff; - if ((riff = new_file(path, - channels, - sample_size, - sample_rate, - flags)) == NULL) { + if ((riff = new_file(path, format, flags)) == NULL) { goto error_new_file; } if (flags & (O_RDWR | O_WRONLY)) { if ((stream = xas_audio_stream_new_sink((xas_audio_drain)audio_drain, (xas_audio_cleanup)close_file, - riff, - channels, - sample_size, - sample_rate, - 4096)) == NULL) { + format, + 4096, + riff)) == NULL) { goto error_audio_stream_new_sink; } } else { if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill, (xas_audio_cleanup)close_file, - riff, - channels, - sample_size, - sample_rate, - 4096)) == NULL) { + format, + 4096, + riff)) == NULL) { goto error_audio_stream_new_sink; } } @@ -393,21 +384,17 @@ xas_audio_stream *xas_riff_open_file(const char *path, int flags) { if (flags & (O_RDWR | O_WRONLY)) { if ((stream = xas_audio_stream_new_sink((xas_audio_drain)audio_drain, (xas_audio_cleanup)close_file, - riff, - riff->channels, - riff->sample_size, - riff->sample_rate, - 4096)) == NULL) { + riff->format, + 4096, + riff)) == NULL) { goto error_audio_stream_new_sink; } } else { if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill, (xas_audio_cleanup)close_file, - riff, - riff->channels, - riff->sample_size, - riff->sample_rate, - 4096)) == NULL) { + riff->format, + 4096, + riff)) == NULL) { goto error_audio_stream_new_sink; } } @@ -431,11 +418,9 @@ xas_audio_stream *xas_riff_open_fd(int fd) { if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill, (xas_audio_cleanup)close_file, - riff, - riff->channels, - riff->sample_size, - riff->sample_rate, - 4096)) == NULL) { + riff->format, + 4096, + riff)) == NULL) { goto error_audio_stream_new_sink; } diff --git a/src/synth.c b/src/synth.c index 6dd14ea..d96c1b5 100644 --- a/src/synth.c +++ b/src/synth.c @@ -23,11 +23,10 @@ static void synth_cleanup(xas_synth *synth, xas_audio_stream *stream) { 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_audio_stream *xas_synth_new(xas_synth_callback_sample sample, xas_synth_callback_cleanup cleanup, + xas_audio_format format, + size_t buffer_size, void *ctx) { xas_audio_stream *stream; xas_synth *synth; @@ -36,19 +35,19 @@ xas_audio_stream *xas_synth_new(size_t sample_size, goto error_malloc_synth; } - synth->sample_size = sample_size; - synth->sample_rate = sample_rate; - synth->sample = sample; - synth->cleanup = cleanup; - synth->ctx = ctx; + synth->format.channels = XAS_AUDIO_MONO; + synth->format.sample_size = format.sample_size; + synth->format.sample_rate = format.sample_rate; + + synth->sample = sample; + synth->cleanup = cleanup; + synth->ctx = ctx; if ((stream = xas_audio_stream_new_source((xas_audio_fill)synth_fill, (xas_audio_cleanup)synth_cleanup, - synth, - XAS_AUDIO_MONO, - sample_size, - sample_rate, - buffer_size)) == NULL) { + synth->format, + buffer_size, + synth)) == NULL) { goto error_audio_stream_new_source; } diff --git a/src/vox.c b/src/vox.c index 6739ee0..94d41dc 100644 --- a/src/vox.c +++ b/src/vox.c @@ -64,7 +64,7 @@ static int vox_start(xas_vox *vox) { NULL }; - snprintf(sample_rate, sizeof(sample_rate)-1, "%zu", vox->sample_rate); + snprintf(sample_rate, sizeof(sample_rate)-1, "%zu", vox->format.sample_rate); (void)vox_stop(vox); @@ -144,17 +144,15 @@ static ssize_t vox_fill(xas_vox *vox, ssize_t readlen, readcount; - size_t i; - if (!(vox->flags & XAS_VOX_ACTIVE)) { - memset(samples, '\0', count * vox->sample_size); + xas_audio_zero(vox->format, samples, 0, count); return count; } if ((readlen = read(vox->stdout, samples, - count * vox->sample_size)) < 0) { + count * vox->format.sample_size)) < 0) { goto error_read; } @@ -162,11 +160,9 @@ static ssize_t vox_fill(xas_vox *vox, vox_stop(vox); } - readcount = readlen / vox->sample_size; + readcount = readlen / vox->format.sample_size; - for (i=readcount; iformat, samples, readcount, count-readcount); return count; @@ -175,10 +171,8 @@ error_read: } xas_vox *xas_vox_new(const char *text2wave_path, - size_t sample_size, - size_t sample_rate, - size_t buffer_size, - void *ctx) { + xas_audio_format format, + size_t buffer_size) { xas_vox *vox; if ((vox = malloc(sizeof(*vox))) == NULL) { @@ -186,16 +180,17 @@ xas_vox *xas_vox_new(const char *text2wave_path, } vox->text2wave_path = text2wave_path; - vox->sample_size = sample_size; - vox->sample_rate = sample_rate; - vox->buffer_size = buffer_size; - vox->ctx = ctx; - vox->flags = XAS_VOX_IDLE; - vox->pid = -1; - vox->stdin = -1; - vox->stdout = -1; - vox->in = NULL; + vox->format.channels = XAS_AUDIO_MONO; + vox->format.sample_size = format.sample_size; + vox->format.sample_rate = format.sample_rate; + + vox->buffer_size = buffer_size; + vox->flags = XAS_VOX_IDLE; + vox->pid = -1; + vox->stdin = -1; + vox->stdout = -1; + vox->in = NULL; return vox; @@ -229,8 +224,8 @@ int xas_vox_generate(xas_vox *vox) { goto error_riff_open_fd; } - if (output->sample_size != vox->sample_size - || output->sample_rate != vox->sample_rate) { + if (output->format.sample_size != vox->format.sample_size + || output->format.sample_rate != vox->format.sample_rate) { errno = EINVAL; goto error_invalid_stream; @@ -274,9 +269,7 @@ int xas_vox_say(xas_vox *vox, const char *message) { xas_audio_stream *xas_vox_stream_new(xas_vox *vox) { return xas_audio_stream_new_source((xas_audio_fill)vox_fill, (xas_audio_cleanup)vox_cleanup, - vox, - XAS_AUDIO_MONO, - vox->sample_size, - vox->sample_rate, - vox->buffer_size); + vox->format, + vox->buffer_size, + vox); } -- cgit v1.2.3