1 /*************************************************************************/
2 /* */
3 /* Carnegie Mellon University and */
4 /* Centre for Speech Technology Research */
5 /* University of Edinburgh, UK */
6 /* Copyright (c) 1998-2001 */
7 /* All Rights Reserved. */
8 /* */
9 /* Permission is hereby granted, free of charge, to use and distribute */
10 /* this software and its documentation without restriction, including */
11 /* without limitation the rights to use, copy, modify, merge, publish, */
12 /* distribute, sublicense, and/or sell copies of this work, and to */
13 /* permit persons to whom this work is furnished to do so, subject to */
14 /* the following conditions: */
15 /* 1. The code must retain the above copyright notice, this list of */
16 /* conditions and the following disclaimer. */
17 /* 2. Any modifications must be clearly marked as such. */
18 /* 3. Original authors' names are not deleted. */
19 /* 4. The authors' names are not used to endorse or promote products */
20 /* derived from this software without specific prior written */
21 /* permission. */
22 /* */
23 /* THE UNIVERSITY OF EDINBURGH, CARNEGIE MELLON UNIVERSITY AND THE */
24 /* CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH REGARD TO */
25 /* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY */
26 /* AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF EDINBURGH, CARNEGIE */
27 /* MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, */
28 /* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER */
29 /* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION */
30 /* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF */
31 /* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
32 /* */
33 /*************************************************************************/
34 /* Author : Alan W Black */
35 /* Date : April 1998 */
36 /*-----------------------------------------------------------------------*/
37 /* */
38 /* A quick database structure */
39 /* */
40 /*=======================================================================*/
41 #include <cstdlib>
42 #include <cmath>
43 #include "festival.h"
44 #include "EST_FileType.h"
45 #include "clunits.h"
46
47 VAL_REGISTER_CLASS(clunitsdb,CLDB)
48 SIOD_REGISTER_CLASS(clunitsdb,CLDB)
49 static void cl_load_catalogue(CLDB *cldb,EST_String &indexfile);
50
51 static LISP CLDB_list = NIL;
52 static CLDB *current_cldb = 0;
53
cldb_add(const EST_String & name,CLDB * cldb)54 static void cldb_add(const EST_String &name, CLDB *cldb)
55 {
56 // Add lexicon to list of lexicons
57 LISP lpair;
58
59 lpair = siod_assoc_str(name,CLDB_list);
60
61 if (CLDB_list == NIL)
62 gc_protect(&CLDB_list);
63
64 if (lpair == NIL)
65 {
66 CLDB_list = cons(cons(strintern(name),
67 cons(siod(cldb),NIL)),
68 CLDB_list);
69 }
70 else
71 {
72 cwarn << "CLDB " << name << " recreated" << endl;
73 // old one will be garbage collected
74 setcar(cdr(lpair),siod(cldb));
75 }
76
77 return;
78 }
79
80
cl_load_db(LISP params)81 LISP cl_load_db(LISP params)
82 {
83 EST_String indexfile;
84 int i;
85 LISP w;
86 CLDB *cldb = new CLDB;
87
88 cldb->params = params;
89
90 indexfile = EST_String("") +
91 get_param_str("db_dir",params,"./")+
92 get_param_str("catalogue_dir",params,"./")+
93 get_param_str("index_name",params,"catalogue")+
94 ".catalogue";
95
96 cl_load_catalogue(cldb,indexfile);
97
98 cldb->cweights.resize(siod_llength(get_param_lisp("join_weights",params,NIL)));
99 for (i=0,w=get_param_lisp("join_weights",params,NIL); w; w=cdr(w),i++)
100 cldb->cweights[i] = get_c_float(car(w));
101
102 cldb_add(get_param_str("index_name",params,"catalogue"),cldb);
103
104 current_cldb = cldb;
105
106 return NIL;
107 }
108
cl_load_catalogue(CLDB * cldb,EST_String & indexfile)109 static void cl_load_catalogue(CLDB *cldb,EST_String &indexfile)
110 {
111 EST_TokenStream ts;
112 EST_EstFileType t;
113 EST_Option hinfo;
114 EST_String v;
115 bool ascii;
116 EST_read_status r;
117
118 if (((indexfile == "-") ? ts.open(cin) : ts.open(indexfile)) != 0)
119 {
120 cerr << "CLUNITS: Can't open catalogue file " << indexfile << endl;
121 festival_error();
122 }
123
124 if (((r = read_est_header(ts, hinfo, ascii, t)) != format_ok) ||
125 (t != est_file_index))
126 {
127 cerr << "CLUNITS: " << indexfile << " is not an indexfile" << endl;
128 festival_error();
129 }
130
131 CLunit *ls = 0;
132 while(!ts.eof())
133 {
134 CLunit *s = new CLunit;
135 s->name = ts.get().string();
136 s->base_name = s->name.before("_");
137 s->fileid = ts.get().string();
138 s->start = atof(ts.get().string());
139 s->mid = atof(ts.get().string());
140 s->end = atof(ts.get().string());
141
142 if ((ls != 0) &&
143 (ls->fileid == s->fileid) &&
144 (ls->end == s->start))
145 {
146 s->prev_unit = ls;
147 ls->next_unit = s;
148 }
149 cldb->index.add(s->name,s);
150 ls = s;
151 }
152 }
153
check_cldb()154 CLDB *check_cldb()
155 {
156 if (current_cldb == 0)
157 {
158 cerr << "CLDB: no database loaded\n";
159 festival_error();
160 }
161 return current_cldb;
162 }
163
cl_maybe_fix_pitch_c0(EST_Track * c)164 void cl_maybe_fix_pitch_c0(EST_Track *c)
165 {
166 // If its pitch synchronous, trash the first coefficient with
167 // the pitch value, there should be a cleaner way to do this
168 int i;
169 float ltime = 0;
170
171 if (!c->equal_space())
172 {
173 for (i=0; i < c->num_frames(); i++)
174 {
175 c->a_no_check(i,0) = 1/(c->t(i)-ltime);
176 ltime = c->t(i);
177 }
178 }
179 }
180
load_join_coefs(CLunit * unit)181 void CLDB::load_join_coefs(CLunit *unit)
182 {
183 // Load in the coefficients and signal for this unit.
184 CLfile *fileitem;
185 EST_Track *join_coeffs;
186
187 if (unit->join_coeffs != 0)
188 return;
189
190 fileitem = get_file_join_coefs(unit->fileid);
191
192 EST_Track *unit_join_coeffs = new EST_Track;
193 join_coeffs = fileitem->join_coeffs;
194
195 int pm_start = join_coeffs->index(unit->start);
196 int pm_end = join_coeffs->index(unit->end);
197
198 join_coeffs->sub_track(*unit_join_coeffs, pm_start, pm_end-pm_start+1,0);
199 unit->join_coeffs = unit_join_coeffs;
200 }
201
get_file_join_coefs(const EST_String & fileid)202 CLfile *CLDB::get_file_join_coefs(const EST_String &fileid)
203 {
204 CLfile *fileitem;
205
206 fileitem = get_fileitem(fileid);
207
208 if (fileitem == 0)
209 { // even the file isn't here
210 fileitem = new CLfile;
211 fileindex.add(fileid,fileitem);
212 }
213 if (fileitem->join_coeffs == 0)
214 {
215 EST_Track *join_coeffs = new EST_Track;
216 EST_String jc_filename =
217 EST_String("") +
218 get_param_str("db_dir",params,"./") +
219 get_param_str("coeffs_dir",params,"wav/") +
220 fileid+
221 get_param_str("coeffs_ext",params,".dcoeffs");
222 if (join_coeffs->load(jc_filename) != format_ok)
223 {
224 delete join_coeffs;
225 cerr << "CLUNITS: failed to load join coeffs file " <<
226 jc_filename << endl;
227 festival_error();
228 }
229 // cl_maybe_fix_pitch_c0(join_coeffs);
230 fileitem->join_coeffs = join_coeffs;
231 }
232
233 return fileitem;
234 }
235
get_file_coefs_sig(const EST_String & fileid)236 CLfile *CLDB::get_file_coefs_sig(const EST_String &fileid)
237 {
238 CLfile *fileitem = get_fileitem(fileid);
239
240 if (fileitem == 0)
241 { // even the file isn't here
242 fileitem = new CLfile;
243 fileindex.add(fileid,fileitem);
244 }
245 if (fileitem->sig == 0)
246 {
247 EST_Track *track = new EST_Track;
248 EST_String coef_filename =
249 EST_String("") +
250 get_param_str("db_dir",params,"./") +
251 get_param_str("pm_coeffs_dir",params,"pm/") +
252 fileid+
253 get_param_str("pm_coeffs_ext",params,".pm");
254 if (track->load(coef_filename) != format_ok)
255 {
256 delete track;
257 cerr << "CLUNITS: failed to load coeffs file " <<
258 coef_filename << endl;
259 festival_error();
260 }
261 fileitem->coefs = track;
262
263 EST_Wave *sig = new EST_Wave;
264 EST_String sig_filename =
265 EST_String("") +
266 get_param_str("db_dir",params,"./") +
267 get_param_str("sig_dir",params,"wav/") +
268 fileid+
269 get_param_str("sig_ext",params,".wav");
270 if (sig->load(sig_filename) != format_ok)
271 {
272 delete sig;
273 cerr << "CLUNITS: failed to load signal file " <<
274 sig_filename << endl;
275 festival_error();
276 }
277 fileitem->sig = sig;
278 }
279 return fileitem;
280 }
281
load_coefs_sig(EST_Item * unit)282 void CLDB::load_coefs_sig(EST_Item *unit)
283 {
284 // Load in the coefficients and signal for this unit.
285 EST_String fileid = unit->f("fileid");
286 CLfile *fileitem;
287
288 fileitem = get_file_coefs_sig(fileid);
289
290 EST_Track *coeffs = fileitem->coefs;
291 EST_Wave *sig = fileitem->sig;
292 EST_Track u1;
293 EST_Wave *unit_sig = new EST_Wave;
294
295 int pm_start = coeffs->index(unit->F("start"));
296 int pm_middle = coeffs->index(unit->F("middle"));
297 int pm_end = coeffs->index(unit->F("end"));
298
299 // coeffs->sub_track(u1,Gof((pm_start-1),0), pm_end - pm_start + 1);
300 coeffs->sub_track(u1,pm_start, pm_end - pm_start + 1,0);
301 EST_Track *unit_coeffs = new EST_Track(u1);
302 for (int j = 0; j < u1.num_frames(); ++j)
303 unit_coeffs->t(j) = u1.t(j) - coeffs->t(Gof((pm_start - 1), 0));
304
305 /* printf("coefs %s: pm_start %d pm_end %d pm_length %d\n",
306 (const char *)fileid,
307 pm_start, pm_end, pm_end - pm_start + 1); */
308 unit->set_val("coefs",est_val(unit_coeffs));
309
310 if ((pm_middle-pm_start-1) < 1)
311 unit->set("middle_frame", 1);
312 else
313 unit->set("middle_frame", pm_middle - pm_start -1);
314 int samp_start = (int)(coeffs->t(Gof((pm_start - 1), 0))
315 * (float)sig->sample_rate());
316 int samp_end;
317 if ((pm_end + 1) < coeffs->num_frames())
318 samp_end = (int)(coeffs->t(pm_end + 1) * (float)sig->sample_rate());
319 else
320 samp_end = (int)(coeffs->t(pm_end) * (float)sig->sample_rate());
321 int real_samp_start = (int)(unit->F("start") * (float)sig->sample_rate());
322 int real_samp_end = (int)(unit->F("end") * (float)sig->sample_rate());
323 if (samp_end-samp_start < 1)
324 sig->sub_wave(*unit_sig,samp_start, 1);
325 else
326 sig->sub_wave(*unit_sig,samp_start, samp_end-samp_start);
327 if (real_samp_start-samp_start<0)
328 unit->set("samp_start",0);
329 else
330 unit->set("samp_start",real_samp_start-samp_start);
331 unit->set("samp_end",real_samp_end-samp_start);
332 /* Need to preserve where the phone boundary is (which may actually */
333 /* be past the end of this unit */
334 unit->set("samp_seg_start",
335 (int)(unit->F("seg_start") *
336 (float)sig->sample_rate())-samp_start);
337 unit->set_val("sig",est_val(unit_sig));
338 }
339
CLunit()340 CLunit::CLunit()
341 {
342 start=0;
343 mid=0;
344 end=0;
345 prev_unit = 0;
346 next_unit = 0;
347 samp_start = 0;
348 samp_end = 0;
349 join_coeffs = 0;
350 coefs = 0;
351 sig = 0;
352 }
353
~CLunit()354 CLunit::~CLunit()
355 {
356 delete join_coeffs;
357 delete coefs;
358 delete sig;
359 }
360
CLfile()361 CLfile::CLfile()
362 {
363 join_coeffs = 0;
364 coefs = 0;
365 sig = 0;
366 }
367
~CLfile()368 CLfile::~CLfile()
369 {
370 delete join_coeffs;
371 delete coefs;
372 delete sig;
373 }
374
CLDB()375 CLDB::CLDB()
376 {
377 gc_protect(¶ms);
378 }
379
del_clunit(void * s)380 static void del_clunit(void *s) { delete (CLunit *)s; }
del_clfile(void * s)381 static void del_clfile(void *s) { delete (CLfile *)s; }
~CLDB()382 CLDB::~CLDB()
383 {
384 index.clear(del_clunit);
385 fileindex.clear(del_clfile);
386 gc_unprotect(¶ms);
387 }
388
cldb_list(void)389 LISP cldb_list(void)
390 {
391 // List names of all current defined cluster dbs
392 LISP d = NIL;
393 LISP l;
394
395 for (l=CLDB_list; l != NIL; l=cdr(l))
396 d = cons(car(car(l)),d);
397
398 return d;
399 }
400
cldb_select(LISP dbname)401 LISP cldb_select(LISP dbname)
402 {
403 // Select named cldb and make it current
404 EST_String name = get_c_string(dbname);
405 LISP lpair;
406
407 lpair = siod_assoc_str(name,CLDB_list);
408
409 if (lpair == NIL)
410 {
411 cerr << "CLDB " << name << " not defined" << endl;
412 festival_error();
413 }
414 else
415 current_cldb = clunitsdb(car(cdr(lpair)));
416
417 return dbname;
418 }
419
420
421
422