diff options
-rw-r--r-- | examples/say.c | 111 |
1 files changed, 95 insertions, 16 deletions
diff --git a/examples/say.c b/examples/say.c index 92d2b19..d72c7ff 100644 --- a/examples/say.c +++ b/examples/say.c @@ -9,8 +9,19 @@ #include <xas/audio.h> #include <xas/mixer.h> #include <xas/riff.h> +#include <xas/synth.h> #include <xas/vox.h> +#define SYNTH_STATUS_CLEAR 0 +#define SYNTH_STATUS_ON (1 << 0) + +typedef struct _synth_sine { + int flags; + float phase; + + size_t frequency; +} synth_sine; + static void usage(int argc, char **argv, const char *message, ...) { va_list args; @@ -28,31 +39,53 @@ static void usage(int argc, char **argv, const char *message, ...) { exit(EX_USAGE); } +static int16_t sine_sample(xas_synth *synth, synth_sine *sine) { + int16_t ret; + static float tau = 2.0f * M_PI; + + if (sine->flags & SYNTH_STATUS_ON) { + ret = (int16_t)roundf((INT16_MAX >> 2) * sinf(sine->phase)); + + sine->phase += tau / (synth->sample_rate / sine->frequency); + + if (sine->phase > tau) { + sine->phase -= tau; + } + } else { + ret = 0; + } + + return ret; +} + +static void sine_cleanup(xas_synth *synth, synth_sine *sine) { + return; +} + int main(int argc, char **argv) { + synth_sine sine_channels[2] = { + { SYNTH_STATUS_ON, 0.0f, 220 }, + { SYNTH_STATUS_ON, 0.0f, 420 }, + }; + xas_mixer *mixer; xas_audio_stream *input, + *synth_l, + *synth_r, *output; xas_vox *vox; - size_t sample_rate = 44100, - buffer_size = 4096, - duration_s = 60, + size_t sample_rate = 44100, + buffer_size = 735, + duration_frames = 3600, i; if (argc != 2) { usage(argc, argv, "No output file provided"); } - if ((output = xas_riff_new_file(argv[1], - XAS_AUDIO_STREAM_PCM_16_BIT, - sample_rate, - XAS_AUDIO_STREAM_STEREO, - O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { - goto error_riff_new_file; - } - if ((vox = xas_vox_new("/usr/bin/text2wave", XAS_AUDIO_STREAM_PCM_16_BIT, sample_rate, @@ -61,10 +94,36 @@ int main(int argc, char **argv) { goto error_vox_new; } + if ((output = xas_riff_new_file(argv[1], + XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + XAS_AUDIO_STREAM_STEREO, + O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { + goto error_riff_new_file; + } + if ((input = xas_vox_stream_new(vox)) == NULL) { goto error_vox_stream_new; } + if ((synth_l = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + buffer_size, + (xas_synth_callback_sample)sine_sample, + (xas_synth_callback_cleanup)sine_cleanup, + &sine_channels[0])) == NULL) { + goto error_synth_new_l; + } + + if ((synth_r = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT, + sample_rate, + buffer_size, + (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, @@ -72,13 +131,23 @@ int main(int argc, char **argv) { goto error_mixer_new; } - if (xas_mixer_input_add(mixer, input, 1.0, -1.0) == NULL) { + if (xas_mixer_input_add(mixer, input, 1.0, 0.0) == NULL) { + goto error_mixer_input_add; + } + + if (xas_mixer_input_add(mixer, synth_l, 0.5, -1.0) == NULL) { + goto error_mixer_input_add; + } + + if (xas_mixer_input_add(mixer, synth_r, 0.5, 1.0) == NULL) { goto error_mixer_input_add; } xas_vox_say(vox, "I want to eat your soul. You don't understand. I really want to eat your soul.\n"); - for (i=0; i<duration_s; i++) { + xas_vox_generate(vox); + + for (i=0; i<duration_frames; i++) { void *buf; ssize_t readlen; @@ -96,9 +165,13 @@ int main(int argc, char **argv) { xas_audio_stream_flush(output); xas_mixer_destroy(mixer); + xas_audio_stream_destroy(synth_r); + xas_audio_stream_destroy(synth_l); xas_audio_stream_destroy(input); xas_audio_stream_destroy(output); + xas_vox_destroy(vox); + return EX_OK; error_audio_stream_write: @@ -107,14 +180,20 @@ 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(input); error_vox_stream_new: - xas_vox_destroy(vox); - -error_vox_new: xas_audio_stream_destroy(output); error_riff_new_file: + xas_vox_destroy(vox); + +error_vox_new: return EX_OSERR; } |