speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] espeak - Add config option to show variants in voice list


From: Luke Yelavich
Subject: [PATCH] espeak - Add config option to show variants in voice list
Date: Wed, 3 Jun 2015 12:23:10 +1000

From: Luke Yelavich <address@hidden>
To: address@hidden

Longre term we need to extend the client API to allow synths to present
such information to the user, but this will work for now, disabled by default.
---
 config/modules/espeak.conf |   7 +++
 src/modules/espeak.c       | 110 ++++++++++++++++++++++++++++++++++++---------
 2 files changed, 97 insertions(+), 20 deletions(-)

diff --git a/config/modules/espeak.conf b/config/modules/espeak.conf
index ce9963a..e8afa4c 100644
--- a/config/modules/espeak.conf
+++ b/config/modules/espeak.conf
@@ -35,7 +35,14 @@ EspeakNormalRate 170
 # Maximum rate (100 in speech-dispatcher)
 EspeakMaxRate 390
 
+# -- Espeak variants --
 
+# Controls whether espeak voice variants are presented in the list of
+# available voices. A value of 1 will present an espeak voice, plus the
+# espeak voice with all the available variants. A value of 0 will present
+# the list of espeak voices only.
+
+EspeakListVoiceVariants 0
 
 # -- Internal parameters --
 
diff --git a/src/modules/espeak.c b/src/modules/espeak.c
index b4040bd..48fc743 100644
--- a/src/modules/espeak.c
+++ b/src/modules/espeak.c
@@ -193,6 +193,7 @@ MOD_OPTION_1_STR(EspeakPunctuationList)
     MOD_OPTION_1_INT(EspeakMinRate)
     MOD_OPTION_1_INT(EspeakNormalRate)
     MOD_OPTION_1_INT(EspeakMaxRate)
+    MOD_OPTION_1_INT(EspeakListVoiceVariants)
 
     MOD_OPTION_1_INT(EspeakAudioChunkSize)
     MOD_OPTION_1_INT(EspeakAudioQueueMaxSize)
@@ -219,6 +220,7 @@ int module_load(void)
        MOD_OPTION_1_INT_REG(EspeakMaxRate, 390);
        MOD_OPTION_1_STR_REG(EspeakPunctuationList, "@/+-_");
        MOD_OPTION_1_INT_REG(EspeakCapitalPitchRise, 800);
+       MOD_OPTION_1_INT_REG(EspeakListVoiceVariants, 0);
        if (EspeakCapitalPitchRise == 1 || EspeakCapitalPitchRise == 2) {
                EspeakCapitalPitchRise = 0;
        }
