1 /* VocalTract.cpp
2  *
3  * Copyright (C) 1992-2008,2011,2012,2015-2020 Paul Boersma
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this work. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "VocalTract.h"
20 
21 Thing_implement (VocalTract, Vector, 2);
22 
23 void structVocalTract :: v_info () {
24 	structDaata :: v_info ();
25 	MelderInfo_writeLine (U"Vocal tract length: ", Melder_single (xmax), U" metres");
26 	MelderInfo_writeLine (U"Number of sections: ", nx);
27 	MelderInfo_writeLine (U"Section length: ", Melder_single (dx), U" metres");
28 }
29 
30 autoVocalTract VocalTract_create (integer nx, double dx) {
31 	try {
32 		autoVocalTract me = Thing_new (VocalTract);
33 		Matrix_init (me.get(), 0.0, nx * dx, nx, dx, 0.5 * dx, 1.0, 1.0, 1, 1.0, 1.0);
34 		return me;
35 	} catch (MelderError) {
36 		Melder_throw (U"VocalTract not created.");
37 	}
38 }
39 
40 namespace theVocalTract {
41 	constexpr double minimumWidth { 0.0001 };
42 	struct { conststring32 phone; int numberOfSections; double area [40]; }
43 		data [] = {
44 	{ U"a", 34, { 1.7, 1.2, 1.6, 3.39, 2.1, 1.4, 1, 0.8, 0.8, 0.8, 1, 1.4,
45 		2.1, 2.9, 3.09, 2.1, 2.5, 4, 5.3, 6.16, 7, 7.6, 8.15, 8.5, 8.6,
46 		8.4, 8, 7.5, 6.9, 6, 5.1, 5, 5.5, 7.9 } },
47 	{ U"e", 33, { 2.3, 1.95, 1.73, 1.7, 5.3, 6.3, 6.8, 7.55, 8.2, 9.1, 9.7,
48 		10.1, 10.2, 10, 8, 7.2, 7.5, 6.4, 5.4, 4.9, 4.35, 3.9, 3.5, 3.1,
49 		2.7, 2.4, 2.2, 2.5, 3.4, 5, 6.7, 8.5, 10 } },
50 	{ U"i", 35, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
51 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
52 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 5, 8 } },
53 	{ U"o", 37, { 2.6, 2.05, 1.56, 1.3, 5.2, 4.54, 3.49, 2.6, 2.1, 1.8, 1.6, 1.4,
54 		1.29, 1.19, 1.22, 2.6, 2.9, 2.2, 2.6, 3.6, 4.55, 5.55, 6.4, 7.15,
55 		8, 8.9, 9.6, 10.5, 11.8, 14.6, 14.5, 12.9, 10.4, 5, 3.4, 3.4, 4 } },
56 	{ U"u", 40, { 2.5, 2.5, 2.5, 2.4, 5, 8.1, 8.9, 8.9, 8.4, 7.5, 5.8, 3.9, 2.3, 1.6, 1.2,
57 		1.05, 1.1, 1.4, 2.2, 2, 1.3, 2, 2.2, 2.3, 2.8, 3.7, 5, 6.2, 7.9,
58 		10.9, 12.9, 13.15, 13, 12.5, 9.9, 3.9, 1.8, 0.32, 0.4, 0.6 } },
59 	{ U"y1", 37, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
60 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
61 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 1.8, 0.32,
62 		0.4, 0.6 } },
63 	{ U"y2", 38, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
64 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
65 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 4, 1.8, 0.32,
66 		0.4, 0.6 } },
67 	{ U"y3", 39, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
68 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
69 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 4, 4, 1.8, 0.32,
70 		0.4, 0.6 } },
71 	{ U"jery", 38, { 3.2, 3.2, 3.2, 3.2, 10.5, 10.5, 13, 13, 10.5, 10.5, 10.5, 10.5, 10.5,
72 		8, 6.5, 6.5, 5, 4, 2, 2.6, 1.6, 1.3, 1, 1, 1.3, 1.6, 2, 2, 2.6, 3.2, 5,
73 		8, 8, 8, 6.5,
74 		2, 6.5, 6.5 } },
75 	{ U"p", 39, { 3.5, 3.2, 2.9, 2.6, 6.9, 6.65, 5.8, 4.9, 4, 3.14, 2.5, 1.84,
76 		1.25, 0.83, 0.6, 0.53,
77 		0.5, 0.6, 0.85, 1, 1.6, 2.05, 2.55, 3.08, 3.67, 4.15, 4.8, 5.5, 6.3,
78 		7.4, 12, 12.98, 12.9, 11.4, 6.6, 2, 0.45, 0.1, minimumWidth } },
79 	{ U"t", 36, { 2.8, 2.7, 2.4, 2.6, 6.45, 6.01, 5.31, 4.85, 4.55, 4.32, 4.18, 4.1,
80 		4.04, 3.97, 3.85, 3.7, 3.4, 3.05, 2.91, 3.1, 3.55, 3.9, 4.1, 4, 3.8,
81 		3.3, 2.55, 1.8, 1, 0.45, 0.1, minimumWidth, 0.8, 2.5, 6, 9 } },
82 	{ U"k", 38, { 2.4, 2.7, 3, 3.3, 7, 9.38, 9.25, 8.62, 7.8, 6.7, 5.4, 4, 2.8, 1.9, 1.35,
83 		0.9, 0.55, 0.3, 0.19, 0.07, minimumWidth, 0.12, 0.17, 0.3, 0.5, 0.9,
84 		1.4, 2.2, 3.3, 5, 9, 11.25, 10.9, 7.3, 4.3, 3.5, 3.7, 6 } },
85 	{ U"x", 40, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
86 		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 } },
87 	{ U"pa", 39, { 1.7, 1.2, 1.6, 3.39, 2.1, 1.4, 1, 0.8, 0.8, 0.8, 1, 1.4,
88 		2.1, 2.9, 3.09, 2.1, 2.5, 4, 5.3, 6.16, 7, 7.6, 8.15, 8.5, 8.6,
89 		8.4, 8, 7.5, 6.9, 6, 5.1, 5, 5.5, 7.9, 6.6, 2, 0.45, 0.1,
90 		minimumWidth } },
91 	{ U"ta", 34, { 1.7, 1.2, 1.6, 3.39, 2.1, 1.4, 1, 0.8, 0.8, 0.8, 1, 1.4,
92 		2.1, 2.9, 3.09, 2.1, 2.5, 4, 5.3, 6.16, 7, 7.6, 8.15, 8.5, 8.6,
93 		8.5, 6, 2, 0.45, minimumWidth, 0.8, 2.5, 5.5, 7.9 } },
94 	{ U"ka", 34, { 1.7, 1.2, 1.6, 3.39, 2.1, 1.4, 1, 0.8, 0.8, 0.8, 1, 1.4,
95 		2.1, 2.9, 3.09, 2.1, 0.3, minimumWidth,
96 		0.3, 2, 5, 7.6, 8.15, 8.5, 8.6,
97 		8.4, 8, 7.5, 6.9, 6, 5.1, 5, 5.5, 7.9 } },
98 	{ U"pi", 39, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
99 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
100 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 5,
101 		6.6, 2, 0.45, 0.1, minimumWidth } },
102 	{ U"ti", 35, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
103 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 7.8, 7, 4.5, 2.8, 1.9, 1.3,
104 		0.9, 0.65, 0.55, 0.5, 0.5, 0.5, 0.3, 0.1, minimumWidth,
105 		0.8, 2.5, 8 } },
106 	{ U"ki", 35, { 3, 2.9, 2.75, 2.58, 2.7, 6.35, 7.8, 8.9, 9.6, 10.15, 10.55,
107 		10.9, 11.15, 11.3, 11.2, 10.8, 8, 6, 2, 0.3, minimumWidth, 0.3, 1.3,
108 		0.9, 0.65, 0.55, 0.5, 0.55, 0.7, 0.95, 1.3, 2, 3, 5, 8 } },
109 	{ U"pu", 40, { 2.5, 2.5, 2.5, 2.4, 5, 8.1, 8.9, 8.9, 8.4, 7.5, 5.8, 3.9, 2.3, 1.6, 1.2,
110 		1.05, 1.1, 1.4, 2.2, 2, 1.3, 2, 2.2, 2.3, 2.8, 3.7, 5, 6.2, 7.9,
111 		10.9, 12.9, 13.15, 13, 12.5, 9.9, 6.6, 2, 0.45, 0.1, minimumWidth } },
112 	{ U"tu", 40, { 2.5, 2.5, 2.5, 2.4, 5, 8.1, 8.9, 8.9, 8.4, 7.5, 5.8, 3.9, 2.3, 1.6, 1.2,
113 		1.05, 1.1, 1.4, 2.2, 2, 1.3, 2, 2.2, 2.3, 2.8, 3.7, 5, 6.2, 7.9,
114 		10.9, 9, 3, 0.4, minimumWidth, 0.8, 2.5, 1.8, 0.32, 0.4, 0.6 } },
115 	{ U"ku", 40, { 2.5, 2.5, 2.5, 2.4, 5, 8.1, 8.9, 8.9, 8.4, 7.5, 5.8, 3.9, 2.3, 1.6, 1.2,
116 		1.05, 1.1, 1.4, 1.2, 0.3, minimumWidth, 0.3, 2.2, 2.3, 2.8, 3.7, 5, 6.2, 7.9,
117 		10.9, 12.9, 13.15, 13, 12.5, 9.9, 3.9, 1.8, 0.32, 0.4, 0.6 } },
118 	{ nullptr, 0, { 0 } } };
119 }
120 
121 autoVocalTract VocalTract_createFromPhone (conststring32 phone) {
122 	try {
123 		int i = 0;
124 		for (;; i ++) {
125 			if (! theVocalTract::data [i]. phone)
126 				Melder_throw (U"Unknown phone ", phone);
127 			if (Melder_equ (theVocalTract::data [i]. phone, phone))
128 				break;
129 		}
130 		autoVocalTract me = VocalTract_create (theVocalTract::data [i]. numberOfSections, 0.005);
131 		for (int isection = 1; isection <= my nx; isection ++)
132 			my z [1] [isection] = theVocalTract::data [i]. area [isection - 1] * 0.0001;
133 		return me;
134 	} catch (MelderError) {
135 		Melder_throw (U"VocalTract not created from phone.");
136 	}
137 }
138 
139 void VocalTract_draw (VocalTract me, Graphics g) {
140 	Matrix_drawRows (me, g, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
141 }
142 
143 autoMatrix VocalTract_to_Matrix (VocalTract me) {
144 	try {
145 		autoMatrix thee = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, my ymin, my ymax, my ny, my dy, my y1);
146 		thy z.all()  <<=  my z.all();
147 		return thee;
148 	} catch (MelderError) {
149 		Melder_throw (me, U": not converted to Matrix.");
150 	}
151 }
152 
153 autoVocalTract Matrix_to_VocalTract (Matrix me) {
154 	try {
155 		autoVocalTract thee = VocalTract_create (my nx, my dx);
156 		thy z.all()  <<=  my z.all();
157 		return thee;
158 	} catch (MelderError) {
159 		Melder_throw (me, U": not converted to VocalTract.");
160 	}
161 }
162 
163 /* End of file VocalTract.cpp */
164