1 /*************************************************************************/
2 /*                                                                       */
3 /*                  Language Technologies Institute                      */
4 /*                     Carnegie Mellon University                        */
5 /*                         Copyright (c) 2001                            */
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:  Alan W Black (awb@cs.cmu.edu)                    */
34 /*               Date:  January 2001                                     */
35 /*************************************************************************/
36 /*                                                                       */
37 /*  Diphone specific functions                                           */
38 /*                                                                       */
39 /*************************************************************************/
40 
41 #include "cst_math.h"
42 #include "cst_hrg.h"
43 #include "cst_utt_utils.h"
44 #include "cst_wave.h"
45 #include "cst_track.h"
46 #include "cst_diphone.h"
47 #include "cst_units.h"
48 #include "cst_sigpr.h"
49 
50 CST_VAL_REGISTER_TYPE_NODEL(diphone_db,cst_diphone_db)
51 
52 static int get_diphone_entry(cst_diphone_db *udb,const char *name);
53 static int get_diphone_entry_bsearch(const cst_diphone_entry *entries,
54 				     int start, int end,
55 				     const char *key);
56 
diphone_synth(cst_utterance * utt)57 cst_utterance* diphone_synth(cst_utterance *utt)
58 {
59     get_diphone_units(utt);
60     join_units(utt);
61     return utt;
62 }
63 
get_diphone_units(cst_utterance * utt)64 cst_utterance *get_diphone_units(cst_utterance *utt)
65 {
66     /* Select units from db with times etc */
67     cst_relation *units;
68     cst_item *s0, *s1, *u;
69     float end0,end1;
70     char diphone_name[22];
71     cst_diphone_db *udb;
72     int unit_entry = -1;
73 
74     udb = val_diphone_db(utt_feat_val(utt,"diphone_db"));
75     utt_set_feat(utt,"sts_list",sts_list_val(udb->sts));
76 
77     units = utt_relation_create(utt,"Unit");
78 
79     for (s0=relation_head(utt_relation(utt,"Segment"));
80 	 s0 && item_next(s0); s0=s1)
81     {
82 	s1 = item_next(s0);
83         unit_entry = -1;
84         if (cst_streq("-",ffeature_string(s0,"ph_vc")) &&
85             cst_streq("-",ffeature_string(s0,"R:SylStructure.n.ph_vc")))
86         {   /* Might have consonant cluster diphones */
87             cst_sprintf(diphone_name,
88                         "%.10s_-_%.10s",
89                         item_name(s0),
90                         item_name(s1));
91             unit_entry = get_diphone_entry(udb,diphone_name);
92         }
93 
94         if (unit_entry == -1) /* no consonant cluster diphone */
95         {
96             cst_sprintf(diphone_name,
97                         "%.10s-%.10s",
98                         item_name(s0),
99                         item_name(s1));
100 
101             unit_entry = get_diphone_entry(udb,diphone_name);
102         }
103 
104 	if (unit_entry == -1)
105 	{
106 	    cst_errmsg("flite: udb failed to find entry for: %s\n",
107 		       diphone_name);
108 	    unit_entry = 0;
109 	}
110 
111 	/* first half of diphone */
112 	u = relation_append(units,NULL);
113 	item_add_daughter(s0,u);
114 	item_set_string(u,"name",diphone_name);
115 	end0 = item_feat_float(s0,"end");
116 	item_set_int(u,"target_end", (int)(end0*udb->sts->sample_rate));
117 	item_set_int(u,"unit_entry",unit_entry);
118 	item_set_int(u,"unit_start",udb->diphones[unit_entry].start_pm);
119 	item_set_int(u,"unit_end",
120 		     udb->diphones[unit_entry].start_pm +
121 		     udb->diphones[unit_entry].pb_pm);
122 	/* second half of diphone */
123 	u = relation_append(units,NULL);
124 	item_add_daughter(s1,u);
125 	item_set_string(u,"name",diphone_name);
126 	end1 = item_feat_float(s1,"end");
127 	item_set_int(u,"target_end",(int)(((end0+end1)/2.0)*udb->sts->sample_rate));
128 	item_set_int(u,"unit_entry",unit_entry);
129 	item_set_int(u,"unit_start",
130 		     udb->diphones[unit_entry].start_pm +
131 		     udb->diphones[unit_entry].pb_pm);
132 	item_set_int(u,"unit_end",
133 		     udb->diphones[unit_entry].start_pm +
134 		     udb->diphones[unit_entry].pb_pm+
135 		     udb->diphones[unit_entry].end_pm);
136     }
137 
138     return utt;
139 }
140 
get_diphone_entry(cst_diphone_db * udb,const char * name)141 static int get_diphone_entry(cst_diphone_db *udb, const char *name)
142 {
143     return get_diphone_entry_bsearch(udb->diphones,0,
144 				     udb->num_entries,
145 				     name);
146 }
147 
get_diphone_entry_bsearch(const cst_diphone_entry * entries,int start,int end,const char * key)148 static int get_diphone_entry_bsearch(const cst_diphone_entry *entries,
149 				     int start, int end,
150 				     const char *key)
151 {
152     int mid,c;
153 
154     while (start < end)
155     {
156 	mid = (start+end)/2;
157 
158 	c = strcmp(entries[mid].name,key);
159 
160 	if (c == 0)
161 	    return mid;
162 	else if (c > 0)
163 	    end = mid;
164 	else
165 	    start = mid + 1;
166     }
167 
168     return -1;  /* can't find it */
169 }
170 
171