#include #include #include #include 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; ibank, 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_bass = xas_spatial_scene_add_synth(scene, (xas_spatial_coord){ location.x, location.y, location.z + 5.0 }, XAS_SYNTH_SQUARE)) == NULL) { goto error_spatial_scene_add_synth; } 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; } xas_synth_set_frequency(chamber->synth_bass->ctx, XAS_DRONE_CHAMBER_BASS_FREQUENCY); xas_synth_start(chamber->synth_bass->ctx); xas_synth_start(chamber->synth_l->ctx); xas_synth_start(chamber->synth_r->ctx); 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_seq_intervals(xas_drone_chamber *chamber, xas_drone_chamber_interval *intervals, xas_seq *seq, size_t count, struct timeval *now) { size_t i; for (i=0; itv_sec, .tv_usec = now->tv_usec }; if (xas_seq_add_set_frequency(seq, chamber->synth_l, *now, intervals[i].freq_l) < 0) { goto error_seq_add; } if (xas_seq_add_set_synth_type(seq, chamber->synth_l, *now, intervals[i].type_l) < 0) { goto error_seq_add; } if (xas_seq_add_set_frequency(seq, chamber->synth_r, *now, intervals[i].freq_r) < 0) { goto error_seq_add; } if (xas_seq_add_set_synth_type(seq, chamber->synth_r, *now, intervals[i].type_r) < 0) { goto error_seq_add; } timeradd(&cur, &intervals[i].duration, now); } return 0; error_seq_add: return -1; } int xas_drone_chamber_seq_speech(xas_drone_chamber *chamber, xas_drone *drone, xas_seq *seq, size_t speech_part, struct timeval *now) { struct timeval duration, tmp; if (xas_seq_add_set_bank(seq, drone->obj, *now, speech_part) < 0) { goto error_xas_seq_add; } if (xas_seq_add_event_on(seq, drone->obj, *now) < 0) { goto error_xas_seq_add; } xas_bank_entry_duration(drone->bank, speech_part, &duration); timeradd(now, &duration, &tmp); now->tv_sec = tmp.tv_sec; now->tv_usec = tmp.tv_usec; return 0; error_xas_seq_add: return -1; } static void max_speech_duration(xas_drone_chamber *chamber, struct timeval *max) { size_t i; for (i=0; idrone_count; i++) { xas_drone *drone = chamber->drones[i]; xas_bank_player *player = (xas_bank_player *)drone->obj->ctx; struct timeval duration; xas_bank_entry_duration(drone->bank, player->entry, &duration); if (timercmp(&duration, max, >)) { duration.tv_sec = max->tv_sec; duration.tv_usec = max->tv_usec; } } } int xas_drone_chamber_seq_chorus(xas_drone_chamber *chamber, xas_seq *seq, size_t speech_part, struct timeval *now) { struct timeval duration, tmp, delay = { 0, 500000 }; size_t i; max_speech_duration(chamber, &duration); 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) { goto error_seq_add; } if (xas_seq_add_event_on(seq, drone->obj, *now) < 0) { goto error_seq_add; } } timeradd(now, &duration, &tmp); timeradd(&tmp, &delay, now); return 0; error_seq_add: return -1; }