#include #include #include #include #include #include #include #include #include #include #include #include #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; va_start(args, message); if (message) { vfprintf(stderr, message, args); fputc('\n', stderr); } va_end(args); fprintf(stderr, "usage: %s output.wav\n", argv[0]); 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->format.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) { xas_spatial_scene *scene; xas_audio_stream *synth, *voice, *output, *wave; xas_vox *vox; synth_sine sine_channels[2] = { { SYNTH_STATUS_ON, 0.0f, 2600 }, { SYNTH_STATUS_ON, 0.0f, 420 }, }; xas_audio_format format = { .channels = XAS_AUDIO_STEREO, .sample_size = XAS_AUDIO_PCM_16_BIT, .sample_rate = 44100 }; size_t buffer_size = 735, duration_s = 300, i; xas_spatial_coord speakers[2] = { { -0.09, 0.0, 0.0 }, { 0.09, 0.0, 0.0 } }; if (argc != 2) { usage(argc, argv, "No output file provided"); } if ((wave = xas_riff_new_file(argv[1], format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_new_file; } if ((synth = 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; } if ((vox = xas_vox_new("/usr/bin/text2wave", format, buffer_size)) == NULL) { goto error_vox_new; } if ((voice = xas_vox_stream_new(vox)) == NULL) { goto error_vox_stream_new; } if ((scene = xas_spatial_scene_new(format, speakers[0], speakers[1])) == NULL) { goto error_spatial_scene_new; } if ((output = xas_spatial_scene_new_stream(scene, buffer_size)) == NULL) { goto error_spatial_scene_new_stream; } if (xas_spatial_scene_add_object(scene, (xas_spatial_coord){ 5.2, 0.0, 0.0 }, synth) == NULL) { goto error_spatial_scene_add_object; } if (xas_spatial_scene_add_object(scene, (xas_spatial_coord){ -5.2, 0.0, 0.0 }, voice) == NULL) { goto error_spatial_scene_add_object; } xas_vox_say(vox, "I want to eat your soul. You don't understand. I really want to eat your soul.\n"); xas_vox_generate(vox); for (i=0; i