summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorXANTRONIX Development2022-03-13 17:16:26 -0400
committerXANTRONIX Development2022-03-13 17:16:26 -0400
commit7b8375ee2026d42b5444f8ae0e7b98e272e87d69 (patch)
tree38382c0062f095c9efcd0d6bc29e1b5a5e6ac2f1 /src
parent98de824b0eb038d37f62f5317a367b2bfbd38b9d (diff)
downloadxas-7b8375ee2026d42b5444f8ae0e7b98e272e87d69.tar.gz
xas-7b8375ee2026d42b5444f8ae0e7b98e272e87d69.tar.bz2
xas-7b8375ee2026d42b5444f8ae0e7b98e272e87d69.zip
Refactor drone speech modules
Changes: * Implement xas_drone_vox type to wrap a xas_vox and audio stream object in one, and save rendered speech to a drone's audio bank * Implement xas_drone_speech_import() as a convenience wrapper to xas_drone_vox methods
Diffstat (limited to 'src')
-rw-r--r--src/drone.c220
1 files changed, 159 insertions, 61 deletions
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) {