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