1 /*************************************************************************/
2 /* */
3 /* Language Technologies Institute */
4 /* Carnegie Mellon University */
5 /* Copyright (c) 2010-2013 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author: Alok Parlikar (aup@cs.cmu.edu) */
34 /* Date: April 2010 */
35 /*************************************************************************/
36 /* */
37 /* Load a clustergen voice from a file */
38 /* */
39 /*************************************************************************/
40
41 #include "flite.h"
42 #include "cst_cg.h"
43 #include "cst_cg_map.h"
44
cg_init_lang_lex(cst_voice * vox,const cst_lang * lang_table,const char * language)45 cst_lexicon *cg_init_lang_lex(cst_voice *vox,
46 const cst_lang *lang_table,
47 const char *language)
48 {
49 cst_lexicon *lex = NULL;
50 int i;
51
52 /* Search Lang table for lang_init() and lex_init(); */
53 for (i=0; lang_table[i].lang; i++)
54 {
55 if (cst_streq(language,lang_table[i].lang))
56 {
57 (lang_table[i].lang_init)(vox);
58 lex = (lang_table[i].lex_init)();
59 break;
60 }
61 }
62
63 /* NULL if lang/lex not found */
64 return lex;
65 }
66
cst_cg_load_voice(const char * filename,const cst_lang * lang_table)67 cst_voice *cst_cg_load_voice(const char *filename,
68 const cst_lang *lang_table)
69 {
70 cst_voice *vox;
71 cst_lexicon *lex = NULL;
72 int end_of_features;
73 const char *language;
74 const char *xname;
75 cst_val *secondary_langs;
76 const cst_val *sc;
77 cst_cg_db *cg_db;
78 char* fname;
79 char* fval;
80 cst_file vd;
81 int byteswapped = 0;
82 int r;
83
84 vd = cst_fopen(filename,CST_OPEN_READ);
85 if (vd == NULL)
86 {
87 cst_errmsg("Error load voice: can't open file %s\n",filename);
88 return NULL;
89 }
90
91 r = cst_cg_read_header(vd);
92 if (r == CST_CG_BYTESWAPPED_VOICE)
93 byteswapped = 1;
94 else if (r != 0)
95 {
96 cst_errmsg("Error load voice: %s does not have expected header\n",filename);
97 cst_fclose(vd);
98 return NULL;
99 }
100
101 vox = new_voice();
102
103 /* Read voice features from the external file */
104 /* Read until the feature is "end_of_features" */
105 fname=NULL;
106 end_of_features = 0;
107 while (end_of_features == 0)
108 {
109 cst_read_voice_feature(vd,&fname, &fval,byteswapped);
110 if (cst_streq(fname,"end_of_features"))
111 end_of_features = 1;
112 else
113 {
114 xname = feat_own_string(vox->features,fname);
115 flite_feat_set_string(vox->features,xname, fval);
116 }
117 cst_free(fname);
118 cst_free(fval);
119 }
120
121 /* Load up cg_db from external file */
122 cg_db = cst_cg_load_db(vox,vd,byteswapped);
123
124 if (cg_db == NULL)
125 {
126 cst_fclose(vd);
127 return NULL;
128 }
129
130 /* Use the language feature to initialize the correct voice */
131 language = flite_get_param_string(vox->features, "language", "");
132
133 /* Some languages require initialization of more than one language */
134 /* e.g. Indic languages require English initialization too */
135 /* We initialize the secondary languages first so our last init is */
136 /* the primary language */
137 secondary_langs =
138 val_readlist_string(flite_get_param_string(vox->features,
139 "secondary_languages",""));
140 for (sc = secondary_langs; sc; sc=val_cdr(sc))
141 {
142 cg_init_lang_lex(vox,lang_table,val_string(val_car(sc)));
143 }
144 delete_val(secondary_langs);
145
146 /* Init primary language */
147 lex = cg_init_lang_lex(vox,lang_table,language);
148
149 if (lex == NULL)
150 { /* Language is not supported */
151 /* Delete allocated memory in cg_db */
152 cst_cg_free_db(vd,cg_db);
153 cst_fclose(vd);
154 cst_errmsg("Error load voice: lang/lex %s not supported in this binary\n",language);
155 return NULL;
156 }
157
158 /* Things that weren't filled in already. */
159 vox->name = cg_db->name;
160 flite_feat_set_string(vox->features,"name",cg_db->name);
161 flite_feat_set_string(vox->features,"pathname",filename);
162
163 flite_feat_set(vox->features,"lexicon",lexicon_val(lex));
164 flite_feat_set(vox->features,"postlex_func",uttfunc_val(lex->postlex));
165
166 /* No standard segment durations are needed as its done at the */
167 /* HMM state level */
168 flite_feat_set_string(vox->features,"no_segment_duration_model","1");
169 flite_feat_set_string(vox->features,"no_f0_target_model","1");
170
171 /* Waveform synthesis */
172 flite_feat_set(vox->features,"wave_synth_func",uttfunc_val(&cg_synth));
173 flite_feat_set(vox->features,"cg_db",cg_db_val(cg_db));
174 flite_feat_set_int(vox->features,"sample_rate",cg_db->sample_rate);
175
176 cst_fclose(vd);
177 return vox;
178 }
179
cst_cg_unload_voice(cst_voice * vox,cst_val * voice_list)180 void cst_cg_unload_voice(cst_voice *vox,cst_val *voice_list)
181 {
182 delete_voice(vox);
183 }
184
185