diff options
| -rw-r--r-- | examples/seq.c | 18 | ||||
| -rw-r--r-- | include/xas/drone.h | 66 | ||||
| -rw-r--r-- | src/drone.c | 220 | 
3 files changed, 226 insertions, 78 deletions
| diff --git a/examples/seq.c b/examples/seq.c index 601e46a..ab8da55 100644 --- a/examples/seq.c +++ b/examples/seq.c @@ -195,19 +195,15 @@ int main(int argc, char **argv) {      if ((drone = xas_drone_new(scene,                                   (xas_spatial_coord){ 0.0, 0.0, -1.0 }, -                                 1.3f,                                   2646000, -                                 4, -                                 drone_lines)) == NULL) { +                                 4)) == NULL) {          goto error_drone_new;      }      if ((nurse = xas_drone_new(scene,                                   (xas_spatial_coord){ 1.0, 0.0, 0.0 }, -                                 1.0f,                                   2646000, -                                 4, -                                 nurse_lines)) == NULL) { +                                 4)) == NULL) {          goto error_drone_new_nurse;      } @@ -217,6 +213,14 @@ int main(int argc, char **argv) {          goto error_drone_chamber_new;      } +    if (xas_drone_speech_import(drone, NULL, 0.75f, 0, 4, drone_lines) < 0) { +        goto error_drone_speech_import; +    } + +    if (xas_drone_speech_import(nurse, NULL, 1.0f, 0, 4, nurse_lines) < 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); @@ -291,6 +295,8 @@ int main(int argc, char **argv) {      return EX_OK;  error_seq: +error_drone_speech_import_nurse: +error_drone_speech_import:      xas_drone_chamber_destroy(chamber);  error_drone_chamber_new: diff --git a/include/xas/drone.h b/include/xas/drone.h index b790cc5..d7dc4c0 100644 --- a/include/xas/drone.h +++ b/include/xas/drone.h @@ -1,24 +1,37 @@  #ifndef _XAS_DRONE_H  #define _XAS_DRONE_H +#include <stdarg.h>  #include <sys/time.h>  #include <xas/spatial.h> +#include <xas/vox.h>  #include <xas/seq.h> +#define XAS_DRONE_VOX_BUFFER_SIZE    735 +#define XAS_DRONE_VOX_TEXT2WAVE_PATH "/usr/bin/text2wave" + +#define XAS_DRONE_VOX_DEFAULT_SPEED  1.0f +#define XAS_DRONE_VOX_DEFAULT_VOICE  "voice_cmu_us_slt_cg" +  #define XAS_DRONE_CHAMBER_BASS_FREQUENCY 20 /* Hz */  #define XAS_DRONE_CHAMBER_BASS_TYPE      XAS_SYNTH_SQUARE -typedef struct _xas_drone xas_drone; - -struct _xas_drone { +typedef struct _xas_drone {      xas_bank *bank;      xas_spatial_scene *scene;      xas_spatial_object *obj; -    float speech_speed; -    const char **speech_lines; -}; +} xas_drone; + +typedef struct _xas_drone_vox { +    xas_drone *drone; +    xas_vox *obj; +    xas_audio_stream *source; + +    const char *voice; +    float speed; +} xas_drone_vox;  typedef struct _xas_drone_chamber_interval {      struct timeval duration; @@ -36,7 +49,6 @@ typedef struct _xas_drone_chamber_speech {  } xas_drone_chamber_speech;  typedef struct _xas_drone_chamber { -    xas_spatial_scene *scene;      xas_drone **drones;      size_t drone_count; @@ -45,17 +57,49 @@ typedef struct _xas_drone_chamber {                           *synth_r;  } xas_drone_chamber; +/* + * Methods for individual drones + */  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); +                             size_t bank_entry_size, +                             size_t bank_entry_count);  void xas_drone_destroy(xas_drone *drone);  xas_spatial_object *xas_drone_get_spatial_object(xas_drone *drone); +int xas_drone_speech_import(xas_drone *drone, +                              const char *voice, +                              float speed, +                              size_t speech_sample_first, +                              size_t speech_sample_count, +                              const char **speech_lines); + +/* + * Methods for drone vocalisations + */ +xas_drone_vox *xas_drone_vox_new(xas_drone *drone); + +void xas_drone_vox_destroy(xas_drone_vox *vox); + +void xas_drone_vox_set_voice(xas_drone_vox *vox, const char *voice); + +void xas_drone_vox_set_speed(xas_drone_vox *vox, float speed); + +int xas_drone_vox_vsayf(xas_drone_vox *vox, +                          const char *format, +                          va_list args); + +int xas_drone_vox_sayf(xas_drone_vox *vox, const char *format, ...); + +int xas_drone_vox_say(xas_drone_vox *vox, const char *text); + +int xas_drone_vox_save(xas_drone_vox *vox, size_t sample_index); + +/* + * Drone conversion chamber methods + */  xas_drone_chamber *xas_drone_chamber_new(xas_spatial_scene *scene,                                               xas_spatial_coord location,                                               size_t drone_count); diff --git a/src/drone.c b/src/drone.c index dc8c084..e4a0cb7 100644 --- a/src/drone.c +++ b/src/drone.c @@ -1,91 +1,37 @@  #include <stdlib.h>  #include <string.h> +#include <errno.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) { +                             size_t bank_entry_size, +                             size_t bank_entry_count) {      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) { +                                      bank_entry_size, +                                      bank_entry_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;      } +    drone->scene = scene; +      return drone;  error_spatial_scene_add_bank_player: -error_record_speech_sample:      xas_bank_destroy(drone->bank);  error_bank_new: @@ -105,6 +51,158 @@ xas_spatial_object *xas_drone_get_spatial_object(xas_drone *drone) {      return drone->obj;  } +int xas_drone_speech_import(xas_drone *drone, +                              const char *voice, +                              float speed, +                              size_t speech_sample_first, +                              size_t speech_sample_count, +                              const char **speech_lines) { +    xas_drone_vox *vox; +    size_t i, o; + +    if (speech_sample_first + speech_sample_count - 1 >= drone->bank->entry_count) { +        errno = EINVAL; + +        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_drone_vox_set_speed(vox, speed); + +    for (i=0, o=speech_sample_first; i<speech_sample_count; i++, o++) { +        if (xas_drone_vox_say(vox, speech_lines[i]) < 0) { +            goto error_vox_say; +        } + +        if (xas_drone_vox_save(vox, 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; +} + +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; +    } + +    if ((vox->source = xas_vox_stream_new(vox->obj)) == NULL) { +        goto error_vox_stream_new; +    } + +    vox->drone = drone; +    vox->voice = XAS_DRONE_VOX_DEFAULT_VOICE; +    vox->speed = XAS_DRONE_VOX_DEFAULT_SPEED; + +    return vox; + +error_vox_stream_new: +    xas_vox_destroy(vox->obj); + +error_vox_new: +    free(vox); + +error_malloc_vox: +    return NULL; +} + +void xas_drone_vox_destroy(xas_drone_vox *vox) { +    xas_audio_stream_destroy(vox->source); +    xas_vox_destroy(vox->obj); +    free(vox); +} + +void xas_drone_vox_set_voice(xas_drone_vox *vox, const char *voice) { +    vox->voice = voice; +} + +void xas_drone_vox_set_speed(xas_drone_vox *vox, float speed) { +    vox->speed = speed; +} + +int xas_drone_vox_say(xas_drone_vox *vox, const char *text) { +    return xas_vox_say(vox->obj, text); +} + +int xas_drone_vox_vsayf(xas_drone_vox *vox, +                          const char *format, +                          va_list args) { +    return xas_vox_vsayf(vox->obj, format, args); +} + +int xas_drone_vox_sayf(xas_drone_vox *vox, const char *format, ...) { +    int ret; +    va_list args; + +    va_start(args, format); + +    ret = xas_vox_vsayf(vox->obj, format, args); + +    va_end(args); + +    return ret; +} + +int xas_drone_vox_save(xas_drone_vox *vox, size_t sample_index) { +    if (vox->voice && xas_vox_set_voice(vox->obj, vox->voice) < 0) { +        goto error_vox_set_voice; +    } + +    if (xas_vox_set_parameter_float(vox->obj, +                                      "Duration_Stretch", +                                      1.0f / vox->speed) < 0) { +        goto error_vox_set_parameter_float; +    } + +    if (xas_vox_generate(vox->obj) < 0) { +        goto error_vox_generate; +    } + +    if (xas_bank_record(vox->drone->bank, +                          vox->source, +                          sample_index, +                          vox->drone->bank->entry_size) < 0) { +        goto error_bank_record; +    } + +    return 0; + +error_bank_record: +error_vox_generate: +error_vox_set_parameter_float: +error_vox_set_voice: +    return -1; +} +  xas_drone_chamber *xas_drone_chamber_new(xas_spatial_scene *scene,                                               xas_spatial_coord location,                                               size_t drone_count) { | 
 
    