Bug Summary

File:modules/MultiSyn/DiphoneVoiceModule.cc
Location:line 578, column 8
Description:Dereference of null pointer (loaded from variable 'utt')

Annotated Source Code

1/*************************************************************************/
2/* */
3/* Centre for Speech Technology Research */
4/* (University of Edinburgh, UK) and */
5/* Korin Richmond */
6/* Copyright (c) 2002 */
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/* */
16/* 1. The code must retain the above copyright notice, this list of */
17/* conditions and the following disclaimer. */
18/* 2. Any modifications must be clearly marked as such. */
19/* 3. Original authors' names are not deleted. */
20/* 4. The authors' names are not used to endorse or promote products */
21/* derived from this software without specific prior written */
22/* permission. */
23/* */
24/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
25/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
26/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT */
27/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
28/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
29/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
30/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
31/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
32/* THIS SOFTWARE. */
33/* */
34/*************************************************************************/
35/* */
36/* Author: Korin Richmond */
37/* Date: Aug 2002 */
38/* --------------------------------------------------------------------- */
39/* A diphone unit selection "voice module" */
40/* (implemented using a list of utterance objects) */
41/*************************************************************************/
42
43#include "DiphoneVoiceModule.h"
44#include "EST_TargetCost.h"
45#include "EST_viterbi.h"
46#include "EST_rw_status.h"
47#include "EST_Track.h"
48#include "EST_track_aux.h"
49#include "EST_Wave.h"
50#include "EST_THash.h"
51#include "EST_TList.h"
52#include "EST_types.h"
53#include "ling_class/EST_Utterance.h"
54#include "siod.h"
55#include "siod_est.h"
56#include "safety.h"
57#include <cstdlib>
58
59#include "EST_Val.h"
60
61// from src/modules/UniSyn_diphone/us_diphone.h
62// this won't be staying here long...
63void parse_diphone_times(EST_Relation &diphone_stream,
64 EST_Relation &source_lab);
65
66SIOD_REGISTER_CLASS(du_voicemodule,DiphoneVoiceModule)class DiphoneVoiceModule *du_voicemodule(LISP x) { return du_voicemodule
(val(x)); } int du_voicemodule_p(LISP x) { if (val_p(x) &&
(val_type_du_voicemodule == val(x).type())) return (1==1); else
return (1==0); } LISP siod(const class DiphoneVoiceModule *v
) { if (v == 0) return ((struct obj *) 0); else return siod(est_val
(v)); }
67VAL_REGISTER_CLASS(du_voicemodule,DiphoneVoiceModule)val_type val_type_du_voicemodule="du_voicemodule"; class DiphoneVoiceModule
*du_voicemodule(const EST_Val &v) { if (v.type() == val_type_du_voicemodule
) return (class DiphoneVoiceModule *)v.internal_ptr(); else (
EST_error_where = __null), (*EST_error_func)("val not of type val_type_"
"du_voicemodule"); return __null; } static void val_delete_du_voicemodule
(void *v) { delete (class DiphoneVoiceModule *)v; } EST_Val est_val
(const class DiphoneVoiceModule *v) { return EST_Val(val_type_du_voicemodule
, (void *)v,val_delete_du_voicemodule); }
68
69VAL_REGISTER_CLASS(diphonecandidate,DiphoneCandidate)val_type val_type_diphonecandidate="diphonecandidate"; class DiphoneCandidate
*diphonecandidate(const EST_Val &v) { if (v.type() == val_type_diphonecandidate
) return (class DiphoneCandidate *)v.internal_ptr(); else (EST_error_where
= __null), (*EST_error_func)("val not of type val_type_""diphonecandidate"
); return __null; } static void val_delete_diphonecandidate(void
*v) { delete (class DiphoneCandidate *)v; } EST_Val est_val(
const class DiphoneCandidate *v) { return EST_Val(val_type_diphonecandidate
, (void *)v,val_delete_diphonecandidate); }
70
71// defined in a single place to avoid inconsistency.
72// Given a phone segment item, return the standard cut point
73// time, calculated in the standard way.
74float getJoinTime( const EST_Item *seg )
75{
76 float midt=0.0;
77
78 // hack to avoid overhead of string creation and deletion
79 // (EST feature access should really be changed to take
80 // const char* instead of const EST_String& )
81 static const EST_String cl_end_str( "cl_end" );
82 static const EST_String dipth_str( "dipth" );
83 static const EST_String start_str( "start" );
84
85 // work out boundary for diphone join
86 if( seg->f_present(cl_end_str) ) // join at cl_end point for stops
87 midt = seg->features().val("cl_end").Float();
88 else if( seg->f_present(dipth_str) ) // join at 25% through a diphthong
89 midt = 0.75*seg->F(start_str)
90 + 0.25*seg->features().val("end").Float();
91 else
92 midt = ( seg->F(start_str)
93 + seg->features().val("end").Float() ) / 2.0;
94
95 return midt;
96}
97
98DiphoneVoiceModule::DiphoneVoiceModule( const EST_StrList& basenames,
99 const EST_String& uttDir,
100 const EST_String& wavDir,
101 const EST_String& pmDir,
102 const EST_String& coefDir,
103 unsigned int sr,
104 const EST_String& uttExt,
105 const EST_String& wavExt,
106 const EST_String& pmExt,
107 const EST_String& coefExt )
108
109 : fileList( basenames ),
110 utt_dir ( uttDir ),
111 utt_ext ( uttExt ),
112 pm_dir( pmDir ),
113 pm_ext( pmExt ),
114 coef_dir( coefDir ),
115 coef_ext( coefExt ),
116 wave_dir( wavDir ),
117 wave_ext( wavExt ),
118 wav_srate( sr ),
119 tcdatahash ( 0 ),
120 utt_dbase( 0 ),
121 catalogue( 0 )
122{
123
124}
125
126void DiphoneVoiceModule::addCoefficients( EST_Relation *segs, const EST_Track& coefs )
127{
128 float startt, midt, endt;
129 EST_FVector *startf, *midf, *endf;
130 const int num_coefs = coefs.num_channels();
131
132 // hack to avoid overhead of string creation and deletion
133 // (EST feature access should really be changed to take
134 // const char* instead of const EST_String& )
135 static const EST_String startcoef_str("startcoef");
136 static const EST_String midcoef_str("midcoef");
137 static const EST_String endcoef_str("endcoef");
138 static const EST_String start_str("start");
139
140 EST_Item *seg=segs->head();
141 startt = seg->F(start_str);
142
143 startf = new EST_FVector(num_coefs);
144 CHECK_PTR(startf)if((startf)==0){ (EST_error_where = __null), (*EST_error_func
)("memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,144);}
;
145 coefs.copy_frame_out(coefs.index(startt), *startf); //this one not shared
146
147 for( ; seg!=0; seg=seg->next() ){
148
149 // work out boundary for diphone join
150 midt = getJoinTime( seg );
151
152 // copy frames out and set as features
153 seg->features().set_val( startcoef_str, est_val(startf) );
154
155 midf = new EST_FVector(num_coefs);
156 CHECK_PTR(midf)if((midf)==0){ (EST_error_where = __null), (*EST_error_func)(
"memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,156);}
;
157 coefs.copy_frame_out(coefs.index(midt), *midf);
158 seg->features().set_val( midcoef_str, est_val(midf) );
159
160 endt = seg->features().val("end").Float();
161 endf = new EST_FVector(num_coefs);
162 CHECK_PTR(endf)if((endf)==0){ (EST_error_where = __null), (*EST_error_func)(
"memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,162);}
;
163 coefs.copy_frame_out(coefs.index(endt), *endf);
164 seg->features().set_val( endcoef_str, est_val(endf) );
165
166 startf = endf; // phones share frame at phone boundary (reference counted in EST_Val)
167 }
168}
169
170void DiphoneVoiceModule::flatPack( EST_Relation *segs,
171 const EST_TargetCost *tc ) const
172{
173
174 const EST_FlatTargetCost *ftc = (EST_FlatTargetCost *)tc;
175
176 for( EST_Item *seg=segs->head(); seg->next() !=0; seg=seg->next() )
177 tcdatahash->add_item(seg, ftc->flatpack(seg));
178
179}
180
181void DiphoneVoiceModule::initialise( const EST_TargetCost *tc, bool ignore_bad_tag )
182{
183 EST_Utterance *u=0;
184 EST_Relation *segs=0;
185
186 tcdatahash = new TCDataHash(500);
187
188 utt_dbase = new EST_TList<EST_Utterance *>;
189 CHECK_PTR(utt_dbase)if((utt_dbase)==0){ (EST_error_where = __null), (*EST_error_func
)("memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,189);}
;
190
191 catalogue = new EST_TStringHash<ItemList*>( 2500 );
192 CHECK_PTR(catalogue)if((catalogue)==0){ (EST_error_where = __null), (*EST_error_func
)("memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,192);}
;
193
194 int numIgnoredPhones=0;
195
196 if(ignore_bad_tag)
197 EST_warning(EST_error_where = __null), (*EST_warning_func)( "Looking for bad flags");
198 else
199 EST_warning(EST_error_where = __null), (*EST_warning_func)( "Ignoring bad flags");
200
201
202 for( EST_Litem *it=fileList.head(); it!=0 ; it=it->next() ){
203 u = new EST_Utterance;
204 CHECK_PTR(u)if((u)==0){ (EST_error_where = __null), (*EST_error_func)("memory allocation failed (file %s, line %d)"
, "DiphoneVoiceModule.cc",204);}
;
205
206 if( (u->load(utt_dir+fileList(it)+utt_ext)) != read_ok )
207 EST_error(EST_error_where = __null), (*EST_error_func)( "Couldn't load utterance %s\n",
208 (const char*)fileList(it) );
209
210 segs = u->relation( "Segment" );
211
212 // add join cost coefficients (at middle of phones)
213 EST_Track coefs;
214 if( (coefs.load((coef_dir+fileList(it)+coef_ext))) != read_ok )
215 EST_error(EST_error_where = __null), (*EST_error_func)( "Couldn't load data file %s",
216 (const char*) (coef_dir+fileList(it)+coef_ext) );
217
218 addCoefficients( segs, coefs );
219
220 if (tc->is_flatpack())
221 {
222 flatPack(segs,tc);
223 u->remove_relation("Token");
224 u->remove_relation("Word");
225 u->remove_relation("Phrase");
226 u->remove_relation("Syllable");
227 u->remove_relation("SylStructure");
228 u->remove_relation("IntEvent");
229 u->remove_relation("Intonation");
230 }
231
232 addToCatalogue( u, &numIgnoredPhones, ignore_bad_tag );
233 utt_dbase->append( u );
234 }
235
236 if(ignore_bad_tag)
237 EST_warning(EST_error_where = __null), (*EST_warning_func)( "Ignored %d phones with bad flag set\n", numIgnoredPhones );
238}
239
240DiphoneVoiceModule::~DiphoneVoiceModule()
241{
242 if( utt_dbase != 0 ){
243 EST_Litem *it = utt_dbase->head();
244 for( ; it!=0 ; it=it->next() )
245 delete (*utt_dbase)(it);
246 delete utt_dbase;
247 }
248
249 delete catalogue;
250
251 if(tcdatahash)
252 delete tcdatahash;
253
254}
255
256void DiphoneVoiceModule::addToCatalogue( const EST_Utterance *utt, int *num_ignored, bool ignore_bad )
257{
258 EST_Item *item, *next_item;
259 ItemList *diphoneList;
260 const EST_String *ph1, *ph2;
261 int found=0;
262
263 static const EST_String bad_str( "bad" );
264
265 item = (utt->relation( "Segment" ))->tail();
266 if( item!=0 ){
267 ph2 = &(item->features().val("name").String());
268
269 while( (item=item->prev()) != 0 ){
270
271 next_item = item->next();
272
273 // You'd think we need to check both item->f_present(bad_str) and
274 // next_item->f_present(bad_str) like this:
275 //if((item->f_present(bad_str) || next_item->f_present(bad_str)) && ignore_bad == true){
276 // But experiment showed that then each time one diphone too many would be
277 // ignored. This was partly compensated by a bug pesent up to r1.14
278 // (a iteration within "if(item=item->prev()!=0)" just before the "continue")
279 // which caused the leftmost bad phone in a row of bad phones NOT to be ignored
280 // when the length of the row was even (or when it was odd and ended in the
281 // utterance-final phone, which is never checked for badness).
282 if(item->f_present(bad_str) && ignore_bad == true){
283
284 (*num_ignored)++;
285
286 EST_warning(EST_error_where = __null), (*EST_warning_func)( "Ignoring diphone \"%s_%s\" (LEFT %s in %s at %fs, bad flag \"%s\")",
287 item->S("name").str(),
288 next_item->S("name").str(),
289 item->S("name").str(),
290 utt->f.S("fileid").str(),
291 item->F("end"),
292 item->S("bad").str() );
293
294 if(item->prev() != 0){
295 continue;
296 }
297 else
298 break; //already at start of list, so finish up
299 }
300
301 ph1 = &(item->features().val("name").String());
302
303// EST_warning( "Adding phone \"%s\" (%s, %f) to diphoneList %s_%s",
304// item->S("name").str(),
305// utt->f.S("fileid").str(),
306// item->F("end"),
307// item->S("name").str(),
308// next_item->S("name").str());
309
310 diphoneList = catalogue->val(EST_String::cat(*ph1,"_",*ph2), found);
311
312 if( !found ){
313 diphoneList = new ItemList;
314 CHECK_PTR(diphoneList)if((diphoneList)==0){ (EST_error_where = __null), (*EST_error_func
)("memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,314);}
;
315 catalogue->add_item(EST_String::cat(*ph1,"_",*ph2), diphoneList, 1); // no_search=1
316 }
317
318 diphoneList->append( item );
319
320 ph2 = ph1;
321 }
322 }
323}
324
325void DiphoneVoiceModule::getDiphone( const EST_Item *phone1,
326 EST_Track* coef, EST_Wave* sig, int *midframe,
327 bool extendLeft, bool extendRight ) const
328{
329 EST_Item *phone2 = phone1->next();
330
331 // load the relevant parts
332 const EST_String &fname = phone1->relation()->utt()->f.val("fileid").String();
333
334 static const EST_String start_str( "start" );
335
336 float startt,midt,endt;
337
338 if( extendLeft==true )
339 startt = phone1->F(start_str);
340 else
341 startt = getJoinTime( phone1 );
342
343 midt = phone1->features().val("end").Float();
344
345 if( extendRight==true )
346 endt = phone2->features().val("end").Float();
347 else
348 endt = getJoinTime( phone2 );
349
350 // get pitchmarks for pitch synchronous synthesis
351 EST_Track *tempcoef = new EST_Track;
352 CHECK_PTR(tempcoef)if((tempcoef)==0){ (EST_error_where = __null), (*EST_error_func
)("memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,352);}
;
353 if( (tempcoef->load((pm_dir+fname+pm_ext))) != read_ok )
354 EST_error(EST_error_where = __null), (*EST_error_func)( "Couldn't load data file %s",
355 (const char*) (pm_dir+fname+pm_ext) );
356
357 // following few lines effectively moves segment boundaries to
358 // line up with pitch periods.
359 int copy_start = tempcoef->index( startt );
360 int copy_end = tempcoef->index( endt );
361 //copy_end -= 1; //so that adjacent units don't start and end with same frame
362
363 int copy_len = copy_end - copy_start;
364 //int copy_len = copy_end - copy_start + 1;
365
366 startt = tempcoef->t( copy_start );
367 endt = tempcoef->t( copy_end );
368
369 if( copy_len == 0 ){
370 EST_warning(EST_error_where = __null), (*EST_warning_func)( "%s(%f->%f): %s_%s diphone length means 1 pitchmark will be duplicated",
371 fname.str(), startt, endt, phone1->S("name").str(), phone2->S("name").str() );
372 copy_len=1;
373 }
374 else if( copy_len < 0 ){
375 EST_error(EST_error_where = __null), (*EST_error_func)( "%s(%f->%f): %s_%s diphone length renders %d pitchmark",
376 fname.str(), startt, endt, phone1->S("name").str(), phone2->S("name").str(), copy_len );
377 }
378
379 tempcoef->copy_sub_track( *coef, copy_start, copy_len );
380
381 *midframe = coef->index( midt );
382
383 // adjust timing, which Festival synthesis code makes assumptions about
384 // SPECIFICALLY, the unisyn module wants all units to start from
385 // the first value above 0.0 (as the first pitch mark)
386 float t_off = (copy_start!=0) ? tempcoef->t(copy_start-1) : 0.0;
387 int nframes = coef->num_frames();
388 for( int i=0; i<nframes; ++i )
389 coef->t(i) -= t_off;
390
391 //start waveform at previous pitchmark (this is period approximation used)
392 int st_sample = (int)rint( t_off * (float) wav_srate );
393
394 //preferably end waveform at following pitchmark (follows convention in UniSyn module)
395 int end_sample;
396 if( copy_end < tempcoef->num_frames() )
397 end_sample = (int) rint( tempcoef->t(copy_end) * (float) wav_srate );
398 //if( copy_end+1 < tempcoef->num_frames() )
399 // end_sample = (int) rint( tempcoef->t(copy_end+1) * (float) wav_srate );
400 else{
401 // estimate from previous pitch mark shift
402 int pp_centre_sample = (int) rint( endt * (float) wav_srate );
403 int pp_first_sample = (int) rint( tempcoef->t(copy_end) * (float) wav_srate );
404 //int pp_first_sample = (int) rint( tempcoef->t(copy_end-1) * (float) wav_srate );
405 end_sample = (2*pp_centre_sample)-pp_first_sample;
406 }
407
408 // (obviously, we would want to load and cache any files //
409 // which haven't been loaded yet, rather than just load //
410 // the parts each and every time) //
411 if( sig->load( wave_dir+fname+wave_ext, //
412 st_sample, end_sample-st_sample+1) != read_ok ) //
413 EST_error(EST_error_where = __null), (*EST_error_func)( "Couldn't load data file %s", //
414 (const char*) (wave_dir+fname+wave_ext) ); //
415
416 delete tempcoef;
417}
418
419
420inline EST_VTCandidate* makeCandidate( const EST_Item *target_ph1,
421 const EST_Item *cand_ph1,
422 const EST_TargetCost *tc,
423 const TCData *tcd,
424 const TCDataHash *tcdatahash,
425 float tc_weight,
426 const DiphoneVoiceModule *dvm_p )
427{
428 // hack to avoid overhead of string creation and deletion
429 // (EST feature access should really be changed to take
430 // const char* instead of const EST_String& )
431 static const EST_String extendLeft_str("extendLeft");
432 static const EST_String extendRight_str("extendRight");
433 static const EST_String jccid_str("jccid");
434
435 EST_VTCandidate *c = new EST_VTCandidate;
436 CHECK_PTR(c)if((c)==0){ (EST_error_where = __null), (*EST_error_func)("memory allocation failed (file %s, line %d)"
, "DiphoneVoiceModule.cc",436);}
;
437
438 EST_Item *cand_ph2 = cand_ph1->next();
439
440 // set up all the members we can here
441 c->s = const_cast<EST_Item*>(cand_ph1);
442
443 EST_FVector *left, *right;
444 if( target_ph1->f_present( extendLeft_str ) )
445 left = fvector( cand_ph1->features().val( "startcoef" ) );
446 else
447 left = fvector( cand_ph1->features().val( "midcoef" ) );
448
449 if( target_ph1->next()->f_present( extendRight_str ) )
450 right = fvector( cand_ph2->features().val( "endcoef" ) );
451 else
452 right = fvector( cand_ph2->features().val( "midcoef" ) );
453
454 // an abuse of the "name" EST_Val member to store data we want instead
455 // of what is intended to go there
456 // (will become unnecessary with a more general candidate class)
457 DiphoneCandidate *cand = new DiphoneCandidate( cand_ph1, dvm_p, left, right );
458 CHECK_PTR(cand)if((cand)==0){ (EST_error_where = __null), (*EST_error_func)(
"memory allocation failed (file %s, line %d)", "DiphoneVoiceModule.cc"
,458);}
;
459 c->name = est_val( cand ); //to get synthesis parameters (deleted by EST_Val c->name)
460
461 if( cand_ph1->f_present( jccid_str ) ){
462 cand->ph1_jccid = cand_ph1->features().val( "jccid" ).Int();
463 cand->ph1_jccindex = cand_ph1->features().val( "jccindex" ).Int();
464 }
465
466 if( cand_ph2->f_present( jccid_str ) ){
467 cand->ph1_jccid = cand_ph2->features().val( "jccid" ).Int();
468 cand->ph1_jccindex = cand_ph2->features().val( "jccindex" ).Int();
469 }
470
471 if(tc->is_flatpack())
472 c->score = tc_weight*
473 ((const EST_FlatTargetCost *)tc)
474 ->operator()( tcd,
475 tcdatahash->val( const_cast<EST_Item*>(cand_ph1) ) );
476 else
477 c->score = tc_weight*tc->operator()( target_ph1, cand_ph1 );
478
479
480 return c;
481}
482
483inline void itemListToCandidateList( ItemList::Entries &it,
484 EST_VTCandidate **head,
485 EST_VTCandidate **tail,
486 const EST_Item *target_ph1,
487 const EST_TargetCost *tc,
488 const TCDataHash *tcdh,
489 const TCDataHash *tcdatahash,
490 float tc_weight,
491 int count,
492 const DiphoneVoiceModule *dvm_p )
493
494{
495 int i=0;
496
497 if( count > 0 ){
498 TCData *tcd = tcdh->val( const_cast<EST_Item*>(target_ph1) );
499 EST_VTCandidate *nextc = 0;
500
501 // make last one first
502 EST_VTCandidate *c = makeCandidate( target_ph1, (*it), tc, tcd, tcdatahash, tc_weight, dvm_p );
503 c->next = nextc;
504 *tail = c;
505
506 // then iterate back prepending to linked list
507 // (order reversed because using c->next)
508 nextc = c;
509 it++; i++;
510 for( ; (it && i<count); it++, i++ ){
511 c = makeCandidate( target_ph1, (*it), tc, tcd, tcdatahash, tc_weight, dvm_p );
512 c->next = nextc;
513 nextc = c;
514 }
515
516 *head = c; // keep hold of last one set up
517 }
518
519 return;
520}
521
522int DiphoneVoiceModule::getCandidateList( const EST_Item& target,
523 const EST_TargetCost* tc,
524 const TCDataHash *tcdh,
525 float tc_weight,
526 EST_VTCandidate **head,
527 EST_VTCandidate **tail ) const
528{
529 int nfound = 0;
530 const EST_Item *target_ph1 = item(target.f("ph1"));
531
532 int found = 0;
533 const ItemList *candidateItemList = catalogue->val( target.S("name"), found );
534 if( found != 0 ){
535 nfound = candidateItemList->length();
536
537 ItemList::Entries it = ItemList::Entries(*candidateItemList);
538
539 itemListToCandidateList( it,
540 head, tail,
541 target_ph1,
542 tc, tcdh, tcdatahash, tc_weight,
543 nfound, this );
544 }
545
546 return nfound;
547}
548
549
550int DiphoneVoiceModule::getPhoneList( const EST_String &phone, ItemList &list )
551{
552 unsigned int n=0;
553
554 if( utt_dbase != 0 ){
555 for( EST_Litem *it=utt_dbase->head(); it!=0 ; it=it->next() ){
556 EST_Item *ph=(*utt_dbase)(it)->relation("Segment")->head();
557 for( ; ph!=0; ph=ph->next() ){
558 if( ph->S("name") == phone ){
559 list.append( ph );
560 n++;
561 }
562 }
563 }
564 }
565
566 return n;
567}
568
569bool DiphoneVoiceModule::getUtterance( EST_Utterance** utt, int n ) const
570{
571 if( n<0 || n>(utt_dbase->length()-1) )
1
Assuming 'n' is >= 0
2
Taking false branch
572 EST_error(EST_error_where = __null), (*EST_error_func)( "Utterance index out of bounds" );
573
574 if( utt == 0 )
3
Assuming 'utt' is equal to null
4
Taking true branch
575 EST_error(EST_error_where = __null), (*EST_error_func)( "Invalid utterance" );
576
577 // deep copy the utterance in question
578 *utt = new EST_Utterance( *(utt_dbase->nth(n)) );
5
Dereference of null pointer (loaded from variable 'utt')
579 CHECK_PTR(utt)if((utt)==0){ (EST_error_where = __null), (*EST_error_func)("memory allocation failed (file %s, line %d)"
, "DiphoneVoiceModule.cc",579);}
;
580
581 return true;
582}
583
584
585bool DiphoneVoiceModule::getUtterance( EST_Utterance **utt,
586 const EST_String &feat_name,
587 const EST_Val &value ) const
588{
589 //search down list of utterance structures, comparing
590 // fileid feature. If find a match, return pointer to that
591 // utterance.
592 for( EST_Litem *it=utt_dbase->head(); it!=0 ; it=it->next() )
593 if( (*utt_dbase)(it)->f.val(feat_name) == value ){
594 *utt = (*utt_dbase)(it);
595 return true;
596 }
597
598 return false;
599}
600
601void DiphoneVoiceModule::getDiphoneCoverageStats(EST_DiphoneCoverage *dc) const
602{
603 for( EST_Litem *it=utt_dbase->head(); it!=0 ; it=it->next() )
604 dc->add_stats((*utt_dbase)(it));
605}
606
607
608
609unsigned int DiphoneVoiceModule::numUnitTypes() const
610{
611 return catalogue ? catalogue->num_entries() : 0;
612}
613
614unsigned int DiphoneVoiceModule::numModuleUnits() const
615{
616 unsigned int sum=0;
617
618 if( catalogue != 0 ){
619 EST_TStringHash<ItemList*>::Entries it;
620
621 for( it.begin( *catalogue ); it; it++ )
622 sum += it->v->length(); //EST_UList.length() counts the entries :(
623 }
624
625 return sum;
626}
627
628
629unsigned int DiphoneVoiceModule::numAvailableCandidates( const EST_String &unit ) const
630{
631 int number=0;
632
633 int found=0;
634 const ItemList *candidateItemList = catalogue->val( unit, found );
635
636 if( found > 0 )
637 number = candidateItemList->length();
638
639 return number;
640}