From f96a070e690d97764fb4c47caaba9c3847d7a713 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Sun, 13 Mar 2022 21:42:48 -0400 Subject: Implement examples/pod.c Implement examples/pod.c to create audio files for any given drone, providing a drone identifier as first argument --- examples/Makefile | 2 +- examples/pod.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 examples/pod.c diff --git a/examples/Makefile b/examples/Makefile index 756fa89..1146600 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -8,7 +8,7 @@ LIBNAME = xas CFLAGS += -I$(INCLUDE_PATH) LDFLAGS += -L../src -l$(LIBNAME) -lm -EXAMPLES = test open say spatial seq +EXAMPLES = test open say spatial seq pod all: $(EXAMPLES) diff --git a/examples/pod.c b/examples/pod.c new file mode 100644 index 0000000..b9f2218 --- /dev/null +++ b/examples/pod.c @@ -0,0 +1,312 @@ +#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_chamber_seq_speech(chamber, + drone, + seq, + 0, + &cur) < 0) { + goto error_seq; + } + + if (xas_drone_chamber_seq_speech(chamber, + 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; +} -- cgit v1.2.3