1 /*
2  * Copyright (C) 2005 to 2010 by Jonathan Duddington
3  * email: jonsd@users.sourceforge.net
4  * Copyright (C) 2015-2017 Reece H. Dunn
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see: <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifdef __cplusplus
21 extern "C"
22 {
23 #endif
24 
25 // See docs/phonemes.md for the list of supported features.
26 typedef enum {
27 #	define FEATURE_T(a, b, c) ((a << 16) | (b << 8) | (c))
28 	// invalid phoneme feature name
29 	inv = 0,
30 	// manner of articulation
31 	nas = FEATURE_T('n', 'a', 's'),
32 	stp = FEATURE_T('s', 't', 'p'),
33 	afr = FEATURE_T('a', 'f', 'r'),
34 	frc = FEATURE_T('f', 'r', 'c'),
35 	flp = FEATURE_T('f', 'l', 'p'),
36 	trl = FEATURE_T('t', 'r', 'l'),
37 	apr = FEATURE_T('a', 'p', 'r'),
38 	clk = FEATURE_T('c', 'l', 'k'),
39 	ejc = FEATURE_T('e', 'j', 'c'),
40 	imp = FEATURE_T('i', 'm', 'p'),
41 	vwl = FEATURE_T('v', 'w', 'l'),
42 	lat = FEATURE_T('l', 'a', 't'),
43 	sib = FEATURE_T('s', 'i', 'b'),
44 	// place of articulation
45 	blb = FEATURE_T('b', 'l', 'b'),
46 	lbd = FEATURE_T('l', 'b', 'd'),
47 	bld = FEATURE_T('b', 'l', 'd'),
48 	dnt = FEATURE_T('d', 'n', 't'),
49 	alv = FEATURE_T('a', 'l', 'v'),
50 	pla = FEATURE_T('p', 'l', 'a'),
51 	rfx = FEATURE_T('r', 'f', 'x'),
52 	alp = FEATURE_T('a', 'l', 'p'),
53 	pal = FEATURE_T('p', 'a', 'l'),
54 	vel = FEATURE_T('v', 'e', 'l'),
55 	lbv = FEATURE_T('l', 'b', 'v'),
56 	uvl = FEATURE_T('u', 'v', 'l'),
57 	phr = FEATURE_T('p', 'h', 'r'),
58 	glt = FEATURE_T('g', 'l', 't'),
59 	// voice
60 	vcd = FEATURE_T('v', 'c', 'd'),
61 	vls = FEATURE_T('v', 'l', 's'),
62 	// vowel height
63 	hgh = FEATURE_T('h', 'g', 'h'),
64 	smh = FEATURE_T('s', 'm', 'h'),
65 	umd = FEATURE_T('u', 'm', 'd'),
66 	mid = FEATURE_T('m', 'i', 'd'),
67 	lmd = FEATURE_T('l', 'm', 'd'),
68 	sml = FEATURE_T('s', 'm', 'l'),
69 	low = FEATURE_T('l', 'o', 'w'),
70 	// vowel backness
71 	fnt = FEATURE_T('f', 'n', 't'),
72 	cnt = FEATURE_T('c', 'n', 't'),
73 	bck = FEATURE_T('b', 'c', 'k'),
74 	// rounding
75 	unr = FEATURE_T('u', 'n', 'r'),
76 	rnd = FEATURE_T('r', 'n', 'd'),
77 	// articulation
78 	lgl = FEATURE_T('l', 'g', 'l'),
79 	idt = FEATURE_T('i', 'd', 't'),
80 	apc = FEATURE_T('a', 'p', 'c'),
81 	lmn = FEATURE_T('l', 'm', 'n'),
82 	// air flow
83 	egs = FEATURE_T('e', 'g', 's'),
84 	igs = FEATURE_T('i', 'g', 's'),
85 	// phonation
86 	brv = FEATURE_T('b', 'r', 'v'),
87 	slv = FEATURE_T('s', 'l', 'v'),
88 	stv = FEATURE_T('s', 't', 'v'),
89 	crv = FEATURE_T('c', 'r', 'v'),
90 	glc = FEATURE_T('g', 'l', 'c'),
91 	// rounding and labialization
92 	ptr = FEATURE_T('p', 't', 'r'),
93 	cmp = FEATURE_T('c', 'm', 'p'),
94 	mrd = FEATURE_T('m', 'r', 'd'),
95 	lrd = FEATURE_T('l', 'r', 'd'),
96 	// syllabicity
97 	syl = FEATURE_T('s', 'y', 'l'),
98 	nsy = FEATURE_T('n', 's', 'y'),
99 	// consonant release
100 	asp = FEATURE_T('a', 's', 'p'),
101 	nrs = FEATURE_T('n', 'r', 's'),
102 	lrs = FEATURE_T('l', 'r', 's'),
103 	unx = FEATURE_T('u', 'n', 'x'),
104 	// coarticulation
105 	pzd = FEATURE_T('p', 'z', 'd'),
106 	vzd = FEATURE_T('v', 'z', 'd'),
107 	fzd = FEATURE_T('f', 'z', 'd'),
108 	nzd = FEATURE_T('n', 'z', 'd'),
109 	rzd = FEATURE_T('r', 'z', 'd'),
110 	// tongue root
111 	atr = FEATURE_T('a', 't', 'r'),
112 	rtr = FEATURE_T('r', 't', 'r'),
113 	// fortis and lenis
114 	fts = FEATURE_T('f', 't', 's'),
115 	lns = FEATURE_T('l', 'n', 's'),
116 	// length
117 	est = FEATURE_T('e', 's', 't'),
118 	hlg = FEATURE_T('h', 'l', 'g'),
119 	lng = FEATURE_T('l', 'n', 'g'),
120 	elg = FEATURE_T('e', 'l', 'g'),
121 #	undef FEATURE_T
122 } phoneme_feature_t;
123 
124 phoneme_feature_t phoneme_feature_from_string(const char *feature);
125 
126 // phoneme types
127 #define phPAUSE   0
128 #define phSTRESS  1
129 #define phVOWEL   2
130 #define phLIQUID  3
131 #define phSTOP    4
132 #define phVSTOP   5
133 #define phFRICATIVE 6
134 #define phVFRICATIVE 7
135 #define phNASAL   8
136 #define phVIRTUAL 9
137 #define phDELETED 14
138 #define phINVALID 15
139 
140 // places of articulation (phARTICULATION)
141 #define phPLACE_BILABIAL 1
142 #define phPLACE_LABIODENTAL 2
143 #define phPLACE_DENTAL 3
144 #define phPLACE_ALVEOLAR 4
145 #define phPLACE_RETROFLEX 5
146 #define phPLACE_PALATO_ALVEOLAR 6
147 #define phPLACE_PALATAL 7
148 #define phPLACE_VELAR 8
149 #define phPLACE_LABIO_VELAR 9
150 #define phPLACE_UVULAR 10
151 #define phPLACE_PHARYNGEAL 11
152 #define phPLACE_GLOTTAL 12
153 
154 // phflags
155 #define phFLAGBIT_UNSTRESSED 1
156 #define phFLAGBIT_VOICELESS 3
157 #define phFLAGBIT_VOICED 4
158 #define phFLAGBIT_SIBILANT 5
159 #define phFLAGBIT_NOLINK 6
160 #define phFLAGBIT_TRILL 7
161 #define phFLAGBIT_PALATAL 9
162 #define phFLAGBIT_BRKAFTER 14 // [*] add a post-pause
163 #define phARTICULATION 0xf0000 // bits 16-19
164 #define phFLAGBIT_NONSYLLABIC 20 // don't count this vowel as a syllable when finding the stress position
165 #define phFLAGBIT_LONG 21
166 #define phFLAGBIT_LENGTHENSTOP 22 // make the pre-pause slightly longer
167 #define phFLAGBIT_RHOTIC 23
168 #define phFLAGBIT_NOPAUSE 24
169 #define phFLAGBIT_PREVOICE 25 // for voiced stops
170 #define phFLAGBIT_FLAG1 28
171 #define phFLAGBIT_FLAG2 29
172 #define phFLAGBIT_LOCAL 31 // used during compilation
173 
174 // phoneme properties
175 #define phUNSTRESSED   (1 << phFLAGBIT_UNSTRESSED)
176 #define phVOICELESS    (1 << phFLAGBIT_VOICELESS)
177 #define phVOICED       (1 << phFLAGBIT_VOICED)
178 #define phSIBILANT     (1 << phFLAGBIT_SIBILANT)
179 #define phNOLINK       (1 << phFLAGBIT_NOLINK)
180 #define phTRILL        (1 << phFLAGBIT_TRILL)
181 #define phPALATAL      (1 << phFLAGBIT_PALATAL)
182 #define phBRKAFTER     (1 << phFLAGBIT_BRKAFTER)
183 #define phNONSYLLABIC  (1 << phFLAGBIT_NONSYLLABIC)
184 #define phLONG         (1 << phFLAGBIT_LONG)
185 #define phLENGTHENSTOP (1 << phFLAGBIT_LENGTHENSTOP)
186 #define phRHOTIC       (1 << phFLAGBIT_RHOTIC)
187 #define phNOPAUSE      (1 << phFLAGBIT_NOPAUSE)
188 #define phPREVOICE     (1 << phFLAGBIT_PREVOICE)
189 #define phFLAG1        (1 << phFLAGBIT_FLAG1)
190 #define phFLAG2        (1 << phFLAGBIT_FLAG2)
191 #define phLOCAL        (1 << phFLAGBIT_LOCAL)
192 
193 // fixed phoneme code numbers, these can be used from the program code
194 #define phonCONTROL     1
195 #define phonSTRESS_U    2
196 #define phonSTRESS_D    3
197 #define phonSTRESS_2    4
198 #define phonSTRESS_3    5
199 #define phonSTRESS_P    6
200 #define phonSTRESS_P2   7    // priority stress within a word
201 #define phonSTRESS_PREV 8
202 #define phonPAUSE       9
203 #define phonPAUSE_SHORT 10
204 #define phonPAUSE_NOLINK 11
205 #define phonLENGTHEN    12
206 #define phonSCHWA       13
207 #define phonSCHWA_SHORT 14
208 #define phonEND_WORD    15
209 #define phonDEFAULTTONE 17
210 #define phonCAPITAL     18
211 #define phonGLOTTALSTOP 19
212 #define phonSYLLABIC    20
213 #define phonSWITCH      21
214 #define phonX1          22      // a language specific action
215 #define phonPAUSE_VSHORT 23
216 #define phonPAUSE_LONG  24
217 #define phonT_REDUCED   25
218 #define phonSTRESS_TONIC 26
219 #define phonPAUSE_CLAUSE 27
220 #define phonVOWELTYPES   28  // 28 to 33
221 
222 extern const unsigned char pause_phonemes[8];  // 0, vshort, short, pause, long, glottalstop
223 
224 #define N_PHONEME_TABS     150     // number of phoneme tables
225 #define N_PHONEME_TAB      256     // max phonemes in a phoneme table
226 #define N_PHONEME_TAB_NAME  32     // must be multiple of 4
227 
228 // main table of phonemes, index by phoneme number (1-254)
229 
230 typedef struct {
231 	unsigned int mnemonic;       // Up to 4 characters.  The first char is in the l.s.byte
232 	unsigned int phflags;        // bits 16-19 place of articulation
233 	unsigned short program;      // index into phondata file
234 	unsigned char code;          // the phoneme number
235 	unsigned char type;          // phVOWEL, phPAUSE, phSTOP etc
236 	unsigned char start_type;
237 	unsigned char end_type;      // vowels: endtype; consonant: voicing switch
238 	unsigned char std_length;    // for vowels, in mS/2;  for phSTRESS phonemes, this is the stress/tone type
239 	unsigned char length_mod;    // a length_mod group number, used to access length_mod_tab
240 } PHONEME_TAB;
241 
242 espeak_ng_STATUS
243 phoneme_add_feature(PHONEME_TAB *phoneme,
244                     phoneme_feature_t feature);
245 
246 // Several phoneme tables may be loaded into memory. phoneme_tab points to
247 // one for the current voice
248 extern int n_phoneme_tab;
249 extern int current_phoneme_table;
250 extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
251 extern unsigned char phoneme_tab_flags[N_PHONEME_TAB];  // bit 0: not inherited
252 
253 typedef struct {
254 	char name[N_PHONEME_TAB_NAME];
255 	PHONEME_TAB *phoneme_tab_ptr;
256 	int n_phonemes;
257 	int includes;            // also include the phonemes from this other phoneme table
258 } PHONEME_TAB_LIST;
259 
260 // table of phonemes to be replaced with different phonemes, for the current voice
261 #define N_REPLACE_PHONEMES   60
262 typedef struct {
263 	unsigned char old_ph;
264 	unsigned char new_ph;
265 	char type;   // 0=always replace, 1=only at end of word
266 } REPLACE_PHONEMES;
267 
268 extern int n_replace_phonemes;
269 extern REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES];
270 
271 // Table of phoneme programs and lengths.  Used by MakeVowelLists
272 typedef struct {
273 	unsigned int addr;
274 	unsigned int length;
275 } PHONEME_PROG_LOG;
276 
277 #define PH(c1, c2) (c2<<8)+c1          // combine two characters into an integer for phoneme name
278 #define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1
279 #define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1)
280 int LookupPhonemeString(const char *string);
281 int PhonemeCode(unsigned int mnem);
282 
283 const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme);
284 void DecodePhonemes(const char *inptr, char *outptr);
285 
286 extern const char *WordToString(unsigned int word);
287 
288 extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS];
289 extern int phoneme_tab_number;
290 
291 #ifdef __cplusplus
292 }
293 #endif
294