From d685f7a7c3f1abcc402e1ac8b808f2ccd16708ad Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Thu, 17 Mar 2022 11:44:36 -0400 Subject: Refactor to allow sequencing events on drones Changes: * Consolidate xas_drone_vox into xas_drone * Refactor xas_drone to no longer be centered around spatial objects for its vocalisations * Add a two-tone beep system to drones to allow beeping according to mood * Consolidate head-oriented sound effects into a single spatial object within drones * Implement ability to add a mixer to a spatial scene * Allow setting spatial coordinates for objects generically; remove code from src/spatial.c for doing this specifically --- src/drone.c | 290 +++++++++++++++++++++++++++++++++++++++++----------------- src/seq.c | 44 ++++----- src/spatial.c | 19 ++-- 3 files changed, 240 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/drone.c b/src/drone.c index 096507f..fcd73ca 100644 --- a/src/drone.c +++ b/src/drone.c @@ -7,11 +7,97 @@ #include #include +static inline int drone_beep(xas_drone *drone) { + struct { + size_t a, b; + enum xas_synth_type b_type; + } freqs[6] = { + { 400, 0, XAS_SYNTH_SINE }, + { 600, 0, XAS_SYNTH_SINE }, + { 800, 0, XAS_SYNTH_SINE }, + { 300, 0, XAS_SYNTH_SINE }, + { 300, 200, XAS_SYNTH_SQUARE }, + { 400, 600, XAS_SYNTH_SAWTOOTH } + }; + + switch (drone->mood) { + case XAS_DRONE_MOOD_NEUTRAL: + case XAS_DRONE_MOOD_HAPPY: + case XAS_DRONE_MOOD_FLIRTY: + case XAS_DRONE_MOOD_SAD: + case XAS_DRONE_MOOD_ANGRY: + case XAS_DRONE_MOOD_DISTRESSED: + xas_synth_set_frequency(drone->beep_a, freqs[drone->mood].a); + xas_synth_set_frequency(drone->beep_b, freqs[drone->mood].b); + xas_synth_set_type( drone->beep_b, freqs[drone->mood].b_type); + + break; + } + + return 0; +} + +static int drone_start(xas_drone *drone, size_t index) { + switch (index) { + case XAS_DRONE_INDEX_BANK: + return xas_bank_player_start(drone->player); + + case XAS_DRONE_INDEX_BEEP: + return drone_beep(drone); + + default: + break; + } + + return 0; +} + +static int drone_stop(xas_drone *drone, size_t index) { + switch (index) { + case XAS_DRONE_INDEX_BANK: + return xas_bank_player_stop(drone->player); + + case XAS_DRONE_INDEX_BEEP: + xas_synth_stop(drone->beep_a); + xas_synth_stop(drone->beep_b); + + break; + } + + return 0; +} + +static int drone_set_entry(xas_drone *drone, size_t index, size_t entry) { + switch (index) { + case XAS_DRONE_INDEX_BANK: + return xas_bank_player_set_entry(drone->player, entry); + + default: + break; + } + + return 0; +} + +static int drone_set_flags(xas_drone *drone, int flags) { + return xas_bank_player_set_flags(drone->player, flags); +} + +static xas_object_call_table call_table = { + .start = (xas_object_start_callback)drone_start, + .stop = (xas_object_stop_callback)drone_stop, + .set_entry = (xas_object_set_entry_callback)drone_set_entry, + .set_flags = (xas_object_set_flags_callback)drone_set_flags +}; + xas_drone *xas_drone_new(xas_spatial_scene *scene, xas_spatial_coord position, size_t bank_entry_size, size_t bank_entry_count) { xas_drone *drone; + xas_object *objects[3]; + + int i; if ((drone = malloc(sizeof(*drone))) == NULL) { goto error_malloc_drone; @@ -23,17 +109,85 @@ xas_drone *xas_drone_new(xas_spatial_scene *scene, goto error_bank_new; } - if ((drone->obj = xas_spatial_scene_add_bank_player(scene, - position, - drone->bank)) == NULL) { - goto error_spatial_scene_add_bank_player; + if ((drone->sfx = xas_bank_new(scene->format, + XAS_DRONE_SFX_BANK_SIZE, + XAS_DRONE_SFX_BANK_ENTRIES)) == NULL) { + goto error_bank_new_sfx; + } + + if ((drone->vox = xas_vox_new(scene->format, + XAS_DRONE_VOX_BUFFER_SIZE, + XAS_DRONE_VOX_TEXT2WAVE_PATH)) == NULL) { + goto error_vox_new; + } + + if ((drone->player = xas_bank_player_new(drone->bank)) == NULL) { + goto error_bank_player_new; + } + + if ((drone->beep_a = xas_synth_new(scene->format, + XAS_DRONE_BEEP_BUFFER_SIZE, + XAS_SYNTH_SINE)) == NULL) { + goto error_synth_new_a; } + if ((drone->beep_b = xas_synth_new(scene->format, + XAS_DRONE_BEEP_BUFFER_SIZE, + XAS_SYNTH_SINE)) == NULL) { + goto error_synth_new_b; + } + + if ((drone->mixer = xas_mixer_new(xas_audio_format_mono(scene->format), + XAS_DRONE_MIXER_BUFFER_SIZE)) == NULL) { + goto error_mixer_new; + } + + objects[0] = &drone->player->obj; + objects[1] = &drone->beep_a->obj; + objects[2] = &drone->beep_b->obj; + + for (i=0; i<3; i++) { + if ((xas_mixer_object_add(drone->mixer, + objects[i], + XAS_DRONE_MIXER_DEFAULT_GAIN, + XAS_DRONE_MIXER_DEFAULT_PAN)) == NULL) { + goto error_mixer_object_add; + } + } + + if ((drone->head = xas_spatial_scene_add_mixer(scene, + position, + drone->mixer)) == NULL) { + goto error_spatial_scene_add_mixer; + } + + drone->obj.table = &call_table; + + drone->mood = XAS_DRONE_MOOD_NEUTRAL; drone->scene = scene; return drone; -error_spatial_scene_add_bank_player: +error_spatial_scene_add_mixer: +error_mixer_object_add: + xas_mixer_destroy(drone->mixer); + +error_mixer_new: + xas_synth_destroy(drone->beep_b); + +error_synth_new_b: + xas_synth_destroy(drone->beep_a); + +error_synth_new_a: + xas_vox_destroy(drone->vox); + +error_vox_new: + xas_bank_player_destroy(drone->player); + +error_bank_player_new: + xas_bank_destroy(drone->sfx); + +error_bank_new_sfx: xas_bank_destroy(drone->bank); error_bank_new: @@ -44,6 +198,12 @@ error_malloc_drone: } void xas_drone_destroy(xas_drone *drone) { + xas_mixer_destroy(drone->mixer); + xas_synth_destroy(drone->beep_b); + xas_synth_destroy(drone->beep_a); + xas_bank_player_destroy(drone->player); + xas_vox_destroy(drone->vox); + xas_bank_destroy(drone->sfx); xas_bank_destroy(drone->bank); free(drone); @@ -62,7 +222,7 @@ ssize_t xas_drone_sample_record(xas_drone *drone, size_t sample_index, size_t sample_len) { if (sample_index >= drone->bank->entry_count - || sample_len > drone->bank->entry_size) { + || sample_len > drone->bank->entry_size) { errno = EINVAL; goto error_invalid; @@ -113,7 +273,6 @@ int xas_drone_speech_import(xas_drone *drone, size_t sample_index, size_t sample_count, const char **speech_lines) { - xas_drone_vox *vox; size_t i, o; if (sample_index + sample_count - 1 >= drone->bank->entry_count) { @@ -122,38 +281,26 @@ int xas_drone_speech_import(xas_drone *drone, goto error_invalid; } - if ((vox = xas_drone_vox_new(drone)) == NULL) { - goto error_vox_new; - } - if (voice) { - xas_drone_vox_set_voice(vox, voice); + xas_vox_set_voice(drone->vox, voice); } - xas_drone_vox_set_speed(vox, speed); + xas_drone_vox_set_speed(drone, speed); for (i=0, o=sample_index; ivox, speech_lines[i]) < 0) { goto error_vox_say; } - if (xas_drone_vox_save(vox, o) < 0) { + if (xas_drone_vox_save(drone, o) < 0) { goto error_vox_save; } - - if (xas_vox_stop(vox->obj) < 0) { - goto error_vox_stop_obj; - } } - xas_drone_vox_destroy(vox); - return 0; -error_vox_stop_obj: error_vox_save: error_vox_say: -error_vox_new: error_invalid: return -1; } @@ -165,16 +312,18 @@ int xas_drone_seq_sample(xas_drone *drone, struct timeval duration, tmp; - if (xas_seq_add_set_bank(seq, - drone->obj, - *now, - speech_part) < 0) { + if (xas_seq_add_set_bank_entry(seq, + &drone->obj, + *now, + XAS_DRONE_INDEX_BANK, + speech_part) < 0) { goto error_xas_seq_add; } if (xas_seq_add_event_on(seq, - drone->obj, - *now) < 0) { + &drone->obj, + *now, + XAS_DRONE_INDEX_BANK) < 0) { goto error_xas_seq_add; } @@ -193,83 +342,54 @@ error_xas_seq_add: return -1; } -xas_drone_vox *xas_drone_vox_new(xas_drone *drone) { - xas_drone_vox *vox; - - if ((vox = malloc(sizeof(*vox))) == NULL) { - goto error_malloc_vox; - } - - if ((vox->obj = xas_vox_new(drone->scene->format, - XAS_DRONE_VOX_BUFFER_SIZE, - XAS_DRONE_VOX_TEXT2WAVE_PATH)) == NULL) { - goto error_vox_new; - } - - vox->drone = drone; - - return vox; - -error_vox_new: - free(vox); - -error_malloc_vox: - return NULL; -} - -void xas_drone_vox_destroy(xas_drone_vox *vox) { - xas_vox_destroy(vox->obj); - free(vox); +int xas_drone_vox_set_voice(xas_drone *drone, const char *voice) { + return xas_vox_set_voice(drone->vox, voice); } -int xas_drone_vox_set_voice(xas_drone_vox *vox, const char *voice) { - return xas_vox_set_voice(vox->obj, voice); -} - -int xas_drone_vox_set_speed(xas_drone_vox *vox, float speed) { - return xas_vox_set_parameter_float(vox->obj, +int xas_drone_vox_set_speed(xas_drone *drone, float speed) { + return xas_vox_set_parameter_float(drone->vox, "Duration_Stretch", 1.0f / speed); } -int xas_drone_vox_say(xas_drone_vox *vox, const char *text) { - return xas_vox_say(vox->obj, text); +int xas_drone_vox_say(xas_drone *drone, const char *text) { + return xas_vox_say(drone->vox, text); } -int xas_drone_vox_vsayf(xas_drone_vox *vox, +int xas_drone_vox_vsayf(xas_drone *drone, const char *format, va_list args) { - return xas_vox_vsayf(vox->obj, format, args); + return xas_vox_vsayf(drone->vox, format, args); } -int xas_drone_vox_sayf(xas_drone_vox *vox, const char *format, ...) { +int xas_drone_vox_sayf(xas_drone *drone, const char *format, ...) { int ret; va_list args; va_start(args, format); - ret = xas_vox_vsayf(vox->obj, format, args); + ret = xas_vox_vsayf(drone->vox, format, args); va_end(args); return ret; } -int xas_drone_vox_save(xas_drone_vox *vox, size_t sample_index) { +int xas_drone_vox_save(xas_drone *drone, size_t sample_index) { xas_audio_stream *source; - if ((source = xas_vox_stream_new(vox->obj)) == NULL) { + if ((source = xas_vox_stream_new(drone->vox)) == NULL) { goto error_vox_stream_new; } - if (xas_vox_generate(vox->obj) < 0) { + if (xas_vox_generate(drone->vox) < 0) { goto error_vox_generate; } - if (xas_bank_record(vox->drone->bank, + if (xas_bank_record(drone->bank, source, sample_index, - vox->drone->bank->entry_size) < 0) { + drone->bank->entry_size) < 0) { goto error_bank_record; } @@ -367,7 +487,7 @@ void xas_drone_chamber_set_drone_gain(xas_drone_chamber *chamber, float gain) { for (i=0; idrone_count; i++) { xas_drone *drone = chamber->drones[i]; - xas_object_set_gain(drone->obj->ctx, gain); + xas_object_set_gain(&drone->mixer->obj, gain); } } @@ -412,28 +532,28 @@ int xas_drone_chamber_seq_intervals(xas_drone_chamber *chamber, }; if (xas_seq_add_set_frequency(seq, - chamber->synth_l, + chamber->synth_l->ctx, *now, intervals[i].freq_l) < 0) { goto error_seq_add; } if (xas_seq_add_set_synth_type(seq, - chamber->synth_l, + chamber->synth_l->ctx, *now, intervals[i].type_l) < 0) { goto error_seq_add; } if (xas_seq_add_set_frequency(seq, - chamber->synth_r, + chamber->synth_r->ctx, *now, intervals[i].freq_r) < 0) { goto error_seq_add; } if (xas_seq_add_set_synth_type(seq, - chamber->synth_r, + chamber->synth_r->ctx, *now, intervals[i].type_r) < 0) { goto error_seq_add; @@ -487,14 +607,18 @@ int xas_drone_chamber_seq_chorus(xas_drone_chamber *chamber, for (i=0; idrone_count; i++) { xas_drone *drone = chamber->drones[i]; - if (xas_seq_add_set_bank(seq, - drone->obj, - *now, - speech_part) < 0) { + if (xas_seq_add_set_bank_entry(seq, + &drone->obj, + *now, + XAS_DRONE_INDEX_BANK, + speech_part) < 0) { goto error_seq_add; } - if (xas_seq_add_event_on(seq, drone->obj, *now) < 0) { + if (xas_seq_add_event_on(seq, + &drone->obj, + *now, + XAS_DRONE_INDEX_BANK) < 0) { goto error_seq_add; } } diff --git a/src/seq.c b/src/seq.c index 63be43f..d61e391 100644 --- a/src/seq.c +++ b/src/seq.c @@ -157,7 +157,7 @@ static void event_sort(xas_seq *seq) { } int xas_seq_add_event_off(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, size_t index) { xas_seq_event *ev; @@ -185,7 +185,7 @@ error_malloc_ev: } int xas_seq_add_event_on(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, size_t index) { xas_seq_event *ev; @@ -213,7 +213,7 @@ error_malloc_ev: } int xas_seq_add_set_position(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, xas_spatial_coord point) { xas_seq_event *ev; @@ -241,7 +241,7 @@ error_malloc_ev: } int xas_seq_add_set_heading(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, xas_spatial_coord heading) { xas_seq_event *ev; @@ -269,7 +269,7 @@ error_malloc_ev: } int xas_seq_add_set_speed(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, float speed) { xas_seq_event *ev; @@ -297,7 +297,7 @@ error_malloc_ev: } int xas_seq_add_set_gain(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, float gain) { xas_seq_event *ev; @@ -325,7 +325,7 @@ error_malloc_ev: } int xas_seq_add_set_bank_entry(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, size_t index, size_t entry) { @@ -355,7 +355,7 @@ error_malloc_ev: } int xas_seq_add_set_player_flags(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, int flags) { xas_seq_event *ev; @@ -383,7 +383,7 @@ error_malloc_ev: } int xas_seq_add_set_synth_type(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, enum xas_synth_type type) { xas_seq_event *ev; @@ -411,7 +411,7 @@ error_malloc_ev: } int xas_seq_add_set_frequency(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, size_t frequency) { xas_seq_event *ev; @@ -439,7 +439,7 @@ error_malloc_ev: } int xas_seq_add_phrase(xas_seq *seq, - xas_spatial_object *object, + xas_object *object, struct timeval timestamp, const char *phrase) { xas_seq_event *ev; @@ -495,10 +495,10 @@ error_malloc_ev: static int event_trigger(xas_spatial_scene *scene, xas_seq_event *ev) { switch (ev->type) { case XAS_SEQ_EVENT_OFF: - return xas_object_stop(ev->object->ctx, ev->index); + return xas_object_stop(ev->object, ev->index); case XAS_SEQ_EVENT_ON: - return xas_object_start(ev->object->ctx, ev->index); + return xas_object_start(ev->object, ev->index); case XAS_SEQ_EVENT_SET_POSITION: xas_spatial_scene_position_object(scene, @@ -508,43 +508,43 @@ static int event_trigger(xas_spatial_scene *scene, xas_seq_event *ev) { break; case XAS_SEQ_EVENT_SET_HEADING: - ev->object->heading = ev->heading; + xas_object_set_heading(ev->object, ev->heading); break; case XAS_SEQ_EVENT_SET_SPEED: - ev->object->speed = ev->speed; + xas_object_set_speed(ev->object, ev->speed); break; case XAS_SEQ_EVENT_SET_GAIN: - xas_object_set_gain(ev->object->ctx, ev->gain); + xas_object_set_gain(ev->object, ev->gain); break; case XAS_SEQ_EVENT_SET_FREQUENCY: - xas_synth_set_frequency(ev->object->ctx, ev->frequency); + xas_object_set_freq(ev->object, ev->frequency); break; case XAS_SEQ_EVENT_SET_SYNTH_TYPE: - xas_synth_set_type(ev->object->ctx, ev->synth_type); + xas_synth_set_type((xas_synth *)ev->object, ev->synth_type); break; case XAS_SEQ_EVENT_SET_BANK_ENTRY: - xas_object_set_entry(ev->object->ctx, ev->index, ev->entry); + xas_object_set_entry(ev->object, ev->index, ev->entry); break; case XAS_SEQ_EVENT_SET_PLAYER_FLAGS: - xas_object_set_flags(ev->object->ctx, ev->flags); + xas_object_set_flags(ev->object, ev->flags); break; case XAS_SEQ_EVENT_SPEECH: - xas_vox_say(ev->object->ctx, ev->phrase); - xas_vox_generate(ev->object->ctx); + xas_vox_say((xas_vox *)ev->object, ev->phrase); + xas_vox_generate((xas_vox *)ev->object); break; diff --git a/src/spatial.c b/src/spatial.c index 0cc58e9..68c7d41 100644 --- a/src/spatial.c +++ b/src/spatial.c @@ -569,6 +569,15 @@ error_bank_player_new: return NULL; } +xas_spatial_object *xas_spatial_scene_add_mixer(xas_spatial_scene *scene, + xas_spatial_coord point, + xas_mixer *mixer) { + return xas_spatial_scene_add_object(scene, + point, + xas_mixer_output(mixer), + mixer); +} + xas_spatial_object *xas_spatial_scene_add_vox(xas_spatial_scene *scene, xas_spatial_coord point, const char *text2wave_path) { @@ -608,9 +617,9 @@ error_vox_new: } void xas_spatial_scene_position_object(xas_spatial_scene *scene, - xas_spatial_object *object, + xas_object *object, xas_spatial_coord point) { - object->point = point; + xas_object_set_point(object, point); object_update_delays(scene); } @@ -623,12 +632,6 @@ xas_audio_stream *xas_spatial_scene_stream_new(xas_spatial_scene *scene, buffer_size, scene); } -void xas_spatial_object_get_point(xas_spatial_object *object, - xas_spatial_coord *point) { - point->x = object->point.x; - point->y = object->point.y; - point->z = object->point.z; -} float xas_spatial_object_get_speed(xas_spatial_object *object) { return object->speed; -- cgit v1.2.3