#include #include #include #include #include #include #include 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; if ((drone = malloc(sizeof(*drone))) == NULL) { goto error_malloc_drone; } if ((drone->bank = xas_bank_new(scene->format, bank_entry_size, bank_entry_count)) == NULL) { 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; } drone->scene = scene; return drone; error_spatial_scene_add_bank_player: 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); } enum xas_drone_mood xas_drone_mood_get(xas_drone *drone) { return drone->mood; } void xas_drone_mood_set(xas_drone *drone, enum xas_drone_mood mood) { drone->mood = mood; } xas_spatial_object *xas_drone_get_spatial_object(xas_drone *drone) { return drone->obj; } ssize_t xas_drone_sample_record(xas_drone *drone, xas_audio_stream *source, size_t sample_index, size_t sample_len) { if (sample_index >= drone->bank->entry_count || sample_len > drone->bank->entry_size) { errno = EINVAL; goto error_invalid; } return xas_bank_record(drone->bank, source, sample_index, sample_len); return 0; error_invalid: return -1; } ssize_t xas_drone_sample_import(xas_drone *drone, const char *path, size_t sample_index) { ssize_t ret; xas_audio_stream *source; if ((source = xas_riff_open_file(path, O_RDONLY)) == NULL) { goto error_riff_open_file; } if ((ret = xas_drone_sample_record(drone, source, sample_index, drone->bank->entry_size)) < 0) { goto error_sample_record; } xas_audio_stream_destroy(source); return ret; error_sample_record: xas_audio_stream_destroy(source); error_riff_open_file: return -1; } int xas_drone_speech_import(xas_drone *drone, const char *voice, float speed, 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) { 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=sample_index; iobj) < 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; } int xas_drone_seq_sample(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; } 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_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, "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_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) { xas_audio_stream *source; if ((source = xas_vox_stream_new(vox->obj)) == NULL) { goto error_vox_stream_new; } if (xas_vox_generate(vox->obj) < 0) { goto error_vox_generate; } if (xas_bank_record(vox->drone->bank, source, sample_index, vox->drone->bank->entry_size) < 0) { goto error_bank_record; } xas_audio_stream_destroy(source); return 0; error_bank_record: error_vox_generate: xas_audio_stream_destroy(source); error_vox_stream_new: return -1; } 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_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->drones); free(chamber); } void xas_drone_chamber_insert_drone(xas_drone_chamber *chamber, xas_drone *drone, size_t index) { chamber->drones[index] = drone; } void xas_drone_chamber_set_drone_gain(xas_drone_chamber *chamber, float gain) { size_t i; for (i=0; idrone_count; i++) { xas_drone *drone = chamber->drones[i]; xas_object_set_gain(drone->obj->ctx, gain); } } void xas_drone_chamber_set_synth_gain(xas_drone_chamber *chamber, float gain) { xas_object_set_gain(chamber->synth_l->ctx, gain); xas_object_set_gain(chamber->synth_r->ctx, gain); } void xas_drone_chamber_set_bass_gain(xas_drone_chamber *chamber, float gain) { xas_object_set_gain(chamber->synth_bass->ctx, gain); } void xas_drone_chamber_bass_start(xas_drone_chamber *chamber) { xas_synth_start(chamber->synth_bass->ctx); } void xas_drone_chamber_bass_stop(xas_drone_chamber *chamber) { xas_synth_stop(chamber->synth_bass->ctx); } void xas_drone_chamber_bass_set_type(xas_drone_chamber *chamber, enum xas_synth_type type) { xas_synth_set_type(chamber->synth_bass->ctx, type); } void xas_drone_chamber_bass_set_frequency(xas_drone_chamber *chamber, size_t freq) { xas_synth_set_frequency(chamber->synth_bass->ctx, freq); } 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; } static void max_speech_duration(xas_drone_chamber *chamber, size_t speech_part, struct timeval *max) { size_t i; max->tv_sec = 0; max->tv_usec = 0; for (i=0; idrone_count; i++) { xas_drone *drone = chamber->drones[i]; struct timeval duration; xas_bank_entry_duration(drone->bank, speech_part, &duration); if (timercmp(max, &duration, <)) { max->tv_sec = duration.tv_sec; max->tv_usec = duration.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, speech_part, &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; }