1 /***************************************************************************
2  *   Copyright (C) 2005 to 2013 by Jonathan Duddington                     *
3  *   email: jonsd@users.sourceforge.net                                    *
4  *                                                                         *
5  *   This program 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 3 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   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 program; if not, see:                                 *
17  *               <http://www.gnu.org/licenses/>.                           *
18  ***************************************************************************/
19 
20 
21 #include "StdAfx.h"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <wctype.h>
27 #include <string.h>
28 
29 
30 #include "speak_lib.h"
31 #include "speech.h"
32 #include "phoneme.h"
33 #include "synthesize.h"
34 #include "voice.h"
35 #include "translate.h"
36 #include "wave.h"
37 
38 const char *version_string = "1.48.03  04.Mar.14";
39 const int version_phdata  = 0x014801;
40 
41 int option_device_number = -1;
42 FILE *f_logespeak = NULL;
43 int logging_type;
44 
45 // copy the current phoneme table into here
46 int n_phoneme_tab;
47 int current_phoneme_table;
48 PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
49 unsigned char phoneme_tab_flags[N_PHONEME_TAB];   // bit 0: not inherited
50 
51 USHORT *phoneme_index=NULL;
52 char *phondata_ptr=NULL;
53 unsigned char *wavefile_data=NULL;
54 static unsigned char *phoneme_tab_data = NULL;
55 
56 int n_phoneme_tables;
57 PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS];
58 int phoneme_tab_number = 0;
59 
60 int wavefile_ix;              // a wavefile to play along with the synthesis
61 int wavefile_amp;
62 int wavefile_ix2;
63 int wavefile_amp2;
64 
65 int seq_len_adjust;
66 int vowel_transition[4];
67 int vowel_transition0;
68 int vowel_transition1;
69 
70 int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which);
71 
72 
73 
ReadPhFile(void * ptr,const char * fname,int * size)74 static char *ReadPhFile(void *ptr, const char *fname, int *size)
75 {//=============================================================
76 	FILE *f_in;
77 	char *p;
78 	unsigned int  length;
79 	char buf[sizeof(path_home)+40];
80 
81 	sprintf(buf,"%s%c%s",path_home,PATHSEP,fname);
82 	length = GetFileLength(buf);
83 
84 	if((f_in = fopen(buf,"rb")) == NULL)
85 	{
86 		fprintf(stderr,"Can't read data file: '%s'\n",buf);
87 		return(NULL);
88 	}
89 
90 	if(ptr != NULL)
91 		Free(ptr);
92 
93 	if((p = Alloc(length)) == NULL)
94 	{
95 		fclose(f_in);
96 		return(NULL);
97 	}
98 	if(fread(p,1,length,f_in) != length)
99 	{
100 		fclose(f_in);
101 		return(NULL);
102 	}
103 
104 	fclose(f_in);
105 	if(size != NULL)
106 		*size = length;
107 	return(p);
108 }  //  end of ReadPhFile
109 
110 
LoadPhData(int * srate)111 int LoadPhData(int *srate)
112 {//========================
113 	int ix;
114 	int n_phonemes;
115 	int version;
116 	int result = 1;
117 	int length;
118 	int rate;
119 	unsigned char *p;
120 	int *pw;
121 
122 	if((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data),"phontab",NULL)) == NULL)
123 		return(-1);
124 	if((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index),"phonindex",NULL)) == NULL)
125 		return(-1);
126 	if((phondata_ptr = ReadPhFile((void *)(phondata_ptr),"phondata",NULL)) == NULL)
127 		return(-1);
128 	if((tunes = (TUNE *)ReadPhFile((void *)(tunes),"intonations",&length)) == NULL)
129 		return(-1);
130     wavefile_data = (unsigned char *)phondata_ptr;
131 	n_tunes = length / sizeof(TUNE);
132 
133 	// read the version number and sample rate from the first 8 bytes of phondata
134 	version = 0;  // bytes 0-3, version number
135 	rate = 0;     // bytes 4-7, sample rate
136 	for(ix=0; ix<4; ix++)
137 	{
138 		version += (wavefile_data[ix] << (ix*8));
139 		rate += (wavefile_data[ix+4] << (ix*8));
140 	}
141 
142 	if(version != version_phdata)
143 	{
144 		result = version;
145 	}
146 
147 	// set up phoneme tables
148 	p = phoneme_tab_data;
149 	n_phoneme_tables = p[0];
150 	p+=4;
151 
152 	for(ix=0; ix<n_phoneme_tables; ix++)
153 	{
154 		n_phonemes = p[0];
155 		phoneme_tab_list[ix].n_phonemes = p[0];
156 		phoneme_tab_list[ix].includes = p[1];
157 		pw = (int *)p;
158 		phoneme_tab_list[ix].equivalence_tables = Reverse4Bytes(pw[1]);
159 		p += 8;
160 		memcpy(phoneme_tab_list[ix].name,p,N_PHONEME_TAB_NAME);
161 		p += N_PHONEME_TAB_NAME;
162 		phoneme_tab_list[ix].phoneme_tab_ptr = (PHONEME_TAB *)p;
163 		p += (n_phonemes * sizeof(PHONEME_TAB));
164 	}
165 
166 	if(phoneme_tab_number >= n_phoneme_tables)
167 		phoneme_tab_number = 0;
168 
169     if(srate != NULL)
170         *srate = rate;
171 	return(result);
172 }  //  end of LoadPhData
173 
174 
FreePhData(void)175 void FreePhData(void)
176 {//==================
177 	Free(phoneme_tab_data);
178 	Free(phoneme_index);
179 	Free(phondata_ptr);
180 	Free(tunes);
181 	phoneme_tab_data=NULL;
182 	phoneme_index=NULL;
183 	phondata_ptr=NULL;
184 	tunes=NULL;
185 }
186 
187 
PhonemeCode(unsigned int mnem)188 int PhonemeCode(unsigned int mnem)
189 {//===============================
190 	int ix;
191 
192 	for(ix=0; ix<n_phoneme_tab; ix++)
193 	{
194 		if(phoneme_tab[ix] == NULL)
195 			continue;
196 		if(phoneme_tab[ix]->mnemonic == mnem)
197 			return(phoneme_tab[ix]->code);
198 	}
199 	return(0);
200 }
201 
202 
LookupPhonemeString(const char * string)203 int LookupPhonemeString(const char *string)
204 {//========================================
205 	int  ix;
206 	unsigned char c;
207 	unsigned int  mnem;
208 
209 	// Pack up to 4 characters into a word
210 	mnem = 0;
211 	for(ix=0; ix<4; ix++)
212 	{
213 		if(string[ix]==0) break;
214 		c = string[ix];
215 		mnem |= (c << (ix*8));
216 	}
217 
218 	return(PhonemeCode(mnem));
219 }
220 
221 
222 
223 
LookupSpect(PHONEME_TAB * this_ph,int which,FMT_PARAMS * fmt_params,int * n_frames,PHONEME_LIST * plist)224 frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params,  int *n_frames, PHONEME_LIST *plist)
225 {//===================================================================================================================
226 	int  ix;
227 	int  nf;
228 	int  nf1;
229 	int  seq_break;
230 	frameref_t *frames;
231 	int  length1;
232 	int  length_std;
233 	int  length_factor;
234 	SPECT_SEQ *seq, *seq2;
235 	SPECT_SEQK *seqk, *seqk2;
236 	frame_t *frame;
237 	static frameref_t frames_buf[N_SEQ_FRAMES];
238 
239 	seq = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt_addr]);
240 	seqk = (SPECT_SEQK *)seq;
241 	nf = seq->n_frames;
242 
243 
244 	if(nf >= N_SEQ_FRAMES)
245 		nf = N_SEQ_FRAMES - 1;
246 
247 	seq_len_adjust = fmt_params->fmt2_lenadj + fmt_params->fmt_length;
248 	seq_break = 0;
249 
250 	for(ix=0; ix<nf; ix++)
251 	{
252 		if(seq->frame[0].frflags & FRFLAG_KLATT)
253 			frame = &seqk->frame[ix];
254 		else
255 			frame = (frame_t *)&seq->frame[ix];
256 		frames_buf[ix].frame = frame;
257 		frames_buf[ix].frflags = frame->frflags;
258 		frames_buf[ix].length = frame->length;
259 		if(frame->frflags & FRFLAG_VOWEL_CENTRE)
260 			seq_break = ix;
261 	}
262 
263 	frames = &frames_buf[0];
264 	if(seq_break > 0)
265 	{
266 		if(which==1)
267 		{
268 			nf = seq_break + 1;
269 		}
270 		else
271 		{
272 			frames = &frames_buf[seq_break];  // body of vowel, skip past initial frames
273 			nf -= seq_break;
274 		}
275 	}
276 
277 	// do we need to modify a frame for blending with a consonant?
278 	if((this_ph->type == phVOWEL) && (fmt_params->fmt2_addr == 0) && (fmt_params->use_vowelin))
279 	{
280 		seq_len_adjust += FormantTransition2(frames,&nf,fmt_params->transition0,fmt_params->transition1,NULL,which);
281 	}
282 
283 	length1 = 0;
284 	nf1 = nf - 1;
285 	for(ix=0; ix<nf1; ix++)
286 		length1 += frames[ix].length;
287 
288 	if(fmt_params->fmt2_addr != 0)
289 	{
290 		// a secondary reference has been returned, which is not a wavefile
291 		// add these spectra to the main sequence
292 		seq2 = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt2_addr]);
293 		seqk2 = (SPECT_SEQK *)seq2;
294 
295 		// first frame of the addition just sets the length of the last frame of the main seq
296 		nf--;
297 		for(ix=0; ix<seq2->n_frames; ix++)
298 		{
299 			if(seq2->frame[0].frflags & FRFLAG_KLATT)
300 				frame = &seqk2->frame[ix];
301 			else
302 				frame = (frame_t *)&seq2->frame[ix];
303 
304 			frames[nf].length = frame->length;
305 			if(ix > 0)
306 			{
307 				frames[nf].frame = frame;
308 				frames[nf].frflags = frame->frflags;
309 			}
310 			nf++;
311 		}
312 		wavefile_ix = 0;
313 	}
314 
315 	if(length1 > 0)
316 	{
317 		if(which==2)
318 		{
319 			// adjust the length of the main part to match the standard length specified for the vowel
320 			//   less the front part of the vowel and any added suffix
321 
322 			length_std = fmt_params->std_length + seq_len_adjust - 45;
323 			if(length_std < 10)
324 				length_std = 10;
325 			if(plist->synthflags & SFLAG_LENGTHEN)
326 				length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2);  // phoneme was followed by an extra : symbol
327 
328 // can adjust vowel length for stressed syllables here
329 
330 
331 			length_factor = (length_std * 256)/ length1;
332 
333 			for(ix=0; ix<nf1; ix++)
334 			{
335 				frames[ix].length = (frames[ix].length * length_factor)/256;
336 			}
337 		}
338 		else
339 		{
340 			if(which == 1)
341 			{
342 				// front of a vowel
343 				if(fmt_params->fmt_control == 1)
344 				{
345 					// This is the default start of a vowel.
346 					// Allow very short vowels to have shorter front parts
347 					if(fmt_params->std_length < 130)
348 						frames[0].length = (frames[0].length * fmt_params->std_length)/130;
349 				}
350 			}
351 			else
352 			{
353 				//not a vowel
354 				if(fmt_params->std_length > 0)
355 				{
356 					seq_len_adjust += (fmt_params->std_length - length1);
357 				}
358 			}
359 
360 			if(seq_len_adjust != 0)
361 			{
362 				length_factor = ((length1 + seq_len_adjust) * 256)/length1;
363 				for(ix=0; ix<nf1; ix++)
364 				{
365 					frames[ix].length = (frames[ix].length * length_factor)/256;
366 				}
367 			}
368 		}
369 	}
370 
371 	*n_frames = nf;
372 	return(frames);
373 }  //  end of LookupSpect
374 
375 
376 
GetEnvelope(int index)377 unsigned char *GetEnvelope(int index)
378 {//==================================
379 	if(index==0)
380 	{
381 		fprintf(stderr,"espeak: No envelope\n");
382 		return(envelope_data[0]);   // not found, use a default envelope
383 	}
384 	return((unsigned char *)&phondata_ptr[index]);
385 }
386 
387 
SetUpPhonemeTable(int number,int recursing)388 static void SetUpPhonemeTable(int number, int recursing)
389 {//=====================================================
390 	int ix;
391 	int includes;
392 	int ph_code;
393 	PHONEME_TAB *phtab;
394 
395 	if(recursing==0)
396 	{
397 		memset(phoneme_tab_flags,0,sizeof(phoneme_tab_flags));
398 	}
399 
400 	if((includes = phoneme_tab_list[number].includes) > 0)
401 	{
402 		// recursively include base phoneme tables
403 		SetUpPhonemeTable(includes-1,1);
404 	}
405 
406 	// now add the phonemes from this table
407 	phtab = phoneme_tab_list[number].phoneme_tab_ptr;
408 	for(ix=0; ix<phoneme_tab_list[number].n_phonemes; ix++)
409 	{
410 		ph_code = phtab[ix].code;
411 		phoneme_tab[ph_code] = &phtab[ix];
412 		if(ph_code > n_phoneme_tab)
413 			n_phoneme_tab = ph_code;
414 
415 		if(recursing == 0)
416 			phoneme_tab_flags[ph_code] |= 1;   // not inherited
417 	}
418 }  // end of SetUpPhonemeTable
419 
420 
SelectPhonemeTable(int number)421 void SelectPhonemeTable(int number)
422 {//================================
423 	n_phoneme_tab = 0;
424 	SetUpPhonemeTable(number,0);  // recursively for included phoneme tables
425 	n_phoneme_tab++;
426 	current_phoneme_table = number;
427 }  //  end of SelectPhonemeTable
428 
429 
LookupPhonemeTable(const char * name)430 int LookupPhonemeTable(const char *name)
431 {//=====================================
432 	int ix;
433 
434 	for(ix=0; ix<n_phoneme_tables; ix++)
435 	{
436 		if(strcmp(name,phoneme_tab_list[ix].name)==0)
437 		{
438 			phoneme_tab_number = ix;
439 			break;
440 		}
441 	}
442 	if(ix == n_phoneme_tables)
443 		return(-1);
444 
445 	return(ix);
446 }
447 
448 
SelectPhonemeTableName(const char * name)449 int SelectPhonemeTableName(const char *name)
450 {//=========================================
451 // Look up a phoneme set by name, and select it if it exists
452 // Returns the phoneme table number
453 	int ix;
454 
455 	if((ix = LookupPhonemeTable(name)) == -1)
456 		return(-1);
457 
458 	SelectPhonemeTable(ix);
459 	return(ix);
460 }  //  end of DelectPhonemeTableName
461 
462 
463 
464 
LoadConfig(void)465 void LoadConfig(void)
466 {//==================
467 // Load configuration file, if one exists
468 	char buf[sizeof(path_home)+10];
469 	FILE *f;
470 	int ix;
471 	char c1;
472 	char *p;
473 	char string[200];
474 
475 	logging_type = 0;
476 
477 	for(ix=0; ix<N_SOUNDICON_SLOTS; ix++)
478 	{
479 		soundicon_tab[ix].filename = NULL;
480 		soundicon_tab[ix].data = NULL;
481 	}
482 
483 	sprintf(buf,"%s%c%s",path_home,PATHSEP,"config");
484 	if((f = fopen(buf,"r"))==NULL)
485 	{
486 		return;
487 	}
488 
489 	while(fgets(buf,sizeof(buf),f)!=NULL)
490 	{
491 		if(buf[0] == '/')  continue;
492 
493 		if(memcmp(buf,"log",3)==0)
494 		{
495 			if(sscanf(&buf[4],"%d %s",&logging_type,string)==2)
496 				f_logespeak = fopen(string,"w");
497 		}
498 		else
499 		if(memcmp(buf,"tone",4)==0)
500 		{
501 			ReadTonePoints(&buf[5],tone_points);
502 		}
503 		else
504 		if(memcmp(buf,"pa_device",9)==0)
505 		{
506 			sscanf(&buf[10],"%d",&option_device_number);
507 		}
508 		else
509 		if(memcmp(buf,"soundicon",9)==0)
510 		{
511 			ix = sscanf(&buf[10],"_%c %s",&c1,string);
512 			if(ix==2)
513 			{
514 				soundicon_tab[n_soundicon_tab].name = c1;
515 				p = Alloc(strlen(string)+1);
516 				strcpy(p,string);
517 				soundicon_tab[n_soundicon_tab].filename = p;
518 				soundicon_tab[n_soundicon_tab++].length = 0;
519 			}
520 		}
521 	}
522 	fclose(f);
523 }  //  end of LoadConfig
524 
525 
526 
527 
528 PHONEME_DATA this_ph_data;
529 
530 
InvalidInstn(PHONEME_TAB * ph,int instn)531 static void InvalidInstn(PHONEME_TAB *ph, int instn)
532 {//====================================================
533 	fprintf(stderr,"Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic));
534 }
535 
536 
StressCondition(Translator * tr,PHONEME_LIST * plist,int condition,int control)537 static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control)
538 {//========================================================================================
539 // condition:
540 //	0	if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress
541 
542 	int stress_level;
543 	PHONEME_LIST *pl;
544 	static int condition_level[4] = {1,2,4,15};
545 
546 	if(phoneme_tab[plist[0].phcode]->type == phVOWEL)
547 	{
548 		pl = plist;
549 	}
550 	else
551 	{
552 		// consonant, get stress from the following vowel
553 		if(phoneme_tab[plist[1].phcode]->type == phVOWEL)
554 		{
555 			pl = &plist[1];
556 		}
557 		else
558 			return(false);  // no stress elevel for this consonant
559 	}
560 
561 	stress_level = pl->stresslevel & 0xf;
562 
563 	if(tr != NULL)
564 	{
565 		if((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1)==0))
566 		{
567 			// change phoneme.  Don't change phonemes which are given for the word in the dictionary.
568 			return(false);
569 		}
570 
571 		if((tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= pl->wordstress))
572 		{
573 			// treat the most stressed syllable in an unstressed word as stressed
574 			stress_level = 4;
575 		}
576 	}
577 
578 	if(condition == 4)
579 	{
580 		return(stress_level >= pl->wordstress);
581 	}
582 
583 	if(condition == 3)
584 	{
585 		// if stressed
586 		if(stress_level > 3)
587 			return(true);
588 	}
589 	else
590 	{
591 		if(stress_level < condition_level[condition])
592 			return(true);
593 	}
594 	return(false);
595 
596 }  // end of StressCondition
597 
598 
CountVowelPosition(PHONEME_LIST * plist)599 static int CountVowelPosition(PHONEME_LIST *plist)
600 {//===============================================
601 	int count = 0;
602 
603 	for(;;)
604 	{
605 		if(plist->ph->type == phVOWEL)
606 			count++;
607 		if(plist->sourceix != 0)
608 			break;
609 		plist--;
610 	}
611 	return(count);
612 }  // end of CoundVowelPosition
613 
614 
InterpretCondition(Translator * tr,int control,PHONEME_LIST * plist,USHORT * p_prog,WORD_PH_DATA * worddata)615 static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata)
616 {//========================================================================================================================
617 	int which;
618 	int ix;
619 	unsigned int data;
620 	int instn;
621 	int instn2;
622 	int count;
623 	PHONEME_TAB *ph;
624 	PHONEME_LIST *plist_this;
625 
626 	// instruction: 2xxx, 3xxx
627 
628 	// bits 8-10 = 0 to 5,  which phoneme, =6 the 'which' information is in the next instruction.
629 	// bit 11 = 0, bits 0-7 are a phoneme code
630 	// bit 11 = 1, bits 5-7 type of data, bits 0-4 data value
631 
632 	// bits 8-10 = 7,  other conditions
633 
634 	instn = (*p_prog) & 0xfff;
635 	data = instn & 0xff;
636 	instn2 = instn >> 8;
637 
638 	if(instn2 < 14)
639 	{
640 		plist_this = plist;
641 		which = (instn2) % 7;
642 
643 		if(which==6)
644 		{
645 		    // the 'which' code is in the next instruction
646 		    p_prog++;
647 		    which = (*p_prog);
648 		}
649 
650 		if(which==4)
651 		{
652 			// nextPhW not word boundary
653 			if(plist[1].sourceix)
654 				return(false);
655 		}
656 		if(which==5)
657 		{
658 			// prevPhW, not word boundary
659 			if(plist[0].sourceix)
660 				return(false);
661 		}
662 		if(which==6)
663         {
664             // next2PhW, not word boundary
665             if(plist[1].sourceix || plist[2].sourceix)
666                 return(false);
667         }
668 
669 
670         switch(which)
671         {
672         case 0:  // prevPh
673         case 5:  // prevPhW
674             plist--;
675             break;
676 
677         case 1:  // thisPh
678             break;
679 
680         case 2:  // nextPh
681         case 4:  // nextPhW
682             plist++;
683             break;
684 
685         case 3:  // next2Ph
686         case 6:  // next2PhW
687             plist += 2;
688             break;
689 
690         case 7:
691 			// nextVowel, not word boundary
692 			for(which=1;;which++)
693 			{
694 				if(plist[which].sourceix)
695 					return(false);
696 				if(phoneme_tab[plist[which].phcode]->type == phVOWEL)
697 				{
698 					plist = &plist[which];
699 					break;
700 				}
701 			}
702 			break;
703 
704         case 8:  // prevVowel in this word
705 		    if((worddata==NULL) || (worddata->prev_vowel.ph == NULL))
706                 return(false);   // no previous vowel
707 				plist = &(worddata->prev_vowel);
708             break;
709 
710 		case 9:  // next3PhW
711 			for(ix=1; ix<=3; ix++)
712 			{
713 				if(plist[ix].sourceix)
714 					return(false);
715 			}
716 			plist = &plist[3];
717 			break;
718 
719 		case 10: // prev2PhW
720 			if((plist[0].sourceix) || (plist[-1].sourceix))
721 				return(false);
722 			plist-=2;
723 			break;
724         }
725 
726 		if((which == 0) || (which == 5))
727 		{
728 			if(plist->phcode == 1)
729 			{
730 				// This is a NULL phoneme, a phoneme has been deleted so look at the previous phoneme
731 				plist--;
732 			}
733 		}
734 
735 		if(control & 0x100)
736 		{
737 			// "change phonemes" pass
738 			plist->ph = phoneme_tab[plist->phcode];
739 		}
740 		ph = plist->ph;
741 
742 		if(instn2 < 7)
743 		{
744 			// 'data' is a phoneme number
745 			if((phoneme_tab[data]->mnemonic == ph->mnemonic) == true)
746 				return(true);
747 			if((which == 0) && (ph->type == phVOWEL))
748 				return(data == ph->end_type);   // prevPh() match on end_type
749 			return(data == ph->start_type);    // thisPh() or nextPh(), match on start_type
750 		}
751 
752 		data = instn & 0x1f;
753 
754 		switch(instn & 0xe0)
755 		{
756 		case 0x00:
757 			// phoneme type, vowel, nasal, fricative, etc
758 			return(ph->type == data);
759 			break;
760 
761 		case 0x20:
762 			// place of articulation
763 			return(((ph->phflags >> 16) & 0xf) == data);
764 			break;
765 
766 		case 0x40:
767 			// is a bit set in phoneme flags
768 			return((ph->phflags & (1 << data)) != 0);
769 			break;
770 
771 		case 0x80:
772 			switch(data)
773 			{
774 			case 0:
775 			case 1:
776 			case 2:
777 			case 3:
778 			case 4:
779 				return(StressCondition(tr, plist, data, 0));
780 
781 			case 5:  // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word))
782 				return((ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE));
783 
784 			case 6:  // isWordStart
785 				return(plist->sourceix != 0);
786 
787 			case 7:  // notWordStart
788 				return(plist->sourceix == 0);
789 
790 			case 8:  // isWordEnd
791 				return(plist[1].sourceix || (plist[1].ph->type == phPAUSE));
792 				break;
793 
794 			case 9:  // isAfterStress
795 				if(plist->sourceix != 0)
796 					return(false);
797 				do {
798 					plist--;
799 					if((plist->stresslevel & 0xf) >= 4)
800 						return(true);
801 
802 				} while (plist->sourceix == 0);
803 				break;
804 
805 			case 10:  // isNotVowel
806 				return(ph->type != phVOWEL);
807 
808 			case 11:  // isFinalVowel
809 				for(;;)
810 				{
811 					plist++;
812 					plist->ph = phoneme_tab[plist->phcode];
813 					if(plist->sourceix != 0)
814 						return(true);   // start of next word, without finding another vowel
815 					if(plist->ph->type == phVOWEL)
816 						return(false);
817 				}
818 				break;
819 
820 			case 12:  // isVoiced
821 				return((ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED));
822 
823 			case 13:  // isFirstVowel
824 				return(CountVowelPosition(plist)==1);
825 
826 			case 14:  // isSecondVowel
827 				return(CountVowelPosition(plist)==2);
828 
829 			case 15:  // isSeqFlag1
830 				// is this preceded  by a sequence if 1 or more vowels which have 'flag1' ?  (lang=hi)
831 				if(plist->sourceix != 0)
832 					return(false);   // this is the first phoneme in the word, so no.
833 
834 				count = 0;
835 				for(;;)
836 				{
837 					plist--;
838 					if(plist->ph->type == phVOWEL)
839 					{
840 						if(plist->ph->phflags & phFLAG1)
841 							count++;
842 						else
843 							break;  // stop when we find a vowel without flag1
844 					}
845 					if(plist->sourceix != 0)
846 						break;
847 				}
848 				return(count > 0);
849 
850 			case 0x10:  //  isTranslationGiven
851 				return((plist->synthflags & SFLAG_DICTIONARY) != 0);
852 			}
853 			break;
854 
855 		}
856 		return(false);
857 	}
858 	else
859 	if(instn2 == 0xf)
860 	{
861 		// Other conditions
862 		switch(data)
863 		{
864 		case 1:   // PreVoicing
865 			return(control & 1);
866 		case 2:   // KlattSynth
867 			return(voice->klattv[0] != 0);
868 		case 3:   // MbrolaSynth
869 			return(mbrola_name[0] != 0);
870 		}
871 	}
872 	return(false);
873 }  // end of InterpretCondition
874 
875 
SwitchOnVowelType(PHONEME_LIST * plist,PHONEME_DATA * phdata,USHORT ** p_prog,int instn_type)876 static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type)
877 {//========================================================================================================
878 	USHORT *prog;
879 	int voweltype;
880 	signed char x;
881 
882 	if(instn_type == 2)
883 	{
884 		phdata->pd_control |= pd_FORNEXTPH;
885 		voweltype = plist[1].ph->start_type;  // SwitchNextVowelType
886 	}
887 	else
888 	{
889 		voweltype = plist[-1].ph->end_type;  // SwitchPrevVowelType
890 	}
891 
892 	voweltype -= phonVOWELTYPES;
893 	if((voweltype >= 0) && (voweltype < 6))
894 	{
895 		prog = *p_prog + voweltype*2;
896 		phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4;
897 		x = (prog[1] >> 4) & 0xff;
898 		phdata->sound_param[instn_type] = x;  // sign extend
899 	}
900 
901 	*p_prog += 12;
902 }  // end of SwitchVowelType
903 
904 
NumInstnWords(USHORT * prog)905 int NumInstnWords(USHORT *prog)
906 {//============================
907 	int instn;
908 	int instn2;
909 	int instn_type;
910 	int n;
911 	int type2;
912 	static const char n_words[16] = {0,1,0,0,1,1,0,1,1,2,4,0,0,0,0,0};
913 
914 	instn = *prog;
915 	instn_type = instn >> 12;
916 	if((n = n_words[instn_type]) > 0)
917 		return(n);
918 
919 	switch(instn_type)
920 	{
921 	case 0:
922 		if(((instn & 0xf00) >> 8) == i_IPA_NAME)
923 		{
924 			n = ((instn & 0xff) + 1) / 2;
925 			return(n+1);
926 		}
927 		return(1);;
928 
929 	case 6:
930 		type2 = (instn & 0xf00) >> 9;
931 		if((type2 == 5) || (type2 == 6))
932 			return(12);  // switch on vowel type
933 		return(1);
934 
935 	case 2:
936 	case 3:
937 		// a condition, check for a 2-word instruction
938 		if(((n = instn & 0x0f00) == 0x600) || (n == 0x0d00))
939 			return(2);
940 		return(1);
941 
942 	default:
943 		// instn_type 11 to 15, 2 words
944 		instn2 = prog[2];
945 		if((instn2 >> 12) == 0xf)
946 		{
947 			// This instruction is followed by addWav(), 2 more words
948 			return(4);
949 		}
950 		if(instn2 == i_CONTINUE)
951 		{
952 			return(3);
953 		}
954 		return(2);
955 	}
956 }  //  end of NumInstnWords
957 
958 
959 
InterpretPhoneme(Translator * tr,int control,PHONEME_LIST * plist,PHONEME_DATA * phdata,WORD_PH_DATA * worddata)960 void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata)
961 {//===================================================================================================================
962 // control:
963 //bit 0:  PreVoicing
964 //bit 8:  change phonemes
965 	PHONEME_TAB *ph;
966 	USHORT *prog;
967 	USHORT instn;
968 	int instn2;
969 	int or_flag;
970 	bool truth;
971 	bool truth2;
972 	int data;
973 	int end_flag;
974 	int ix;
975 	signed char param_sc;
976 
977 	#define N_RETURN 10
978 	int n_return=0;
979 	USHORT *return_addr[N_RETURN];  // return address stack
980 
981 	ph = plist->ph;
982 
983 	if((worddata != NULL) && (plist->sourceix))
984 	{
985 	    // start of a word, reset word data
986 	    worddata->prev_vowel.ph = NULL;
987 	}
988 
989 	memset(phdata, 0, sizeof(PHONEME_DATA));
990 	phdata->pd_param[i_SET_LENGTH] = ph->std_length;
991 	phdata->pd_param[i_LENGTH_MOD] = ph->length_mod;
992 
993 	if(ph->program == 0)
994 	{
995 		return;
996 	}
997 
998 	end_flag = 0;
999 
1000 	for(prog = &phoneme_index[ph->program]; end_flag != 1; prog++)
1001 	{
1002 		instn = *prog;
1003 		instn2 = (instn >> 8) & 0xf;
1004 		or_flag = 0;
1005 
1006 		switch(instn >> 12)
1007 		{
1008 		case 0:   // 0xxx
1009 			data = instn & 0xff;
1010 
1011 			if(instn2 == 0)
1012 			{
1013 				// instructions with no operand
1014 				switch(data)
1015 				{
1016 				case i_RETURN:
1017 					end_flag = 1;
1018 					break;
1019 
1020 				case i_CONTINUE:
1021 					break;
1022 
1023 				default:
1024 					InvalidInstn(ph,instn);
1025 					break;
1026 				}
1027 			}
1028 			else
1029 			if(instn2 == i_APPEND_IFNEXTVOWEL)
1030 			{
1031 				if(phoneme_tab[plist[1].phcode]->type == phVOWEL)
1032 					phdata->pd_param[i_APPEND_PHONEME] = data;
1033 			}
1034 			else
1035 			if(instn2 == i_ADD_LENGTH)
1036 			{
1037 				if(data & 0x80)
1038 				{
1039 					// a negative value, do sign extension
1040 					data = -(0x100 - data);
1041 				}
1042 				phdata->pd_param[i_SET_LENGTH] += data;
1043 			}
1044 			else
1045 			if(instn2 == i_IPA_NAME)
1046 			{
1047 				// followed by utf-8 characters, 2 per instn word
1048 				for(ix=0; (ix < data) && (ix < 16); ix += 2)
1049 				{
1050 					prog++;
1051 					phdata->ipa_string[ix] = prog[0] >> 8;
1052 					phdata->ipa_string[ix+1] = prog[0] & 0xff;
1053 				}
1054 				phdata->ipa_string[ix] = 0;
1055 			}
1056 			else
1057 			if(instn2 < N_PHONEME_DATA_PARAM)
1058 			{
1059 				if(instn2 == i_CHANGE_PHONEME2)
1060 				{
1061 					phdata->pd_param[i_CHANGE_PHONEME] = data;  // also set ChangePhoneme
1062 				}
1063 				phdata->pd_param[instn2] = data;
1064 				if((instn2 == i_CHANGE_PHONEME) && (control & 0x100))
1065 				{
1066 					// found ChangePhoneme() in PhonemeList mode, exit
1067 					end_flag = 1;
1068 				}
1069 			}
1070 			else
1071 			{
1072 				InvalidInstn(ph,instn);
1073 			}
1074 			break;
1075 
1076 		case 1:
1077 			if(tr == NULL)
1078 				break;   // ignore if in synthesis stage
1079 
1080 			if(instn2 < 8)
1081 			{
1082 				// ChangeIf
1083 				if(StressCondition(tr, plist, instn2 & 7, 1) == true)
1084 				{
1085 					phdata->pd_param[i_CHANGE_PHONEME] = instn & 0xff;
1086 					end_flag = 1;    // change phoneme, exit
1087 				}
1088 			}
1089 			break;
1090 
1091 		case 2:
1092 		case 3:
1093 			// conditions
1094 			or_flag = 0;
1095 			truth = true;
1096 			while((instn & 0xe000) == 0x2000)
1097 			{
1098 				// process a sequence of conditions, using  boolean accumulator
1099 				truth2 = InterpretCondition(tr, control, plist, prog, worddata);
1100 				prog += NumInstnWords(prog);
1101 				if(*prog == i_NOT)
1102 				{
1103 					truth2 = truth2 ^ 1;
1104 					prog++;
1105 				}
1106 
1107 				if(or_flag)
1108 					truth = truth || truth2;
1109 				else
1110 					truth = truth && truth2;
1111 				or_flag = instn & 0x1000;
1112 				instn = *prog;
1113 			}
1114 
1115 			if(truth == false)
1116 			{
1117 				if((instn & 0xf800) == i_JUMP_FALSE)
1118 				{
1119 					prog += instn & 0xff;
1120 				}
1121 				else
1122 				{
1123 					// instruction after a condition is not JUMP_FALSE, so skip the instruction.
1124 					prog += NumInstnWords(prog);
1125 					if((prog[0] & 0xfe00) == 0x6000)
1126 						prog++;    // and skip ELSE jump
1127 				}
1128 			}
1129 			prog--;
1130 		break;
1131 
1132 		case 6:
1133 			// JUMP
1134 			switch(instn2 >> 1)
1135 			{
1136 			case 0:
1137 				prog += (instn & 0xff) - 1;
1138 				break;
1139 
1140 			case 4:
1141 				// conditional jumps should have been processed in the Condition section
1142 				break;
1143 
1144 			case 5:   // NexttVowelStarts
1145 				SwitchOnVowelType(plist, phdata, &prog, 2);
1146 				break;
1147 
1148 			case 6:   // PrevVowelTypeEndings
1149 				SwitchOnVowelType(plist, phdata, &prog, 3);
1150 				break;
1151 			}
1152 		break;
1153 
1154 		case 9:
1155 			data = ((instn & 0xf) << 16) + prog[1];
1156 			prog++;
1157 			switch(instn2)
1158 			{
1159 			case 1:
1160 				// call a procedure or another phoneme
1161 				if(n_return < N_RETURN)
1162 				{
1163 					return_addr[n_return++] = prog;
1164 					prog = &phoneme_index[data] - 1;
1165 				}
1166 				break;
1167 
1168 			case 2:
1169 				// pitch envelope
1170 				phdata->pitch_env = data;
1171 				break;
1172 
1173 			case 3:
1174 				// amplitude envelope
1175 				phdata->amp_env = data;
1176 				break;
1177 			}
1178 			break;
1179 
1180 		case 10:   //  Vowelin, Vowelout
1181 			if(instn2 == 1)
1182 				ix = 0;
1183 			else
1184 				ix = 2;
1185 
1186 			phdata->vowel_transition[ix] = ((prog[0] & 0xff) << 16) + prog[1];
1187 			phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3];
1188 			prog += 3;
1189 			break;
1190 
1191 		case 11:   // FMT
1192 		case 12:   // WAV
1193 		case 13:   // VowelStart
1194 		case 14:   // VowelEnd
1195 		case 15:   // addWav
1196 			instn2 = (instn >> 12) - 11;
1197 			phdata->sound_addr[instn2] = ((instn & 0xf) << 18) + (prog[1] << 2);
1198 			param_sc = phdata->sound_param[instn2] = (instn >> 4) & 0xff;
1199 			prog++;
1200 
1201 			if(prog[1] != i_CONTINUE)
1202 			{
1203 				if(instn2 < 2)
1204 				{
1205 					// FMT() and WAV() imply Return
1206 					end_flag = 1;
1207 					if((prog[1] >> 12) == 0xf)
1208 					{
1209 						// Return after the following addWav()
1210 						end_flag = 2;
1211 					}
1212 				}
1213 				else
1214 				if(instn2 ==pd_ADDWAV)
1215 				{
1216 					// addWav(), return if previous instruction was FMT() or WAV()
1217 					end_flag--;
1218 				}
1219 
1220 				if((instn2 == pd_VWLSTART) || (instn2 == pd_VWLEND))
1221 				{
1222 					// VowelStart or VowelEnding.
1223 					phdata->sound_param[instn2] = param_sc;   // sign extend
1224 				}
1225 			}
1226 		break;
1227 
1228 		default:
1229 			InvalidInstn(ph,instn);
1230 			break;
1231 		}
1232 
1233 		if(ph->phflags & phSINGLE_INSTN)
1234 		{
1235 			end_flag = 1;  // this phoneme has a one-instruction program, with an implicit Return
1236 		}
1237 
1238 		if((end_flag == 1) && (n_return > 0))
1239 		{
1240 			// return from called procedure or phoneme
1241 			end_flag = 0;
1242 			prog = return_addr[--n_return];
1243 		}
1244 	}
1245 
1246     if((worddata != NULL) && (plist->type == phVOWEL))
1247     {
1248         memcpy(&worddata->prev_vowel, &plist[0], sizeof(PHONEME_LIST));
1249     }
1250 
1251 #ifdef _ESPEAKEDIT
1252     plist->std_length = phdata->pd_param[i_SET_LENGTH];
1253     if(phdata->sound_addr[0] != 0)
1254     {
1255         plist->phontab_addr = phdata->sound_addr[0];  // FMT address
1256         plist->sound_param = phdata->sound_param[0];
1257     }
1258     else
1259     {
1260         plist->phontab_addr = phdata->sound_addr[1];  // WAV address
1261         plist->sound_param = phdata->sound_param[1];
1262 	}
1263 #endif
1264 }  // end of InterpretPhoneme
1265 
1266 
InterpretPhoneme2(int phcode,PHONEME_DATA * phdata)1267 void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata)
1268 {//=====================================================
1269 // Examine the program of a single isolated phoneme
1270 	int ix;
1271 	PHONEME_LIST plist[4];
1272 	memset(plist, 0, sizeof(plist));
1273 
1274 	for(ix=0; ix<4; ix++)
1275 	{
1276 		plist[ix].phcode = phonPAUSE;
1277 		plist[ix].ph = phoneme_tab[phonPAUSE];
1278 	}
1279 
1280 	plist[1].phcode = phcode;
1281 	plist[1].ph = phoneme_tab[phcode];
1282 	plist[2].sourceix = 1;
1283 
1284 	InterpretPhoneme(NULL, 0, &plist[1], phdata, NULL);
1285 }  // end of InterpretPhoneme2
1286