#include #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); } int main(int argc, char **argv) { xas_mixer *mixer; xas_bank *bank; xas_vox *vox; xas_synth *sine_l, *sine_r; xas_bank_player *player; xas_audio_stream *voice, *player_stream, *synth_l, *synth_r, *output; 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) { usage(argc, argv, "No output file provided"); } if ((sine_l = xas_synth_new(format, buffer_size, XAS_SYNTH_SINE)) == NULL) { goto error_synth_new_l; } if ((sine_r = xas_synth_new(format, buffer_size, XAS_SYNTH_SINE)) == NULL) { goto error_synth_new_r; } if ((vox = xas_vox_new(format, buffer_size, "/usr/bin/text2wave")) == NULL) { goto error_vox_new; } if ((bank = xas_bank_new(format, 2646000, 4)) == NULL) { goto error_bank_new; } if ((player = xas_bank_player_new(bank)) == NULL) { goto error_bank_player_new; } if ((output = xas_riff_new_file(argv[1], format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_new_file; } if ((voice = xas_vox_stream_new(vox)) == NULL) { goto error_vox_stream_new; } if ((player_stream = xas_bank_player_stream_new(player)) == NULL) { goto error_bank_player_stream_new; } if ((synth_l = xas_synth_new_stream(sine_l)) == NULL) { goto error_synth_new_stream_l; } if ((synth_r = xas_synth_new_stream(sine_r)) == NULL) { goto error_synth_new_stream_r; } if ((mixer = xas_mixer_new(format, buffer_size)) == NULL) { goto error_mixer_new; } if (xas_mixer_input_add(mixer, player_stream, 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_synth_set_frequency(sine_l, 220); xas_synth_start(sine_l); xas_synth_set_frequency(sine_r, 420); xas_synth_start(sine_r); /* * Time to fill the sample bank, meow! */ xas_vox_say(vox, "I want to eat your soul."); xas_vox_say(vox, "You don't understand."); xas_vox_say(vox, "I really want to eat your soul."); xas_vox_generate(vox); if (xas_bank_record(bank, voice, 0, 247018) < 0) { goto error_bank_record; } xas_bank_player_set_entry(player, 0); for (i=0; i= 300 && !xas_bank_player_playing(player)) { xas_bank_player_start(player); } if ((readlen = xas_audio_stream_read(mixer->output, &buf, buffer_size)) < 0) { goto error_audio_stream_read; } if (xas_audio_stream_write(output, buf, readlen) < 0) { goto error_audio_stream_write; } } xas_audio_stream_flush(output); xas_mixer_destroy(mixer); xas_audio_stream_destroy(synth_r); xas_audio_stream_destroy(synth_l); xas_synth_destroy(sine_r); xas_synth_destroy(sine_l); xas_audio_stream_destroy(player_stream); xas_audio_stream_destroy(voice); xas_audio_stream_destroy(output); xas_bank_player_destroy(player); xas_bank_destroy(bank); xas_vox_destroy(vox); return EX_OK; error_audio_stream_write: error_audio_stream_read: error_bank_record: error_mixer_input_add: xas_mixer_destroy(mixer); error_mixer_new: xas_audio_stream_destroy(synth_r); error_synth_new_stream_r: xas_audio_stream_destroy(synth_l); error_synth_new_stream_l: xas_audio_stream_destroy(player_stream); error_bank_player_stream_new: xas_audio_stream_destroy(voice); error_vox_stream_new: xas_audio_stream_destroy(output); error_riff_new_file: xas_bank_player_destroy(player); error_bank_player_new: xas_bank_destroy(bank); error_bank_new: xas_vox_destroy(vox); error_vox_new: xas_synth_destroy(sine_r); error_synth_new_r: xas_synth_destroy(sine_l); error_synth_new_l: return EX_OSERR; }