1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1998 */
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 /* THE UNIVERSITY OF EDINBURGH 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 THE UNIVERSITY OF EDINBURGH 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 and Paul Taylor */
34 /* Date : February 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* */
37 /* An implementation of Metrical Tree Phonology */
38 /* */
39 /*=======================================================================*/
40
41 #include "festival.h"
42
43 void main_stress(EST_Item *s);
44
45 void subword_metrical_tree(EST_Relation &syllable,
46 EST_Relation &metricaltree);
47
48 EST_Item *make_foot(EST_Item *w, EST_Item *met_node, EST_Item *next_syl_node);
49 void subword_metrical_tree(EST_Item *w, EST_Relation &syllable,
50 EST_Relation &metricaltree);
51
52 static void all_stress(EST_Relation &syllable, EST_Relation &mettree);
53
54 static void make_super_foot(EST_Item *w, EST_Item *met_node,
55 EST_Item *next_syl_node);
56
57 // Note: this function doesn't work as it should: currently a
58 // monosyllabic word ends up being the same item as the syllable, when
59 // a single daughter item would be better.
60
subword_list(EST_Item * w,EST_Relation & syllable,EST_Relation & metricaltree)61 void subword_list(EST_Item *w, EST_Relation &syllable,
62 EST_Relation &metricaltree)
63 {
64 EST_Item *s, *n;
65
66 n = metricaltree.append(w);
67
68 if (next(syllable.head()) == 0)
69 return;
70
71 for (s = syllable.head(); s ; s = s->next())
72 {
73 cout << "appending syl\n";
74 n->append_daughter(s);
75 }
76 }
77
subword_metrical_tree(EST_Item * w,EST_Relation & syllable,EST_Relation & metricaltree)78 void subword_metrical_tree(EST_Item *w, EST_Relation &syllable,
79 EST_Relation &metricaltree)
80 {
81 EST_Item *s;
82 EST_Item *new_leaf;
83
84 // single syllable
85 if (next(syllable.head()) == 0)
86 {
87 new_leaf = metricaltree.append(w);
88 return;
89 }
90
91 // absorb initial unstressed syllables
92 for (s = syllable.head(); s && (s->f("stress_num") == 0); s = s->next())
93 {
94 new_leaf = metricaltree.append(s);
95 new_leaf->set("MetricalValue", "w");
96 }
97
98 while (s)
99 {
100 new_leaf = metricaltree.append(s);
101 new_leaf->set("MetricalValue", "s");
102 s = make_foot(w, new_leaf, next(s));
103 }
104
105 if (siod_get_lval("mettree_debug", NULL) != NIL)
106 metricaltree.utt()->save("foot.utt", "est");
107
108 s = metricaltree.head();
109 make_super_foot(w, s, next(s));
110
111 if (siod_get_lval("mettree_debug", NULL) != NIL)
112 metricaltree.utt()->save("super_foot.utt", "est");
113
114 all_stress(syllable, metricaltree);
115 }
116
117
make_foot(EST_Item * w,EST_Item * met_node,EST_Item * next_syl_node)118 EST_Item *make_foot(EST_Item *w, EST_Item *met_node, EST_Item *next_syl_node)
119 {
120 EST_Item *new_parent;
121 EST_Item *fl;
122
123 if (next_syl_node == 0)
124 return 0;
125
126 if (next_syl_node->f("stress_num") == 0)
127 {
128 met_node->set("MetricalValue", "s");
129 next_syl_node->set("MetricalValue", "w");
130
131 fl = first_leaf(met_node);
132
133 if (next(next_syl_node))
134 new_parent = met_node->insert_parent();
135 else
136 {
137 if (prev(fl))
138 new_parent = met_node->insert_parent();
139 else
140 {
141 // cout << "making met node word node in foot\n";
142 // cout << "foot root:" << *w << endl;
143 new_parent = met_node->insert_parent();
144 // new_parent = met_node->insert_above(w);
145 merge_item(new_parent, w);
146 // cout << "foot root:" << *w << endl;
147 // cout << "foot root:" << *new_parent << endl;
148 }
149
150 }
151 new_parent->append_daughter(next_syl_node);
152
153 next_syl_node = make_foot(w, new_parent, next(next_syl_node));
154 }
155 return next_syl_node;
156 }
157
158 // construct left branching unlabelled tree using feet roots as terminals
make_super_foot(EST_Item * w,EST_Item * met_node,EST_Item * next_syl_node)159 static void make_super_foot(EST_Item *w, EST_Item *met_node,
160 EST_Item *next_syl_node)
161 {
162 EST_Item *new_parent;
163
164 if (next_syl_node == 0)
165 return;
166
167 // make sure root node is w, i.e. word
168 if (next(next_syl_node))
169 new_parent = met_node->insert_parent();
170 else
171 {
172 // cout << "inserted word as root in super foot:" << *w << endl;
173 new_parent = met_node->insert_parent();
174
175 // KTH this crashes in linux
176 merge_item(new_parent, w);
177 // cout << "after inserted word as root in super foot:" << *w << endl;
178 // cout << "after inserted word as root in super foot:" <<
179 // *new_parent << endl;
180 // w = new_parent->as_relation("Word");
181 }
182
183 new_parent->append_daughter(next_syl_node);
184
185 make_super_foot(w, new_parent, next(new_parent));
186 }
187
188
all_stress(EST_Relation & syllable,EST_Relation & mettree)189 static void all_stress(EST_Relation &syllable, EST_Relation &mettree)
190 {
191 EST_Item *n, *s;
192 int stress_num = -1;
193
194 for (s = syllable.head(); s; s = s->next())
195 if (s->I("stress_num",0) > stress_num)
196 stress_num = s->I("stress_num");
197
198 // cout << "max stress num:" << stress_num << endl;
199
200 for (; stress_num > 0; --stress_num)
201 {
202 for (s = syllable.head(); s; s = s->next())
203 if (s->I("stress_num",0) == stress_num)
204 break;
205
206 if (s == 0)
207 {
208 cerr << "No main stress found in definition of lexical entry\n";
209 festival_error();
210 }
211
212 n = s->as_relation(mettree.name());
213 main_stress(n);
214 }
215 }
216
217