diff options
| -rw-r--r-- | include/xas/drone.h | 88 | ||||
| -rw-r--r-- | src/Makefile | 4 | ||||
| -rw-r--r-- | src/drone.c | 240 | 
3 files changed, 330 insertions, 2 deletions
| diff --git a/include/xas/drone.h b/include/xas/drone.h new file mode 100644 index 0000000..d77834c --- /dev/null +++ b/include/xas/drone.h @@ -0,0 +1,88 @@ +#ifndef _XAS_DRONE_H +#define _XAS_DRONE_H + +#include <sys/time.h> + +#include <xas/spatial.h> +#include <xas/seq.h> + +enum xas_drone_chamber_event_type { +    XAS_DRONE_CHAMBER_EVENT_NONE, +    XAS_DRONE_CHAMBER_EVENT_SYNTH, +    XAS_DRONE_CHAMBER_EVENT_DRONE_SPEECH +}; + +typedef struct _xas_drone xas_drone; + +struct _xas_drone { +    xas_bank *bank; +    xas_spatial_scene *scene; +    xas_spatial_object *obj; +    float speech_speed; + +    const char **speech_lines; + +    xas_drone *next; +}; + +typedef struct _xas_drone_chamber_interval { +    struct timeval duration; + +    size_t freq_l, +           freq_r; + +    enum xas_synth_type type_l, +                          type_r; +} xas_drone_chamber_interval; + +typedef struct _xas_drone_chamber_speech { +    size_t drone_index, +           speech_line; +} xas_drone_chamber_speech; + +typedef struct _xas_drone_chamber_event { +    enum xas_drone_chamber_event_type type; + +    union { +        xas_drone_chamber_interval interval; +        xas_drone_chamber_speech   speech; +    }; +} xas_drone_chamber_event; + +typedef struct _xas_drone_chamber { +    xas_spatial_scene *scene; +    xas_drone **drones; +    size_t drone_count; + +    xas_spatial_object *synth_l, +                         *synth_r; +} xas_drone_chamber; + +xas_drone *xas_drone_new(xas_spatial_scene *scene, +                             xas_spatial_coord position, +                             float speech_speed, +                             size_t speech_sample_count, +                             size_t speech_line_count, +                             const char **speech_lines); + +void xas_drone_destroy(xas_drone *drone); + +xas_spatial_object *xas_drone_get_spatial_object(xas_drone *drone); + +xas_drone_chamber *xas_drone_chamber_new(xas_spatial_scene *scene, +                                             xas_spatial_coord location, +                                             size_t drone_count); + +void xas_drone_chamber_destroy(xas_drone_chamber *chamber); + +void xas_drone_chamber_insert_drone(xas_drone_chamber *chamber, +                                      xas_drone *drone, +                                      size_t index); + +int xas_drone_chamber_event_seq(xas_drone_chamber *chamber, +                                  xas_drone_chamber_event *ev, +                                  xas_seq *seq, +                                  int advance, +                                  struct timeval *now); + +#endif /* _XAS_DRONE_H */ diff --git a/src/Makefile b/src/Makefile index 099c3ee..c4609c8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,10 +8,10 @@ CFLAGS		+= -I$(INCLUDE_PATH)  LDFLAGS		+=  HEADERS		= audio.h riff.h mixer.h object.h synth.h vox.h bank.h \ -		  spatial.h seq.h +		  spatial.h seq.h drone.h  OBJS		= audio.o riff.o mixer.o object.o synth.o vox.o bank.o \ -		  spatial.o seq.o +		  spatial.o seq.o drone.o  VERSION_MAJOR	= 0  VERSION_MINOR	= 0.1 diff --git a/src/drone.c b/src/drone.c new file mode 100644 index 0000000..19fccba --- /dev/null +++ b/src/drone.c @@ -0,0 +1,240 @@ +#include <stdlib.h> +#include <string.h> + +#include <xas/vox.h> +#include <xas/drone.h> + +static size_t DEFAULT_BUFFER_SIZE = 735; + +static int record_speech_sample(xas_bank *bank, +                                size_t entry_index, +                                float speed, +                                const char *text) { +    xas_vox *vox; +    xas_audio_stream *source; + +    if ((vox = xas_vox_new(bank->format, +                             DEFAULT_BUFFER_SIZE, +                             "/usr/bin/text2wave")) == NULL) { +        goto error_vox_new; +    } + +    if ((source = xas_vox_stream_new(vox)) == NULL) { +        goto error_vox_stream_new; +    } + +    xas_vox_set_voice(vox, "voice_cmu_us_slt_cg"); +    xas_vox_set_parameter_float(vox, "Duration_Stretch", speed); +    xas_vox_say(vox, text); +    xas_vox_generate(vox); + +    if (xas_bank_record(bank, source, entry_index, bank->entry_size) < 0) { +        goto error_bank_record; +    } + +    xas_audio_stream_destroy(source); +    xas_vox_destroy(vox); + +    return 0; + +error_bank_record: +    xas_audio_stream_destroy(source); + +error_vox_stream_new: +    xas_vox_destroy(vox); + +error_vox_new: +    return -1; +} + +xas_drone *xas_drone_new(xas_spatial_scene *scene, +                             xas_spatial_coord position, +                             float speech_speed, +                             size_t speech_sample_count, +                             size_t speech_line_count, +                             const char **speech_lines) { +    xas_drone *drone; + +    size_t i; + +    if ((drone = malloc(sizeof(*drone))) == NULL) { +        goto error_malloc_drone; +    } + +    if ((drone->bank = xas_bank_new(scene->format, +                                      speech_sample_count, +                                      speech_line_count)) == NULL) { +        goto error_bank_new; +    } + +    for (i=0; i<speech_line_count; i++) { +        if (record_speech_sample(drone->bank, +                                 i, +                                 speech_speed, +                                 speech_lines[i]) < 0) { +            goto error_record_speech_sample; +        } +    } + +    if ((drone->obj = xas_spatial_scene_add_bank_player(scene, +                                                          position, +                                                          drone->bank)) == NULL) { +        goto error_spatial_scene_add_bank_player; +    } + +    return drone; + +error_spatial_scene_add_bank_player: +error_record_speech_sample: +    xas_bank_destroy(drone->bank); + +error_bank_new: +    free(drone); + +error_malloc_drone: +    return NULL; +} + +void xas_drone_destroy(xas_drone *drone) { +    xas_bank_destroy(drone->bank); + +    free(drone); +} + +xas_spatial_object *xas_drone_get_spatial_object(xas_drone *drone) { +    return drone->obj; +} + +xas_drone_chamber *xas_drone_chamber_new(xas_spatial_scene *scene, +                                             xas_spatial_coord location, +                                             size_t drone_count) { +    xas_drone_chamber *chamber; + +    size_t total = drone_count * sizeof(xas_drone *); + +    if ((chamber = malloc(sizeof(*chamber))) == NULL) { +        goto error_malloc_chamber; +    } + +    if ((chamber->drones = malloc(total)) == NULL) { +        goto error_malloc_chamber_drones; +    } + +    if ((chamber->synth_l = xas_spatial_scene_add_synth(scene, +                                                          (xas_spatial_coord){ +                                                              location.x - 5.0, +                                                              location.y, +                                                              location.z +                                                          }, +                                                          XAS_SYNTH_SINE)) == NULL) { +        goto error_spatial_scene_add_synth; +    } + +    if ((chamber->synth_r = xas_spatial_scene_add_synth(scene, +                                                          (xas_spatial_coord){ +                                                              location.x + 5.0, +                                                              location.y, +                                                              location.z +                                                          }, +                                                          XAS_SYNTH_SINE)) == NULL) { +        goto error_spatial_scene_add_synth; +    } + +    chamber->drone_count = drone_count; + +    memset(chamber->drones, '\0', total); + +    return chamber; + +error_spatial_scene_add_synth: +error_malloc_chamber_drones: +    free(chamber); + +error_malloc_chamber: +    return NULL; +} + +void xas_drone_chamber_destroy(xas_drone_chamber *chamber) { +    free(chamber); +} + +void xas_drone_chamber_insert_drone(xas_drone_chamber *chamber, +                                      xas_drone *drone, +                                      size_t index) { +    chamber->drones[index] = drone; +} + +int xas_drone_chamber_event_seq(xas_drone_chamber *chamber, +                                  xas_drone_chamber_event *ev, +                                  xas_seq *seq, +                                  int advance, +                                  struct timeval *now) { +    struct timeval tmp = *now; + +    switch (ev->type) { +        case XAS_DRONE_CHAMBER_EVENT_NONE: +            return 0; + +        case XAS_DRONE_CHAMBER_EVENT_SYNTH: +            if (xas_seq_add_set_frequency(seq, +                                            chamber->synth_l, +                                            *now, +                                            ev->interval.freq_l) < 0) { +                goto error_seq_add; +            } + +            if (xas_seq_add_set_synth_type(seq, +                                             chamber->synth_l, +                                             *now, +                                             ev->interval.type_l) < 0) { +                goto error_seq_add; +            } + +            if (xas_seq_add_set_frequency(seq, +                                            chamber->synth_r, +                                            *now, +                                            ev->interval.freq_r) < 0) { +                goto error_seq_add; +            } + +            if (xas_seq_add_set_synth_type(seq, +                                             chamber->synth_r, +                                             *now, +                                             ev->interval.type_r) < 0) { +                goto error_seq_add; +            } + +            if (advance) { +                timeradd(&tmp, &ev->interval.duration, now); +            } + +            break; + +        case XAS_DRONE_CHAMBER_EVENT_DRONE_SPEECH: +            struct timeval duration, +                           delay = { 0, 5000000 }; + +            xas_drone *drone = chamber->drones[ev->speech.drone_index]; +            size_t slot = ev->speech.speech_line; + +            xas_bank_entry_duration(drone->bank, slot, &duration); + +            if (xas_seq_add_event_on(seq, +                                       drone->obj, +                                       *now) < 0) { +                goto error_seq_add; +            } + +            if (advance) { +                timeradd(now, &delay, &tmp); +                timeradd(&tmp, &duration, now); +            } + +            break; +    } + +    return 0; + +error_seq_add: +    return -1; +} | 
 
    