@@ -1159,31 +1161,43 @@ static void *_espeak_play(void *nothing)
 static SPDVoice **espeak_list_synthesis_voices()
 {
        SPDVoice **result = NULL;
-       const espeak_VOICE **espeak_voices = espeak_ListVoices(NULL);
+       SPDVoice *voice = NULL;
+       SPDVoice *vo = NULL;
+       const espeak_VOICE **espeak_voices = NULL;
+       const espeak_VOICE **espeak_variants = NULL;
+       espeak_VOICE *variant_spec = NULL;
+       const espeak_VOICE *v = NULL;
+       GQueue *voice_list = NULL;
+       GQueue *variant_list = NULL;
+       GList *voice_list_iter = NULL;
+       GList *variant_list_iter = NULL;
+       const gchar *first_lang = NULL;
+       gchar *lang = NULL;
+       gchar *variant = NULL;
+       gchar *dash = NULL;
+       gchar *vname = NULL;
+       int numvoices = 0;
+       int numvariants = 0;
+       int totalvoices = 0;
        int i = 0;
-       int j = 0;
 
-       /* Count number of voices */
-       int numvoices = 0;
-       while (espeak_voices[numvoices] != NULL) {
-               numvoices++;
-       }
-       DBG("Espeak: %d voices total.", numvoices);
-       result = g_new0(SPDVoice *, numvoices + 1);
-       for (i = j = 0; espeak_voices[i] != NULL; i++) {
-               const espeak_VOICE *v = espeak_voices[i];
+       espeak_voices = espeak_ListVoices(NULL);
+       voice_list = g_queue_new();
+
+       for (i = 0; espeak_voices[i] != NULL; i++) {
+               v = espeak_voices[i];
                if (!g_str_has_prefix(v->identifier, "mb/")) {
                        /* Not an mbrola voice */
-                       SPDVoice *voice = g_new0(SPDVoice, 1);
+                       voice = g_new0(SPDVoice, 1);
 
                        voice->name = g_strdup(v->name);
 
-                       const gchar *first_lang = v->languages + 1;
-                       gchar *lang = NULL;
-                       gchar *variant = NULL;
+                       first_lang = v->languages + 1;
+                       lang = NULL;
+                       variant = NULL;
                        if (g_utf8_validate(first_lang, -1, NULL)) {
-                               gchar *dash =
-                                   g_utf8_strchr(first_lang, -1, '-');
+                               dash =
+                                      g_utf8_strchr(first_lang, -1, '-');
                                if (dash != NULL) {
                                        /* There is probably a variant string 
(like en-uk) */
                                        lang =
@@ -1201,11 +1215,67 @@ static SPDVoice **espeak_list_synthesis_voices()
                        voice->language = lang;
                        voice->variant = variant;
 
-                       result[j++] = voice;
+                       g_queue_push_tail(voice_list, voice);
+               }
+
+       }
+
+       numvoices = g_queue_get_length(voice_list);
+       DBG("Espeak: %d voices total.", numvoices)
+
+       if (EspeakListVoiceVariants) {
+               variant_spec = g_new0(espeak_VOICE, 1);
+               variant_spec->languages = "variant";
+               espeak_variants = espeak_ListVoices(variant_spec);
+               variant_list = g_queue_new();
+
+               for (i = 0; espeak_variants[i] != NULL; i++) {
+                       v = espeak_variants[i];
+
+                       vname = g_strdup(v->name);
+                       g_queue_push_tail(variant_list, vname);
+               }
+
+               numvariants = g_queue_get_length(variant_list);
+               DBG("Espeak: %d variants total.", numvariants)
+       }
+
+       totalvoices = (numvoices * numvariants) + numvoices;
+       result = g_new0(SPDVoice *, totalvoices + 1);
+       voice_list_iter = g_queue_peek_head_link(voice_list);
+
+       for (i = 0; i < totalvoices; i++) {
+               result[i] = voice_list_iter->data;
+
+               if (!g_queue_is_empty(variant_list)) {
+                       vo = voice_list_iter->data;
+                       variant_list_iter = 
g_queue_peek_head_link(variant_list);
+
+                       while (variant_list_iter != NULL && 
variant_list_iter->data != NULL) {
+                               voice = g_new0(SPDVoice, 1);
+
+                               voice->name = g_strdup_printf("%s+%s", vo->name,
+                                                             
variant_list_iter->data);
+                               voice->language = g_strdup(vo->language);
+                               voice->variant = g_strdup(vo->variant);
+
+                               result[++i] = voice;
+                               variant_list_iter = variant_list_iter->next;
+                       }
                }
+
+               voice_list_iter = voice_list_iter->next;
        }
-       result[j] = NULL;
-       DBG("Espeak: %d usable voices.", j);
+
+       if (voice_list != NULL)
+               g_queue_free(voice_list);
+       if (variant_list != NULL)
+               g_queue_free_full(variant_list, (GDestroyNotify)g_free);
+       if (variant_spec != NULL)
+               g_free(variant_spec);
+
+       result[i] = NULL;
+       DBG("Espeak: %d usable voices.", totalvoices);
 
        return result;
 }
-- 
2.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]