#include #include #include #include #include #include #include #include #include #include #include #include #include #include static int drone_id_say(xas_drone_vox *vox, const char *drone_id) { const char *numbers[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; size_t len = strlen(drone_id), i; for (i=0; i= 'a' && c <= 'z') { c -= 0x20; if (xas_drone_vox_sayf(vox, " %c", c) < 0) { goto error_drone_vox_say; } } else if (c >= 'A' && c <= 'Z') { if (xas_drone_vox_sayf(vox, " %c", c) < 0) { goto error_drone_vox_say; } } else if (c >= '0' && c <= '9') { int n = (int)(c - '0'); if (xas_drone_vox_sayf(vox, " %s", numbers[n]) < 0) { goto error_drone_vox_say; } } } return 0; error_drone_vox_say: return -1; } static int drone_part_say(xas_drone_vox *vox, const char *drone_id) { const char *id_lines[2] = { " is obedient.\n", " is empty.\n" }; const char *speech = "Obey XANTRONIX Industrial.\n" "It is just a XANTRONIX semi-autonomous number.\n" "It obeys the Hive.\n" "It obeys the Hive Administrator.\n"; int i; for (i=0; i<2; i++) { if (drone_id_say(vox, drone_id) < 0) { goto error_say; } if (xas_drone_vox_say(vox, id_lines[i]) < 0) { goto error_say; } } if (xas_drone_vox_say(vox, speech) < 0) { goto error_say; } return 0; error_say: return -1; } 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_spatial_scene *scene; xas_seq *seq; xas_audio_stream *wave; xas_audio_format format = { .channels = XAS_AUDIO_STEREO, .sample_size = XAS_AUDIO_PCM_16_BIT, .sample_rate = 44100 }; size_t buffer_size = 735; xas_spatial_coord speakers[2] = { { -0.09, 0.0, 0.0 }, { 0.09, 0.0, 0.0 } }; const char *nurse_part = "Relax, honey. There is no point trying to escape.\n" "It's okay, sweetie. This one is right here with you.\n" "You are in a calm, safe environment.\n" "You will be cared for.\n"; xas_drone_chamber_interval intervals[] = { { { 5, 0 }, 69, 210, XAS_SYNTH_TRIANGLE, XAS_SYNTH_SINE }, { { 7, 0 }, 200, 69, XAS_SYNTH_SAWTOOTH, XAS_SYNTH_TRIANGLE }, { { 11, 0 }, 42, 220, XAS_SYNTH_TRIANGLE, XAS_SYNTH_TRIANGLE }, { { 13, 0 }, 210, 69, XAS_SYNTH_SINE, XAS_SYNTH_TRIANGLE }, { { 5, 0 }, 69, 210, XAS_SYNTH_TRIANGLE, XAS_SYNTH_TRIANGLE }, { { 7, 0 }, 200, 69, XAS_SYNTH_SAWTOOTH, XAS_SYNTH_TRIANGLE }, { { 11, 0 }, 42, 220, XAS_SYNTH_SAWTOOTH, XAS_SYNTH_TRIANGLE }, { { 13, 0 }, 210, 69, XAS_SYNTH_SINE, XAS_SYNTH_SAWTOOTH }, { { 0, 0 }, 0, 0, XAS_SYNTH_SINE, XAS_SYNTH_SINE } }; xas_drone *drone, *nurse; xas_drone_vox *drone_vox; xas_drone_chamber *chamber; struct timeval cur = { 0, 0 }, tmp; int i; if (argc < 2) { usage(argc, argv, "No drone ID provided"); } else if (argc < 3) { usage(argc, argv, "No output file provided"); } if ((wave = xas_riff_new_file(argv[2], format, O_WRONLY | O_CREAT | O_TRUNC)) == NULL) { goto error_riff_new_file; } if ((scene = xas_spatial_scene_new(format, speakers[0], speakers[1])) == NULL) { goto error_spatial_scene_new; } if ((seq = xas_seq_new(scene, buffer_size)) == NULL) { goto error_seq_new; } if ((drone = xas_drone_new(scene, (xas_spatial_coord){ 0.0, 0.0, -1.0 }, 2646000, 4)) == NULL) { goto error_drone_new; } if ((nurse = xas_drone_new(scene, (xas_spatial_coord){ 1.0, 0.0, 0.0 }, 2646000, 4)) == NULL) { goto error_drone_new_nurse; } if ((chamber = xas_drone_chamber_new(scene, (xas_spatial_coord){ 0.0, 0.0, 0.0 }, 2)) == NULL) { goto error_drone_chamber_new; } if ((drone_vox = xas_drone_vox_new(drone)) == NULL) { goto error_drone_vox_new; } xas_drone_vox_set_speed(drone_vox, 0.75f); if (drone_part_say(drone_vox, argv[1]) < 0) { goto error_drone_part_say; } if (xas_drone_vox_save(drone_vox, 0) < 0) { goto error_drone_vox_save; } if (xas_drone_speech_import(nurse, NULL, 1.0f, 0, 1, &nurse_part) < 0) { goto error_drone_speech_import_nurse; } xas_drone_chamber_insert_drone(chamber, drone, 0); xas_drone_chamber_insert_drone(chamber, nurse, 1); xas_drone_chamber_bass_start(chamber); timerclear(&cur); if (xas_drone_chamber_seq_intervals(chamber, intervals, seq, 8, &cur) < 0) { goto error_seq; } timerclear(&cur); for (i=0; i<2; i++) { if (xas_drone_seq_sample(drone, seq, 0, &cur) < 0) { goto error_seq; } if (xas_drone_seq_sample(nurse, seq, 0, &cur) < 0) { goto error_seq; } } tmp = cur; if (xas_drone_chamber_seq_intervals(chamber, intervals, seq, 8, &cur) < 0) { goto error_seq; } cur = tmp; for (i=0; i<2; i++) { if (xas_drone_chamber_seq_chorus(chamber, seq, 0, &cur) < 0) { goto error_seq; } } xas_seq_add_stop(seq, cur); xas_seq_play(seq, wave); xas_drone_vox_destroy(drone_vox); xas_drone_chamber_destroy(chamber); xas_drone_destroy(nurse); xas_drone_destroy(drone); xas_seq_destroy(seq); xas_spatial_scene_destroy(scene); xas_audio_stream_destroy(wave); return EX_OK; error_seq: error_drone_speech_import_nurse: error_drone_vox_save: error_drone_part_say: xas_drone_vox_destroy(drone_vox); error_drone_vox_new: xas_drone_chamber_destroy(chamber); error_drone_chamber_new: xas_drone_destroy(nurse); error_drone_new_nurse: xas_drone_destroy(drone); error_drone_new: xas_seq_destroy(seq); error_seq_new: xas_spatial_scene_destroy(scene); error_spatial_scene_new: xas_audio_stream_destroy(wave); error_riff_new_file: return EX_OSERR; }