| /*************************************************************************/ |
| /* */ |
| /* Language Technologies Institute */ |
| /* Carnegie Mellon University */ |
| /* Copyright (c) 2001 */ |
| /* All Rights Reserved. */ |
| /* */ |
| /* Permission is hereby granted, free of charge, to use and distribute */ |
| /* this software and its documentation without restriction, including */ |
| /* without limitation the rights to use, copy, modify, merge, publish, */ |
| /* distribute, sublicense, and/or sell copies of this work, and to */ |
| /* permit persons to whom this work is furnished to do so, subject to */ |
| /* the following conditions: */ |
| /* 1. The code must retain the above copyright notice, this list of */ |
| /* conditions and the following disclaimer. */ |
| /* 2. Any modifications must be clearly marked as such. */ |
| /* 3. Original authors' names are not deleted. */ |
| /* 4. The authors' names are not used to endorse or promote products */ |
| /* derived from this software without specific prior written */ |
| /* permission. */ |
| /* */ |
| /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */ |
| /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ |
| /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ |
| /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */ |
| /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ |
| /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ |
| /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ |
| /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ |
| /* THIS SOFTWARE. */ |
| /* */ |
| /*************************************************************************/ |
| /* Author: Alan W Black (awb@cs.cmu.edu) */ |
| /* Date: January 2001 */ |
| /*************************************************************************/ |
| /* */ |
| /* Diphone specific functions */ |
| /* */ |
| /*************************************************************************/ |
| |
| #include "cst_math.h" |
| #include "cst_hrg.h" |
| #include "cst_utt_utils.h" |
| #include "cst_wave.h" |
| #include "cst_track.h" |
| #include "cst_diphone.h" |
| #include "cst_units.h" |
| #include "cst_sigpr.h" |
| |
| CST_VAL_REGISTER_TYPE_NODEL(diphone_db,cst_diphone_db) |
| |
| static int get_diphone_entry(cst_diphone_db *udb,const char *name); |
| static int get_diphone_entry_bsearch(const cst_diphone_entry *entries, |
| int start, int end, |
| const char *key); |
| |
| cst_utterance* diphone_synth(cst_utterance *utt) |
| { |
| get_diphone_units(utt); |
| join_units(utt); |
| return utt; |
| } |
| |
| cst_utterance *get_diphone_units(cst_utterance *utt) |
| { |
| /* Select units from db with times etc */ |
| cst_relation *units; |
| cst_item *s0, *s1, *u; |
| float end0,end1; |
| char diphone_name[22]; |
| cst_diphone_db *udb; |
| int unit_entry = -1; |
| |
| udb = val_diphone_db(utt_feat_val(utt,"diphone_db")); |
| utt_set_feat(utt,"sts_list",sts_list_val(udb->sts)); |
| |
| units = utt_relation_create(utt,"Unit"); |
| |
| for (s0=relation_head(utt_relation(utt,"Segment")); |
| s0 && item_next(s0); s0=s1) |
| { |
| s1 = item_next(s0); |
| unit_entry = -1; |
| if (cst_streq("-",ffeature_string(s0,"ph_vc")) && |
| cst_streq("-",ffeature_string(s0,"R:SylStructure.n.ph_vc"))) |
| { /* Might have consonant cluster diphones */ |
| cst_sprintf(diphone_name, |
| "%.10s_-_%.10s", |
| item_name(s0), |
| item_name(s1)); |
| unit_entry = get_diphone_entry(udb,diphone_name); |
| } |
| |
| if (unit_entry == -1) /* no consonant cluster diphone */ |
| { |
| cst_sprintf(diphone_name, |
| "%.10s-%.10s", |
| item_name(s0), |
| item_name(s1)); |
| |
| unit_entry = get_diphone_entry(udb,diphone_name); |
| } |
| |
| if (unit_entry == -1) |
| { |
| cst_errmsg("flite: udb failed to find entry for: %s\n", |
| diphone_name); |
| unit_entry = 0; |
| } |
| |
| /* first half of diphone */ |
| u = relation_append(units,NULL); |
| item_add_daughter(s0,u); |
| item_set_string(u,"name",diphone_name); |
| end0 = item_feat_float(s0,"end"); |
| item_set_int(u,"target_end", (int)(end0*udb->sts->sample_rate)); |
| item_set_int(u,"unit_entry",unit_entry); |
| item_set_int(u,"unit_start",udb->diphones[unit_entry].start_pm); |
| item_set_int(u,"unit_end", |
| udb->diphones[unit_entry].start_pm + |
| udb->diphones[unit_entry].pb_pm); |
| /* second half of diphone */ |
| u = relation_append(units,NULL); |
| item_add_daughter(s1,u); |
| item_set_string(u,"name",diphone_name); |
| end1 = item_feat_float(s1,"end"); |
| item_set_int(u,"target_end",(int)(((end0+end1)/2.0)*udb->sts->sample_rate)); |
| item_set_int(u,"unit_entry",unit_entry); |
| item_set_int(u,"unit_start", |
| udb->diphones[unit_entry].start_pm + |
| udb->diphones[unit_entry].pb_pm); |
| item_set_int(u,"unit_end", |
| udb->diphones[unit_entry].start_pm + |
| udb->diphones[unit_entry].pb_pm+ |
| udb->diphones[unit_entry].end_pm); |
| } |
| |
| return utt; |
| } |
| |
| static int get_diphone_entry(cst_diphone_db *udb, const char *name) |
| { |
| return get_diphone_entry_bsearch(udb->diphones,0, |
| udb->num_entries, |
| name); |
| } |
| |
| static int get_diphone_entry_bsearch(const cst_diphone_entry *entries, |
| int start, int end, |
| const char *key) |
| { |
| int mid,c; |
| |
| while (start < end) |
| { |
| mid = (start+end)/2; |
| |
| c = strcmp(entries[mid].name,key); |
| |
| if (c == 0) |
| return mid; |
| else if (c > 0) |
| end = mid; |
| else |
| start = mid + 1; |
| } |
| |
| return -1; /* can't find it */ |
| } |
| |