1 /***************************************************************************
2 * Copyright (C) 2005 to 2011 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, write see: *
17 * <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
19
20 #include "StdAfx.h"
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <wctype.h>
25
26 #include "speak_lib.h"
27 #include "speech.h"
28 #include "phoneme.h"
29 #include "synthesize.h"
30 #include "voice.h"
31 #include "translate.h"
32
33 extern int GetAmplitude(void);
34 extern void DoSonicSpeed(int value);
35 extern int saved_parameters[];
36
37
38 // convert from words-per-minute to internal speed factor
39 // Use this to calibrate speed for wpm 80-350
40 static unsigned char speed_lookup[] = {
41 255, 255, 255, 255, 255, // 80
42 253, 249, 245, 242, 238, // 85
43 235, 232, 228, 225, 222, // 90
44 218, 216, 213, 210, 207, // 95
45 204, 201, 198, 196, 193, // 100
46 191, 188, 186, 183, 181, // 105
47 179, 176, 174, 172, 169, // 110
48 168, 165, 163, 161, 159, // 115
49 158, 155, 153, 152, 150, // 120
50 148, 146, 145, 143, 141, // 125
51 139, 137, 136, 135, 133, // 130
52 131, 130, 129, 127, 126, // 135
53 124, 123, 122, 120, 119, // 140
54 118, 117, 115, 114, 113, // 145
55 112, 111, 110, 109, 107, // 150
56 106, 105, 104, 103, 102, // 155
57 101, 100, 99, 98, 97, // 160
58 96, 95, 94, 93, 92, // 165
59 91, 90, 89, 89, 88, // 170
60 87, 86, 85, 84, 83, // 175
61 82, 82, 81, 80, 80, // 180
62 79, 78, 77, 76, 76, // 185
63 75, 75, 74, 73, 72, // 190
64 71, 71, 70, 69, 69, // 195
65 68, 67, 67, 66, 66, // 200
66 65, 64, 64, 63, 62, // 205
67 62, 61, 61, 60, 59, // 210
68 59, 58, 58, 57, 57, // 215
69 56, 56, 55, 54, 54, // 220
70 53, 53, 52, 52, 52, // 225
71 51, 50, 50, 49, 49, // 230
72 48, 48, 47, 47, 46, // 235
73 46, 46, 45, 45, 44, // 240
74 44, 44, 43, 43, 42, // 245
75 41, 40, 40, 40, 39, // 250
76 39, 39, 38, 38, 38, // 255
77 37, 37, 37, 36, 36, // 260
78 35, 35, 35, 35, 34, // 265
79 34, 34, 33, 33, 33, // 270
80 32, 32, 31, 31, 31, // 275
81 30, 30, 30, 29, 29, // 280
82 29, 29, 28, 28, 27, // 285
83 27, 27, 27, 26, 26, // 290
84 26, 26, 25, 25, 25, // 295
85 24, 24, 24, 24, 23, // 300
86 23, 23, 23, 22, 22, // 305
87 22, 21, 21, 21, 21, // 310
88 20, 20, 20, 20, 19, // 315
89 19, 19, 18, 18, 17, // 320
90 17, 17, 16, 16, 16, // 325
91 16, 16, 16, 15, 15, // 330
92 15, 15, 14, 14, 14, // 335
93 13, 13, 13, 12, 12, // 340
94 12, 12, 11, 11, 11, // 345
95 11, 10, 10, 10, 9, // 350
96 9, 9, 8, 8, 8, // 355
97 };
98
99
100 // speed_factor1 adjustments for speeds 350 to 374: pauses
101 static unsigned char pause_factor_350[] = {
102 22,22,22,22,22,22,22,21,21,21, // 350
103 21,20,20,19,19,18,17,16,15,15, // 360
104 15,15,15,15,15}; // 370
105
106 // wav_factor adjustments for speeds 350 to 450
107 // Use this to calibrate speed for wpm 350-450
108 static unsigned char wav_factor_350[] = {
109 120, 121, 120, 119, 119, // 350
110 118, 118, 117, 116, 116, // 355
111 115, 114, 113, 112, 112, // 360
112 111, 111, 110, 109, 108, // 365
113 107, 106, 106, 104, 103, // 370
114 103, 102, 102, 102, 101, // 375
115 101, 99, 98, 98, 97, // 380
116 96, 96, 95, 94, 93, // 385
117 91, 90, 91, 90, 89, // 390
118 88, 86, 85, 86, 85, // 395
119 85, 84, 82, 81, 80, // 400
120 79, 77, 78, 78, 76, // 405
121 77, 75, 75, 74, 73, // 410
122 71, 72, 70, 69, 69, // 415
123 69, 67, 65, 64, 63, // 420
124 63, 63, 61, 61, 59, // 425
125 59, 59, 58, 56, 57, // 430
126 58, 56, 54, 53, 52, // 435
127 52, 53, 52, 52, 50, // 440
128 48, 47, 47, 45, 46, // 445
129 45}; // 450
130
131 static int speed1 = 130;
132 static int speed2 = 121;
133 static int speed3 = 118;
134
135
136
137 //#define TEST_SPEED
138
139 #ifdef INCLUDE_SONIC
140
SetSpeed(int control)141 void SetSpeed(int control)
142 {//=======================
143 int x;
144 int s1;
145 int wpm;
146 int wpm2;
147 int wpm_value;
148 double sonic;
149
150 speed.loud_consonants = 0;
151 speed.min_sample_len = 450;
152 speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change
153 speed.lenmod2_factor = 100;
154 speed.min_pause = 5;
155
156 wpm = embedded_value[EMBED_S];
157 if(control == 2)
158 wpm = embedded_value[EMBED_S2];
159
160 wpm_value = wpm;
161
162 if(voice->speed_percent > 0)
163 {
164 wpm = (wpm * voice->speed_percent)/100;
165 }
166
167 if(control & 2)
168 {
169 DoSonicSpeed(1 * 1024);
170 }
171 if((wpm_value > 450) || ((wpm_value > speed.fast_settings[0]) && (wpm > 350)))
172 {
173 wpm2 = wpm;
174 wpm = 175;
175
176 // set special eSpeak speed parameters for Sonic use
177 // The eSpeak output will be speeded up by at least x2
178 x = 73;
179 if(control & 1)
180 {
181 speed1 = (x * voice->speedf1)/256;
182 speed2 = (x * voice->speedf2)/256;
183 speed3 = (x * voice->speedf3)/256;
184 }
185 if(control & 2)
186 {
187 sonic = ((double)wpm2)/wpm;
188 DoSonicSpeed((int)(sonic * 1024));
189 speed.pause_factor = 85;
190 speed.clause_pause_factor = 80;
191 speed.min_pause = 22;
192 speed.min_sample_len = 450*2;
193 speed.wav_factor = 211;
194 speed.lenmod_factor = 210;
195 speed.lenmod2_factor = 170;
196 }
197 return;
198 }
199
200
201 #ifdef TEST_SPEED
202 if(wpm > 1000)
203 {
204 // TESTING
205 // test = wpm / 1000;
206 wpm = wpm % 1000;
207 }
208 #endif
209
210 if(wpm > 450)
211 wpm = 450;
212
213 if(wpm > 360)
214 {
215 speed.loud_consonants = (wpm - 360) / 8;
216 }
217
218 wpm2 = wpm;
219 if(wpm > 359) wpm2 = 359;
220 if(wpm < 80) wpm2 = 80;
221 x = speed_lookup[wpm2-80];
222
223 if(wpm >= 380)
224 x = 7;
225 if(wpm >= 400)
226 x = 6;
227
228 if(control & 1)
229 {
230 // set speed factors for different syllable positions within a word
231 // these are used in CalcLengths()
232 speed1 = (x * voice->speedf1)/256;
233 speed2 = (x * voice->speedf2)/256;
234 speed3 = (x * voice->speedf3)/256;
235
236 if(x <= 7)
237 {
238 speed1 = x;
239 speed2 = speed3 = x - 1;
240 }
241 }
242
243 if(control & 2)
244 {
245 // these are used in synthesis file
246
247 if(wpm > 350)
248 {
249 speed.lenmod_factor = 85 - (wpm - 350) / 3;
250 speed.lenmod2_factor = 60 - (wpm - 350) / 8;
251 }
252 else
253 if(wpm > 250)
254 {
255 speed.lenmod_factor = 110 - (wpm - 250)/4;
256 speed.lenmod2_factor = 110 - (wpm - 250)/2;
257 }
258
259 s1 = (x * voice->speedf1)/256;
260
261 if(wpm >= 170)
262 speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
263 else
264 speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm
265
266 if(wpm >= 350)
267 {
268 speed.wav_factor = wav_factor_350[wpm-350];
269 }
270
271 if(wpm >= 390)
272 {
273 speed.min_sample_len = 450 - (wpm - 400)/2;
274 if(wpm > 440)
275 speed.min_sample_len = 420 - (wpm - 440);
276 }
277
278 // adjust for different sample rates
279 speed.min_sample_len = (speed.min_sample_len * samplerate_native) / 22050;
280
281 speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length
282 speed.clause_pause_factor = 0;
283
284 if(wpm > 430)
285 {
286 speed.pause_factor = 12;
287 // speed.clause_pause_factor = 15;
288 }
289 else
290 if(wpm > 400)
291 {
292 speed.pause_factor = 13;
293 // speed.clause_pause_factor = 15;
294 }
295 else
296 if(wpm > 374)
297 {
298 speed.pause_factor = 14;
299 }
300 else
301 if(wpm > 350)
302 {
303 speed.pause_factor = pause_factor_350[wpm - 350];
304 }
305
306 if(speed.clause_pause_factor == 0)
307 {
308 // restrict the reduction of pauses between clauses
309 if((speed.clause_pause_factor = speed.pause_factor) < 16)
310 speed.clause_pause_factor = 16;
311 }
312 }
313
314 #ifdef TEST_SPEED
315 //if(control==3)
316 printf("%3d: speedf %d %d %d pause=%d %d wav=%d lenmod=%d %d\n",wpm,speed1,speed2,speed3, speed.pause_factor,speed.clause_pause_factor, speed.wav_factor,speed.lenmod_factor,speed.lenmod2_factor);
317 #endif
318 } // end of SetSpeed
319
320 #else // not using sonic speed-up
321
SetSpeed(int control)322 void SetSpeed(int control)
323 {//=======================
324 // This is the earlier version of SetSpeed() before sonic speed-up was added
325 int x;
326 int s1;
327 int wpm;
328 int wpm2;
329
330 speed.loud_consonants = 0;
331 speed.min_sample_len = 450;
332 speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change
333 speed.lenmod2_factor = 100;
334
335 wpm = embedded_value[EMBED_S];
336 if(control == 2)
337 wpm = embedded_value[EMBED_S2];
338
339 #ifdef TEST_SPEED
340 if(wpm > 1000)
341 {
342 // TESTING
343 test = wpm / 1000;
344 wpm = wpm % 1000;
345 }
346 #endif
347
348 if(voice->speed_percent > 0)
349 {
350 wpm = (wpm * voice->speed_percent)/100;
351 }
352 if(wpm > 450)
353 wpm = 450;
354
355 if(wpm > 360)
356 {
357 speed.loud_consonants = (wpm - 360) / 8;
358 }
359
360 wpm2 = wpm;
361 if(wpm > 359) wpm2 = 359;
362 if(wpm < 80) wpm2 = 80;
363 x = speed_lookup[wpm2-80];
364
365 if(wpm >= 380)
366 x = 7;
367 if(wpm >= 400)
368 x = 6;
369
370 if(control & 1)
371 {
372 // set speed factors for different syllable positions within a word
373 // these are used in CalcLengths()
374 speed1 = (x * voice->speedf1)/256;
375 speed2 = (x * voice->speedf2)/256;
376 speed3 = (x * voice->speedf3)/256;
377
378 if(x <= 7)
379 {
380 speed1 = x;
381 speed2 = speed3 = x - 1;
382 }
383 }
384
385 if(control & 2)
386 {
387 // these are used in synthesis file
388
389 if(wpm > 350)
390 {
391 speed.lenmod_factor = 85 - (wpm - 350) / 3;
392 speed.lenmod2_factor = 60 - (wpm - 350) / 8;
393 }
394 else
395 if(wpm > 250)
396 {
397 speed.lenmod_factor = 110 - (wpm - 250)/4;
398 speed.lenmod2_factor = 110 - (wpm - 250)/2;
399 }
400
401 s1 = (x * voice->speedf1)/256;
402
403 if(wpm >= 170)
404 speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
405 else
406 speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm
407
408 if(wpm >= 350)
409 {
410 speed.wav_factor = wav_factor_350[wpm-350];
411 }
412
413 if(wpm >= 390)
414 {
415 speed.min_sample_len = 450 - (wpm - 400)/2;
416 if(wpm > 440)
417 speed.min_sample_len = 420 - (wpm - 440);
418 }
419
420 speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length
421 speed.clause_pause_factor = 0;
422
423 if(wpm > 430)
424 {
425 speed.pause_factor = 12;
426 // speed.clause_pause_factor = 15;
427 }
428 else
429 if(wpm > 400)
430 {
431 speed.pause_factor = 13;
432 // speed.clause_pause_factor = 15;
433 }
434 else
435 if(wpm > 374)
436 {
437 speed.pause_factor = 14;
438 }
439 else
440 if(wpm > 350)
441 {
442 speed.pause_factor = pause_factor_350[wpm - 350];
443 }
444
445 if(speed.clause_pause_factor == 0)
446 {
447 // restrict the reduction of pauses between clauses
448 if((speed.clause_pause_factor = speed.pause_factor) < 16)
449 speed.clause_pause_factor = 16;
450 }
451 }
452
453 #ifdef TEST_SPEED
454 //if(control==3)
455 printf("%3d: speedf %d %d %d pause=%d %d wav=%d lenmod=%d %d\n",wpm,speed1,speed2,speed3, speed.pause_factor,speed.clause_pause_factor, speed.wav_factor,speed.lenmod_factor,speed.lenmod2_factor);
456 #endif
457 } // end of SetSpeed
458
459 #endif // of INCLUDE_SONIC
460
461
462 #ifdef deleted
SetAmplitude(int amp)463 void SetAmplitude(int amp)
464 {//=======================
465 static unsigned char amplitude_factor[] = {0,5,6,7,9,11,14,17,21,26, 32, 38,44,50,56,63,70,77,84,91,100 };
466
467 if((amp >= 0) && (amp <= 20))
468 {
469 option_amplitude = (amplitude_factor[amp] * 480)/256;
470 }
471 }
472 #endif
473
474
475
SetParameter(int parameter,int value,int relative)476 void SetParameter(int parameter, int value, int relative)
477 {//======================================================
478 // parameter: reset-all, amp, pitch, speed, linelength, expression, capitals, number grouping
479 // relative 0=absolute 1=relative
480
481 int new_value = value;
482 int default_value;
483
484 if(relative)
485 {
486 if(parameter < 5)
487 {
488 default_value = param_defaults[parameter];
489 new_value = default_value + (default_value * value)/100;
490 }
491 }
492 param_stack[0].parameter[parameter] = new_value;
493 saved_parameters[parameter] = new_value;
494
495 switch(parameter)
496 {
497 case espeakRATE:
498 embedded_value[EMBED_S] = new_value;
499 embedded_value[EMBED_S2] = new_value;
500 SetSpeed(3);
501 break;
502
503 case espeakVOLUME:
504 embedded_value[EMBED_A] = new_value;
505 GetAmplitude();
506 break;
507
508 case espeakPITCH:
509 if(new_value > 99) new_value = 99;
510 if(new_value < 0) new_value = 0;
511 embedded_value[EMBED_P] = new_value;
512 break;
513
514 case espeakRANGE:
515 if(new_value > 99) new_value = 99;
516 embedded_value[EMBED_R] = new_value;
517 break;
518
519 case espeakLINELENGTH:
520 option_linelength = new_value;
521 break;
522
523 case espeakWORDGAP:
524 option_wordgap = new_value;
525 break;
526
527 case espeakINTONATION:
528 if((new_value & 0xff) != 0)
529 translator->langopts.intonation_group = new_value & 0xff;
530 option_tone_flags = new_value;
531 break;
532
533 default:
534 break;
535 }
536 } // end of SetParameter
537
538
539
DoEmbedded2(int * embix)540 static void DoEmbedded2(int *embix)
541 {//================================
542 // There were embedded commands in the text at this point
543
544 unsigned int word;
545
546 do {
547 word = embedded_list[(*embix)++];
548
549 if((word & 0x1f) == EMBED_S)
550 {
551 // speed
552 SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S]
553 SetSpeed(1);
554 }
555 } while((word & 0x80) == 0);
556 }
557
558
CalcLengths(Translator * tr)559 void CalcLengths(Translator *tr)
560 {//==============================
561 int ix;
562 int ix2;
563 PHONEME_LIST *prev;
564 PHONEME_LIST *next;
565 PHONEME_LIST *next2;
566 PHONEME_LIST *next3;
567 PHONEME_LIST *p;
568 PHONEME_LIST *p2;
569
570 int stress;
571 int type;
572 static int more_syllables=0;
573 int pre_sonorant=0;
574 int pre_voiced=0;
575 int last_pitch = 0;
576 int pitch_start;
577 int length_mod;
578 int next2type;
579 int len;
580 int env2;
581 int end_of_clause;
582 int embedded_ix = 0;
583 int min_drop;
584 int pitch1;
585 int emphasized;
586 int tone_mod;
587 unsigned char *pitch_env=NULL;
588 PHONEME_DATA phdata_tone;
589
590 for(ix=1; ix<n_phoneme_list; ix++)
591 {
592 prev = &phoneme_list[ix-1];
593 p = &phoneme_list[ix];
594 stress = p->stresslevel & 0x7;
595 emphasized = p->stresslevel & 0x8;
596
597 next = &phoneme_list[ix+1];
598
599 if(p->synthflags & SFLAG_EMBEDDED)
600 {
601 DoEmbedded2(&embedded_ix);
602 }
603
604 type = p->type;
605 if(p->synthflags & SFLAG_SYLLABLE)
606 type = phVOWEL;
607
608 switch(type)
609 {
610 case phPAUSE:
611 last_pitch = 0;
612 break;
613
614 case phSTOP:
615 last_pitch = 0;
616 if(prev->type == phFRICATIVE)
617 p->prepause = 25;
618 else
619 if((more_syllables > 0) || (stress < 4))
620 p->prepause = 48;
621 else
622 p->prepause = 60;
623
624 if(prev->type == phSTOP)
625 p->prepause = 60;
626
627 if((tr->langopts.word_gap & 0x10) && (p->newword))
628 p->prepause = 60;
629
630 if(p->ph->phflags & phLENGTHENSTOP)
631 p->prepause += 30;
632
633 if(p->synthflags & SFLAG_LENGTHEN)
634 p->prepause += tr->langopts.long_stop;
635 break;
636
637 case phVFRICATIVE:
638 case phFRICATIVE:
639 if(p->newword)
640 {
641 if((prev->type == phVOWEL) && (p->ph->phflags & phNOPAUSE))
642 {
643 }
644 else
645 {
646 p->prepause = 15;
647 }
648 }
649
650 if(next->type==phPAUSE && prev->type==phNASAL && !(p->ph->phflags&phFORTIS))
651 p->prepause = 25;
652
653 if(prev->ph->phflags & phBRKAFTER)
654 p->prepause = 30;
655
656 if((tr->langopts.word_gap & 0x10) && (p->newword))
657 p->prepause = 30;
658
659 if((p->ph->phflags & phSIBILANT) && next->type==phSTOP && !next->newword)
660 {
661 if(prev->type == phVOWEL)
662 p->length = 200; // ?? should do this if it's from a prefix
663 else
664 p->length = 150;
665 }
666 else
667 p->length = 256;
668
669 if(type == phVFRICATIVE)
670 {
671 if(next->type==phVOWEL)
672 {
673 pre_voiced = 1;
674 }
675 if((prev->type==phVOWEL) || (prev->type == phLIQUID))
676 {
677 p->length = (255 + prev->length)/2;
678 }
679 }
680 break;
681
682 case phVSTOP:
683 if(prev->type==phVFRICATIVE || prev->type==phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID))
684 p->prepause = 30;
685
686 if(next->type==phVOWEL || next->type==phLIQUID)
687 {
688 if((next->type==phVOWEL) || !next->newword)
689 pre_voiced = 1;
690
691 p->prepause = 40;
692
693 if(prev->type == phVOWEL)
694 {
695 p->prepause = 0; // use murmur instead to link from the preceding vowel
696 }
697 else
698 if(prev->type == phPAUSE)
699 {
700 // reduce by the length of the preceding pause
701 if(prev->length < p->prepause)
702 p->prepause -= prev->length;
703 else
704 p->prepause = 0;
705 }
706 else
707 if(p->newword==0)
708 {
709 if(prev->type==phLIQUID)
710 p->prepause = 20;
711 if(prev->type==phNASAL)
712 p->prepause = 12;
713
714 if(prev->type==phSTOP && !(prev->ph->phflags & phFORTIS))
715 p->prepause = 0;
716 }
717 }
718 if((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20))
719 p->prepause = 20;
720
721 break;
722
723 case phLIQUID:
724 case phNASAL:
725 p->amp = tr->stress_amps[0]; // unless changed later
726 p->length = 256; // TEMPORARY
727 min_drop = 0;
728
729 if(p->newword)
730 {
731 if(prev->type==phLIQUID)
732 p->prepause = 25;
733 if(prev->type==phVOWEL)
734 {
735 if(!(p->ph->phflags & phNOPAUSE))
736 p->prepause = 12;
737 }
738 }
739
740 if(next->type==phVOWEL)
741 {
742 pre_sonorant = 1;
743 }
744 else
745 {
746 p->pitch2 = last_pitch;
747
748 if((prev->type==phVOWEL) || (prev->type == phLIQUID))
749 {
750 p->length = prev->length;
751
752 if(p->type == phLIQUID)
753 {
754 p->length = speed1;
755 }
756
757 if(next->type == phVSTOP)
758 {
759 p->length = (p->length * 160)/100;
760 }
761 if(next->type == phVFRICATIVE)
762 {
763 p->length = (p->length * 120)/100;
764 }
765 }
766 else
767 {
768 for(ix2=ix; ix2<n_phoneme_list; ix2++)
769 {
770 if(phoneme_list[ix2].type == phVOWEL)
771 {
772 p->pitch2 = phoneme_list[ix2].pitch2;
773 break;
774 }
775 }
776 }
777
778 p->pitch1 = p->pitch2-16;
779 if(p->pitch2 < 16)
780 {
781 p->pitch1 = 0;
782 }
783 p->env = PITCHfall;
784 pre_voiced = 0;
785 }
786 break;
787
788 case phVOWEL:
789 min_drop = 0;
790 next2 = &phoneme_list[ix+2];
791 next3 = &phoneme_list[ix+3];
792
793 if(stress > 7) stress = 7;
794
795 if(stress <= 1)
796 {
797 stress = stress ^ 1; // swap diminished and unstressed (until we swap stress_amps,stress_lengths in tr_languages)
798 }
799 if(pre_sonorant)
800 p->amp = tr->stress_amps[stress]-1;
801 else
802 p->amp = tr->stress_amps[stress];
803
804 if(emphasized)
805 p->amp = 25;
806
807 if(ix >= (n_phoneme_list-3))
808 {
809 // last phoneme of a clause, limit its amplitude
810 if(p->amp > tr->langopts.param[LOPT_MAXAMP_EOC])
811 p->amp = tr->langopts.param[LOPT_MAXAMP_EOC];
812 }
813
814 // is the last syllable of a word ?
815 more_syllables=0;
816 end_of_clause = 0;
817 for(p2 = p+1; p2->newword== 0; p2++)
818 {
819 if((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC))
820 more_syllables++;
821
822 if(p2->ph->code == phonPAUSE_CLAUSE)
823 end_of_clause = 2;
824 }
825 if(p2->ph->code == phonPAUSE_CLAUSE)
826 end_of_clause = 2;
827
828 if((p2->newword & 2) && (more_syllables==0))
829 {
830 end_of_clause = 2;
831 }
832
833 // calc length modifier
834 if((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE))
835 {
836 // if PAUSE_VSHORT is followed by a pause, then use that
837 next = next2;
838 next2 = next3;
839 next3 = &phoneme_list[ix+4];
840 }
841
842 next2type = next2->ph->length_mod;
843 if(more_syllables==0)
844 {
845 if(next->newword || next2->newword)
846 {
847 // don't use 2nd phoneme over a word boundary, unless it's a pause
848 if(next2type != 1)
849 next2type = 0;
850 }
851
852 len = tr->langopts.length_mods0[next2type *10+ next->ph->length_mod];
853
854 if((next->newword) && (tr->langopts.word_gap & 0x20))
855 {
856 // consider as a pause + first phoneme of the next word
857 length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2;
858 }
859 else
860 length_mod = len;
861 }
862 else
863 {
864 length_mod = tr->langopts.length_mods[next2type *10+ next->ph->length_mod];
865
866 if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS))
867 length_mod -= 15;
868 }
869
870 if(more_syllables==0)
871 length_mod *= speed1;
872 else
873 if(more_syllables==1)
874 length_mod *= speed2;
875 else
876 length_mod *= speed3;
877
878 length_mod = length_mod / 128;
879
880 if(length_mod < 8)
881 length_mod = 8; // restrict how much lengths can be reduced
882
883 if(stress >= 7)
884 {
885 // tonic syllable, include a constant component so it doesn't decrease directly with speed
886 length_mod += tr->langopts.lengthen_tonic;
887 if(emphasized)
888 length_mod += (tr->langopts.lengthen_tonic/2);
889 }
890 else
891 if(emphasized)
892 {
893 length_mod += tr->langopts.lengthen_tonic;
894 }
895
896 if((len = tr->stress_lengths[stress]) == 0)
897 len = tr->stress_lengths[6];
898
899 length_mod = length_mod * len;
900
901 if(p->tone_ph != 0)
902 {
903 if((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0)
904 {
905 // a tone phoneme specifies a percentage change to the length
906 length_mod = (length_mod * tone_mod) / 100;
907 }
908 }
909
910
911 if((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN))
912 {
913 // this is the last syllable in the clause, lengthen it - more for short vowels
914 len = (p->ph->std_length * 2);
915 if(tr->langopts.stress_flags & S_EO_CLAUSE1)
916 len=200; // don't lengthen short vowels more than long vowels at end-of-clause
917 length_mod = length_mod * (256 + (280 - len)/3)/256;
918 }
919
920 if(length_mod > tr->langopts.max_lengthmod*speed1)
921 {
922 //limit the vowel length adjustment for some languages
923 length_mod = (tr->langopts.max_lengthmod*speed1);
924 }
925
926 length_mod = length_mod / 128;
927
928 if(p->type != phVOWEL)
929 {
930 length_mod = 256; // syllabic consonant
931 min_drop = 16;
932 }
933 p->length = length_mod;
934
935 if(p->env >= (N_ENVELOPE_DATA-1))
936 {
937 fprintf(stderr,"espeak: Bad intonation data\n");
938 p->env = 0;
939 }
940
941 // pre-vocalic part
942 // set last-pitch
943 env2 = p->env + 1; // version for use with preceding semi-vowel
944
945 if(p->tone_ph != 0)
946 {
947 InterpretPhoneme2(p->tone_ph, &phdata_tone);
948 pitch_env = GetEnvelope(phdata_tone.pitch_env);
949 }
950 else
951 {
952 pitch_env = envelope_data[env2];
953 }
954
955 pitch_start = p->pitch1 + ((p->pitch2-p->pitch1)*pitch_env[0])/256;
956
957 if(pre_sonorant || pre_voiced)
958 {
959 // set pitch for pre-vocalic part
960 if(pitch_start == 255)
961 last_pitch = pitch_start; // pitch is not set
962
963 if(pitch_start - last_pitch > 16)
964 last_pitch = pitch_start - 16;
965
966 prev->pitch1 = last_pitch;
967 prev->pitch2 = pitch_start;
968 if(last_pitch < pitch_start)
969 {
970 prev->env = PITCHrise;
971 p->env = env2;
972 }
973 else
974 {
975 prev->env = PITCHfall;
976 }
977
978 prev->length = length_mod;
979
980 prev->amp = p->amp;
981 if((prev->type != phLIQUID) && (prev->amp > 18))
982 prev->amp = 18;
983 }
984
985 // vowel & post-vocalic part
986 next->synthflags &= ~SFLAG_SEQCONTINUE;
987 if(next->type == phNASAL && next2->type != phVOWEL)
988 next->synthflags |= SFLAG_SEQCONTINUE;
989
990 if(next->type == phLIQUID)
991 {
992 next->synthflags |= SFLAG_SEQCONTINUE;
993
994 if(next2->type == phVOWEL)
995 {
996 next->synthflags &= ~SFLAG_SEQCONTINUE;
997 }
998
999 if(next2->type != phVOWEL)
1000 {
1001 if(next->ph->mnemonic == ('/'*256+'r'))
1002 {
1003 next->synthflags &= ~SFLAG_SEQCONTINUE;
1004 // min_drop = 15;
1005 }
1006 }
1007 }
1008
1009 if((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop))
1010 {
1011 pitch1 = p->pitch2 - min_drop;
1012 if(pitch1 < 0)
1013 pitch1 = 0;
1014 p->pitch1 = pitch1;
1015 }
1016
1017 last_pitch = p->pitch1 + ((p->pitch2-p->pitch1)*envelope_data[p->env][127])/256;
1018 pre_sonorant = 0;
1019 pre_voiced = 0;
1020 break;
1021 }
1022 }
1023 } // end of CalcLengths
1024
1025