summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorXANTRONIX Development2022-03-17 11:44:36 -0400
committerXANTRONIX Development2022-03-17 11:44:36 -0400
commitd685f7a7c3f1abcc402e1ac8b808f2ccd16708ad (patch)
tree49d9745d840f587ab5bf77ddf164491a53dd570e /src
parent89401de8a6caecc8c283081e7036ad7c0b5d6a92 (diff)
downloadxas-d685f7a7c3f1abcc402e1ac8b808f2ccd16708ad.tar.gz
xas-d685f7a7c3f1abcc402e1ac8b808f2ccd16708ad.tar.bz2
xas-d685f7a7c3f1abcc402e1ac8b808f2ccd16708ad.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/drone.c290
-rw-r--r--src/seq.c44
-rw-r--r--src/spatial.c19
3 files changed, 240 insertions, 113 deletions
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 <xas/vox.h>
#include <xas/drone.h>
+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; i<sample_count; i++, o++) {
- if (xas_drone_vox_say(vox, speech_lines[i]) < 0) {
+ if (xas_vox_say(drone->vox, 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; i<chamber->drone_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; i<chamber->drone_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;