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 #include "StdAfx.h"
21 
22 // this version keeps wavemult window as a constant fraction
23 // of the cycle length - but that spreads out the HF peaks too much
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <math.h>
29 
30 
31 
32 #include "speak_lib.h"
33 #include "speech.h"
34 #include "phoneme.h"
35 #include "synthesize.h"
36 #include "voice.h"
37 
38 #ifdef INCLUDE_SONIC
39 #include "sonic.h"
40 #endif
41 
42 #ifdef USE_PORTAUDIO
43 #include "portaudio.h"
44 #undef USE_PORTAUDIO
45 // determine portaudio version by looking for a #define which is not in V18
46 #ifdef paNeverDropInput
47 #define USE_PORTAUDIO   19
48 #else
49 #define USE_PORTAUDIO   18
50 #endif
51 #endif
52 
53 #define N_SINTAB  2048
54 #include "sintab.h"
55 
56 
57 #define PI  3.1415927
58 #define PI2 6.283185307
59 #define N_WAV_BUF   10
60 
61 voice_t *wvoice;
62 
63 FILE *f_log = NULL;
64 int option_waveout = 0;
65 static int option_harmonic1 = 10;   // 10
66 int option_log_frames = 0;
67 static int flutter_amp = 64;
68 
69 static int general_amplitude = 60;
70 static int consonant_amp = 26;   // 24
71 
72 int embedded_value[N_EMBEDDED_VALUES];
73 
74 static int PHASE_INC_FACTOR;
75 int samplerate = 0;       // this is set by Wavegeninit()
76 int samplerate_native=0;
77 extern int option_device_number;
78 extern int option_quiet;
79 
80 static wavegen_peaks_t peaks[N_PEAKS];
81 static int peak_harmonic[N_PEAKS];
82 static int peak_height[N_PEAKS];
83 
84 int echo_head;
85 int echo_tail;
86 int echo_amp = 0;
87 short echo_buf[N_ECHO_BUF];
88 static int echo_length = 0;   // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho()
89 
90 static int voicing;
91 static RESONATOR rbreath[N_PEAKS];
92 
93 static int harm_sqrt_n = 0;
94 
95 
96 #define N_LOWHARM  30
97 static int harm_inc[N_LOWHARM];    // only for these harmonics do we interpolate amplitude between steps
98 static int *harmspect;
99 static int hswitch=0;
100 static int hspect[2][MAX_HARMONIC];         // 2 copies, we interpolate between then
101 static int max_hval=0;
102 
103 static int nsamples=0;       // number to do
104 static int modulation_type = 0;
105 static int glottal_flag = 0;
106 static int glottal_reduce = 0;
107 
108 
109 WGEN_DATA wdata;
110 
111 static int amp_ix;
112 static int amp_inc;
113 static unsigned char *amplitude_env = NULL;
114 
115 static int samplecount=0;    // number done
116 static int samplecount_start=0;  // count at start of this segment
117 static int end_wave=0;      // continue to end of wave cycle
118 static int wavephase;
119 static int phaseinc;
120 static int cycle_samples;         // number of samples in a cycle at current pitch
121 static int cbytes;
122 static int hf_factor;
123 
124 static double minus_pi_t;
125 static double two_pi_t;
126 
127 
128 unsigned char *out_ptr;
129 unsigned char *out_start;
130 unsigned char *out_end;
131 int outbuf_size = 0;
132 
133 // the queue of operations passed to wavegen from sythesize
134 long64 wcmdq[N_WCMDQ][4];
135 int wcmdq_head=0;
136 int wcmdq_tail=0;
137 
138 // pitch,speed,
139 int embedded_default[N_EMBEDDED_VALUES]        = {0,    50,175,100,50, 0, 0, 0,175,0,0,0,0,0,0};
140 static int embedded_max[N_EMBEDDED_VALUES]     = {0,0x7fff,750,300,99,99,99, 0,750,0,0,0,0,4,0};
141 
142 #define N_CALLBACK_IX N_WAV_BUF-2   // adjust this delay to match display with the currently spoken word
143 int current_source_index=0;
144 
145 extern FILE *f_wave;
146 
147 #if (USE_PORTAUDIO == 18)
148 static PortAudioStream *pa_stream=NULL;
149 #endif
150 #if (USE_PORTAUDIO == 19)
151 static PaStream *pa_stream=NULL;
152 #endif
153 
154 #ifdef INCLUDE_SONIC
155 static sonicStream sonicSpeedupStream = NULL;
156 double sonicSpeed = 1.0;
157 #endif
158 
159 // 1st index=roughness
160 // 2nd index=modulation_type
161 // value: bits 0-3  amplitude (16ths), bits 4-7 every n cycles
162 #define N_ROUGHNESS 8
163 static unsigned char modulation_tab[N_ROUGHNESS][8] = {
164 	{0, 0x00, 0x00, 0x00, 0, 0x46, 0xf2, 0x29},
165 	{0, 0x2f, 0x00, 0x2f, 0, 0x45, 0xf2, 0x29},
166 	{0, 0x2f, 0x00, 0x2e, 0, 0x45, 0xf2, 0x28},
167 	{0, 0x2e, 0x00, 0x2d, 0, 0x34, 0xf2, 0x28},
168 	{0, 0x2d, 0x2d, 0x2c, 0, 0x34, 0xf2, 0x28},
169 	{0, 0x2b, 0x2b, 0x2b, 0, 0x34, 0xf2, 0x28},
170 	{0, 0x2a, 0x2a, 0x2a, 0, 0x34, 0xf2, 0x28},
171 	{0, 0x29, 0x29, 0x29, 0, 0x34, 0xf2, 0x28},
172 };
173 
174 // Flutter table, to add natural variations to the pitch
175 #define N_FLUTTER  0x170
176 static int Flutter_inc;
177 static const unsigned char Flutter_tab[N_FLUTTER] = {
178    0x80, 0x9b, 0xb5, 0xcb, 0xdc, 0xe8, 0xed, 0xec,
179    0xe6, 0xdc, 0xce, 0xbf, 0xb0, 0xa3, 0x98, 0x90,
180    0x8c, 0x8b, 0x8c, 0x8f, 0x92, 0x94, 0x95, 0x92,
181    0x8c, 0x83, 0x78, 0x69, 0x59, 0x49, 0x3c, 0x31,
182    0x2a, 0x29, 0x2d, 0x36, 0x44, 0x56, 0x69, 0x7d,
183    0x8f, 0x9f, 0xaa, 0xb1, 0xb2, 0xad, 0xa4, 0x96,
184    0x87, 0x78, 0x69, 0x5c, 0x53, 0x4f, 0x4f, 0x55,
185    0x5e, 0x6b, 0x7a, 0x88, 0x96, 0xa2, 0xab, 0xb0,
186 
187    0xb1, 0xae, 0xa8, 0xa0, 0x98, 0x91, 0x8b, 0x88,
188    0x89, 0x8d, 0x94, 0x9d, 0xa8, 0xb2, 0xbb, 0xc0,
189    0xc1, 0xbd, 0xb4, 0xa5, 0x92, 0x7c, 0x63, 0x4a,
190    0x32, 0x1e, 0x0e, 0x05, 0x02, 0x05, 0x0f, 0x1e,
191    0x30, 0x44, 0x59, 0x6d, 0x7f, 0x8c, 0x96, 0x9c,
192    0x9f, 0x9f, 0x9d, 0x9b, 0x99, 0x99, 0x9c, 0xa1,
193    0xa9, 0xb3, 0xbf, 0xca, 0xd5, 0xdc, 0xe0, 0xde,
194    0xd8, 0xcc, 0xbb, 0xa6, 0x8f, 0x77, 0x60, 0x4b,
195 
196    0x3a, 0x2e, 0x28, 0x29, 0x2f, 0x3a, 0x48, 0x59,
197    0x6a, 0x7a, 0x86, 0x90, 0x94, 0x95, 0x91, 0x89,
198    0x80, 0x75, 0x6b, 0x62, 0x5c, 0x5a, 0x5c, 0x61,
199    0x69, 0x74, 0x80, 0x8a, 0x94, 0x9a, 0x9e, 0x9d,
200    0x98, 0x90, 0x86, 0x7c, 0x71, 0x68, 0x62, 0x60,
201    0x63, 0x6b, 0x78, 0x88, 0x9b, 0xaf, 0xc2, 0xd2,
202    0xdf, 0xe6, 0xe7, 0xe2, 0xd7, 0xc6, 0xb2, 0x9c,
203    0x84, 0x6f, 0x5b, 0x4b, 0x40, 0x39, 0x37, 0x38,
204 
205    0x3d, 0x43, 0x4a, 0x50, 0x54, 0x56, 0x55, 0x52,
206    0x4d, 0x48, 0x42, 0x3f, 0x3e, 0x41, 0x49, 0x56,
207    0x67, 0x7c, 0x93, 0xab, 0xc3, 0xd9, 0xea, 0xf6,
208    0xfc, 0xfb, 0xf4, 0xe7, 0xd5, 0xc0, 0xaa, 0x94,
209    0x80, 0x71, 0x64, 0x5d, 0x5a, 0x5c, 0x61, 0x68,
210    0x70, 0x77, 0x7d, 0x7f, 0x7f, 0x7b, 0x74, 0x6b,
211    0x61, 0x57, 0x4e, 0x48, 0x46, 0x48, 0x4e, 0x59,
212    0x66, 0x75, 0x84, 0x93, 0x9f, 0xa7, 0xab, 0xaa,
213 
214    0xa4, 0x99, 0x8b, 0x7b, 0x6a, 0x5b, 0x4e, 0x46,
215    0x43, 0x45, 0x4d, 0x5a, 0x6b, 0x7f, 0x92, 0xa6,
216    0xb8, 0xc5, 0xcf, 0xd3, 0xd2, 0xcd, 0xc4, 0xb9,
217    0xad, 0xa1, 0x96, 0x8e, 0x89, 0x87, 0x87, 0x8a,
218    0x8d, 0x91, 0x92, 0x91, 0x8c, 0x84, 0x78, 0x68,
219    0x55, 0x41, 0x2e, 0x1c, 0x0e, 0x05, 0x01, 0x05,
220    0x0f, 0x1f, 0x34, 0x4d, 0x68, 0x81, 0x9a, 0xb0,
221    0xc1, 0xcd, 0xd3, 0xd3, 0xd0, 0xc8, 0xbf, 0xb5,
222 
223    0xab, 0xa4, 0x9f, 0x9c, 0x9d, 0xa0, 0xa5, 0xaa,
224    0xae, 0xb1, 0xb0, 0xab, 0xa3, 0x96, 0x87, 0x76,
225    0x63, 0x51, 0x42, 0x36, 0x2f, 0x2d, 0x31, 0x3a,
226    0x48, 0x59, 0x6b, 0x7e, 0x8e, 0x9c, 0xa6, 0xaa,
227    0xa9, 0xa3, 0x98, 0x8a, 0x7b, 0x6c, 0x5d, 0x52,
228    0x4a, 0x48, 0x4a, 0x50, 0x5a, 0x67, 0x75, 0x82
229 };
230 
231 // waveform shape table for HF peaks, formants 6,7,8
232 #define N_WAVEMULT 128
233 static int wavemult_offset=0;
234 static int wavemult_max=0;
235 
236 // the presets are for 22050 Hz sample rate.
237 // A different rate will need to recalculate the presets in WavegenInit()
238 static unsigned char wavemult[N_WAVEMULT] = {
239   0,  0,  0,  2,  3,  5,  8, 11, 14, 18, 22, 27, 32, 37, 43, 49,
240     55, 62, 69, 76, 83, 90, 98,105,113,121,128,136,144,152,159,166,
241    174,181,188,194,201,207,213,218,224,228,233,237,240,244,246,249,
242    251,252,253,253,253,253,252,251,249,246,244,240,237,233,228,224,
243    218,213,207,201,194,188,181,174,166,159,152,144,136,128,121,113,
244    105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14,
245     11,  8,  5,  3,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
246      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 };
247 
248 
249 // set from y = pow(2,x) * 128,  x=-1 to 1
250 unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = {
251     64, 65, 66, 67, 68, 69, 70, 71,
252     72, 73, 74, 75, 76, 77, 78, 79,
253     80, 81, 82, 83, 84, 86, 87, 88,
254     89, 91, 92, 93, 94, 96, 97, 98,
255    100,101,103,104,105,107,108,110,
256    111,113,115,116,118,119,121,123,
257    124,126,128,130,132,133,135,137,
258    139,141,143,145,147,149,151,153,
259    155,158,160,162,164,167,169,171,
260    174,176,179,181,184,186,189,191,
261    194,197,199,202,205,208,211,214,
262    217,220,223,226,229,232,236,239,
263    242,246,249,252, 254,255 };
264 
265 
266 #ifdef LOG_FRAMES
LogMarker(int type,int value,int value2)267 static void LogMarker(int type, int value, int value2)
268 {//===================================================
269 	char buf[20];
270 	int *p;
271 
272 	if(option_log_frames == 0)
273 		return;
274 
275 	if((type == espeakEVENT_PHONEME) || (type == espeakEVENT_SENTENCE))
276 	{
277 		f_log=fopen("log-espeakedit","a");
278 		if(f_log)
279 		{
280 			if(type == espeakEVENT_PHONEME)
281 			{
282 				p = (int *)buf;
283 				p[0] = value;
284 				p[1] = value2;
285 				buf[8] = 0;
286 				fprintf(f_log,"Phoneme [%s]\n", buf);
287 			}
288 			else
289 				fprintf(f_log,"\n");
290 			fclose(f_log);
291 			f_log = NULL;
292 		}
293 	}
294 }
295 #endif
296 
WcmdqStop()297 void WcmdqStop()
298 {//=============
299 	wcmdq_head = 0;
300 	wcmdq_tail = 0;
301 
302 #ifdef INCLUDE_SONIC
303 	if(sonicSpeedupStream != NULL)
304 	{
305 		sonicDestroyStream(sonicSpeedupStream);
306 		sonicSpeedupStream = NULL;
307 	}
308 #endif
309 
310 #ifdef USE_PORTAUDIO
311 	Pa_AbortStream(pa_stream);
312 #endif
313 	if(mbrola_name[0] != 0)
314 		MbrolaReset();
315 }
316 
317 
WcmdqFree()318 int WcmdqFree()
319 {//============
320 	int i;
321 	i = wcmdq_head - wcmdq_tail;
322 	if(i <= 0) i += N_WCMDQ;
323 	return(i);
324 }
325 
WcmdqUsed()326 int WcmdqUsed()
327 {//============
328    return(N_WCMDQ - WcmdqFree());
329 }
330 
331 
WcmdqInc()332 void WcmdqInc()
333 {//============
334 	wcmdq_tail++;
335 	if(wcmdq_tail >= N_WCMDQ) wcmdq_tail=0;
336 }
337 
WcmdqIncHead()338 static void WcmdqIncHead()
339 {//=======================
340 	wcmdq_head++;
341 	if(wcmdq_head >= N_WCMDQ) wcmdq_head=0;
342 }
343 
344 
345 
346 // data points from which to make the presets for pk_shape1 and pk_shape2
347 #define PEAKSHAPEW 256
348 static const float pk_shape_x[2][8] = {
349 	{0,-0.6f, 0.0f, 0.6f, 1.4f, 2.5f, 4.5f, 5.5f},
350 	{0,-0.6f, 0.0f, 0.6f, 1.4f, 2.0f, 4.5f, 5.5f }};
351 static const float pk_shape_y[2][8] = {
352 	{0,  67,  81,  67,  31,  14,   0,  -6} ,
353 	{0,  77,  81,  77,  31,   7,   0,  -6 }};
354 
355 unsigned char pk_shape1[PEAKSHAPEW+1] = {
356    255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246,
357    245,244,242,241,239,238,236,234,233,231,229,227,225,223,220,218,
358    216,213,211,209,207,205,203,201,199,197,195,193,191,189,187,185,
359    183,180,178,176,173,171,169,166,164,161,159,156,154,151,148,146,
360    143,140,138,135,132,129,126,123,120,118,115,112,108,105,102, 99,
361     96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73,
362     72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55,
363     55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46,
364     45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43,
365     42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33,
366     32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24,
367     23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16,
368     16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10,
369     10,  9,  9,  9,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  5,  5,
370      5,  5,  4,  4,  4,  4,  4,  3,  3,  3,  3,  2,  2,  2,  2,  2,
371      2,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,
372      0 };
373 
374 static unsigned char pk_shape2[PEAKSHAPEW+1] = {
375    255,254,254,254,254,254,254,254,254,254,253,253,253,253,252,252,
376    252,251,251,251,250,250,249,249,248,248,247,247,246,245,245,244,
377    243,243,242,241,239,237,235,233,231,229,227,225,223,221,218,216,
378    213,211,208,205,203,200,197,194,191,187,184,181,178,174,171,167,
379    163,160,156,152,148,144,140,136,132,127,123,119,114,110,105,100,
380     96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60,
381     57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27,
382     25, 23, 21, 19, 18, 16, 14, 12, 11,  9,  7,  6,  4,  3,  1,  0,
383      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
384      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
385      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
386      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
387      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
388      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
389      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
390      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
391      0 };
392 
393 static unsigned char *pk_shape;
394 
395 
WavegenInitPkData(int which)396 static void WavegenInitPkData(int which)
397 {//=====================================
398 // this is only needed to set up the presets for pk_shape1 and pk_shape2
399 // These have already been pre-calculated and preset
400 #ifdef deleted
401 	int ix;
402 	int p;
403 	float x;
404 	float y[PEAKSHAPEW];
405 	float maxy=0;
406 
407 	if(which==0)
408 		pk_shape = pk_shape1;
409 	else
410 		pk_shape = pk_shape2;
411 
412 	p = 0;
413 	for(ix=0;ix<PEAKSHAPEW;ix++)
414 	{
415 		x = (4.5*ix)/PEAKSHAPEW;
416 		if(x >= pk_shape_x[which][p+3]) p++;
417 		y[ix] = polint(&pk_shape_x[which][p],&pk_shape_y[which][p],3,x);
418 		if(y[ix] > maxy) maxy = y[ix];
419 	}
420 	for(ix=0;ix<PEAKSHAPEW;ix++)
421 	{
422 		p = (int)(y[ix]*255/maxy);
423       pk_shape[ix] = (p >= 0) ? p : 0;
424 	}
425 	pk_shape[PEAKSHAPEW]=0;
426 #endif
427 }  //  end of WavegenInitPkData
428 
429 
430 
431 #ifdef USE_PORTAUDIO
432 // PortAudio interface
433 
434 static int userdata[4];
435 static PaError pa_init_err=0;
436 static int out_channels=1;
437 
438 unsigned char *outbuffer = NULL;
439 int outbuffer_size = 0;
440 
441 
442 #if USE_PORTAUDIO == 18
WaveCallback(void * inputBuffer,void * outputBuffer,unsigned long framesPerBuffer,PaTimestamp outTime,void * userData)443 static int WaveCallback(void *inputBuffer, void *outputBuffer,
444 		unsigned long framesPerBuffer, PaTimestamp outTime, void *userData )
445 #else
446 static int WaveCallback(const void *inputBuffer, void *outputBuffer,
447 		long unsigned int framesPerBuffer, const PaStreamCallbackTimeInfo *outTime,
448 		PaStreamCallbackFlags flags, void *userData )
449 #endif
450 {
451 	int ix;
452 	int result;
453 	unsigned char *p;
454 	unsigned char *out_buf;
455 	unsigned char *out_end2;
456 	int pa_size;
457 
458 	pa_size = framesPerBuffer*2;
459 
460 	// make a buffer 3x size of the portaudio output
461 	ix = pa_size*3;
462 	if(ix > outbuffer_size)
463 	{
464 		outbuffer = (unsigned char *)realloc(outbuffer, ix);
465 		if(outbuffer == NULL)
466 		{
467 			fprintf(stderr, "espeak: out of memory\n");
468 		}
469 		outbuffer_size = ix;
470 		out_ptr = NULL;
471 	}
472 	if(out_ptr == NULL)
473 	{
474 		out_ptr = out_start = outbuffer;
475 		out_end = out_start + outbuffer_size;
476 	}
477 	out_end2 = &outbuffer[pa_size];  // top of data needed for the portaudio buffer
478 
479 #ifdef LIBRARY
480 	event_list_ix = 0;
481 #endif
482 
483 	result = WavegenFill(1);
484 
485 	// copy from the outbut buffer into the portaudio buffer
486 	if(result && (out_ptr > out_end2))
487 	{
488 		result = 0;   // don't end yet, there is more data in the buffer than can fit in portaudio
489 	}
490 
491 	while(out_ptr < out_end2)
492 		*out_ptr++ = 0;  // fill with zeros up to the size of the portaudio buffer
493 
494 	memcpy(outputBuffer, outbuffer, pa_size);
495 
496 	// move the remaining contents of the start of the output buffer
497 	for(p = out_end2; p < out_end; p++)
498 	{
499 		p[-pa_size] = p[0];
500 	}
501 	out_ptr -= pa_size;
502 
503 #ifdef LIBRARY
504 	count_samples += framesPerBuffer;
505 	if(synth_callback)
506 	{
507 		// synchronous-playback mode, allow the calling process to abort the speech
508 		event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list
509 		event_list[event_list_ix].user_data = 0;
510 
511 		if(synth_callback(NULL,0,event_list) == 1)
512 		{
513 			SpeakNextClause(NULL,NULL,2);  // stop speaking
514 			result = 1;
515 		}
516 	}
517 #endif
518 
519 #ifdef ARCH_BIG
520 	{
521 		// swap the order of bytes in each sound sample in the portaudio buffer
522 		int c;
523 		unsigned char *buf_end;
524 		out_buf = (unsigned char *)outputBuffer;
525 		buf_end = out_buf + framesPerBuffer*2;
526 		while(out_buf < buf_end)
527 		{
528 			c = out_buf[0];
529 			out_buf[0] = out_buf[1];
530 			out_buf[1] = c;
531 			out_buf += 2;
532 		}
533 	}
534 #endif
535 
536 	if(out_channels == 2)
537 	{
538 		// sound output can only do stereo, not mono.  Duplicate each sound sample to
539 		// produce 2 channels.
540 		out_buf = (unsigned char *)outputBuffer;
541 		for(ix=framesPerBuffer-1; ix>=0; ix--)
542 		{
543 			p = &out_buf[ix*4];
544 			p[3] = p[1] = out_buf[ix*2 + 1];
545 			p[2] = p[0] = out_buf[ix*2];
546 		}
547 	}
548 
549 #if USE_PORTAUDIO == 18
550 #ifdef PLATFORM_WINDOWS
551 	return(result);
552 #endif
553 	if(result != 0)
554 	{
555 		static int end_timer = 0;
556 		if(end_timer == 0)
557 			end_timer = 4;
558 		if(end_timer > 0)
559 		{
560 			end_timer--;
561 			if(end_timer == 0)
562 				return(1);
563 		}
564 	}
565 	return(0);
566 #else
567 	return(result);
568 #endif
569 
570 }  //  end of WaveCallBack
571 
572 
573 #if USE_PORTAUDIO == 19
574 /* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19
575    is broken */
576 
Pa_OpenDefaultStream2(PaStream ** stream,int inputChannelCount,int outputChannelCount,PaSampleFormat sampleFormat,double sampleRate,unsigned long framesPerBuffer,PaStreamCallback * streamCallback,void * userData)577 static PaError Pa_OpenDefaultStream2( PaStream** stream,
578                               int inputChannelCount,
579                               int outputChannelCount,
580                               PaSampleFormat sampleFormat,
581                               double sampleRate,
582                               unsigned long framesPerBuffer,
583                               PaStreamCallback *streamCallback,
584                               void *userData )
585 {
586 	PaError result;
587 	PaStreamParameters hostApiOutputParameters;
588 
589 	if(option_device_number >= 0)
590 		hostApiOutputParameters.device = option_device_number;
591 	else
592 		hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
593 
594 	if( hostApiOutputParameters.device == paNoDevice )
595 		return paDeviceUnavailable;
596 
597 	hostApiOutputParameters.channelCount = outputChannelCount;
598 	hostApiOutputParameters.sampleFormat = sampleFormat;
599 	/* defaultHighOutputLatency is used below instead of
600 	   defaultLowOutputLatency because it is more important for the default
601 	   stream to work reliably than it is for it to work with the lowest
602 	   latency.
603 	*/
604 	hostApiOutputParameters.suggestedLatency =
605 	      Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
606 	hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
607 
608 	result = Pa_OpenStream(
609 		stream, NULL, &hostApiOutputParameters, sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
610 
611 	return(result);
612 }
613 #endif
614 
615 
WavegenOpenSound()616 int WavegenOpenSound()
617 {//===================
618 	PaError err, err2;
619 	PaError active;
620 
621 	if(option_waveout || option_quiet)
622 	{
623 		// writing to WAV file, not to portaudio
624 		return(0);
625 	}
626 
627 #if USE_PORTAUDIO == 18
628 	active = Pa_StreamActive(pa_stream);
629 #else
630 	active = Pa_IsStreamActive(pa_stream);
631 #endif
632 
633 	if(active == 1)
634 		return(0);
635 	if(active < 0)
636 	{
637 		out_channels = 1;
638 
639 #if USE_PORTAUDIO == 18
640 		err2 = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata);
641 
642 		if(err2 == paInvalidChannelCount)
643 		{
644 			// failed to open with mono, try stereo
645 			out_channels=2;
646 			err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata);
647 		}
648 #else
649 		err2 = Pa_OpenDefaultStream2(&pa_stream,0,1,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata);
650 
651 		if(err2 == paInvalidChannelCount)
652 		{
653 			// failed to open with mono, try stereo
654 			out_channels=2;
655 			err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata);
656 		}
657 #endif
658 	}
659 	err = Pa_StartStream(pa_stream);
660 
661 #if USE_PORTAUDIO == 19
662 	if(err == paStreamIsNotStopped)
663 	{
664 		// not sure why we need this, but PA v19 seems to need it
665 		err = Pa_StopStream(pa_stream);
666 		err = Pa_StartStream(pa_stream);
667 	}
668 #endif
669 
670 	if(err != paNoError)
671 	{
672 		// exit speak if we can't open the sound device - this is OK if speak is being run for each utterance
673 		exit(2);
674 	}
675 
676 	return(0);
677 }
678 
679 
680 
WavegenCloseSound()681 int WavegenCloseSound()
682 {//====================
683 	PaError active;
684 
685 	// check whether speaking has finished, and close the stream
686 	if(pa_stream != NULL)
687 	{
688 #if USE_PORTAUDIO == 18
689 		active = Pa_StreamActive(pa_stream);
690 #else
691 		active = Pa_IsStreamActive(pa_stream);
692 #endif
693 		if(WcmdqUsed() == 0)   // also check that the queue is empty
694 		{
695 			if(active == 0)
696 			{
697 				Pa_CloseStream(pa_stream);
698 				pa_stream = NULL;
699 				return(1);
700 			}
701 		}
702 		else
703 		{
704 			WavegenOpenSound();  // still items in the queue, shouldn't be closed
705 		}
706 	}
707 	return(0);
708 }
709 
710 
WavegenInitSound()711 int WavegenInitSound()
712 {//===================
713 	PaError err;
714 
715 	if(option_quiet)
716 		return(0);
717 
718 	// PortAudio sound output library
719 	err = Pa_Initialize();
720 	pa_init_err = err;
721 	if(err != paNoError)
722 	{
723 		fprintf(stderr,"Failed to initialise the PortAudio sound\n");
724 		return(1);
725 	}
726 	return(0);
727 }
728 #else
WavegenOpenSound()729 int WavegenOpenSound()
730 {//===================
731 	return(0);
732 }
WavegenCloseSound()733 int WavegenCloseSound()
734 {//====================
735 	return(0);
736 }
WavegenInitSound()737 int WavegenInitSound()
738 {//===================
739 	return(0);
740 }
741 #endif
742 
743 
WavegenInit(int rate,int wavemult_fact)744 void WavegenInit(int rate, int wavemult_fact)
745 {//==========================================
746 	int  ix;
747 	double x;
748 
749 	if(wavemult_fact == 0)
750 		wavemult_fact=60;  // default
751 
752 	wvoice = NULL;
753 	samplerate = samplerate_native = rate;
754 	PHASE_INC_FACTOR = 0x8000000 / samplerate;   // assumes pitch is Hz*32
755 	Flutter_inc = (64 * samplerate)/rate;
756 	samplecount = 0;
757 	nsamples = 0;
758 	wavephase = 0x7fffffff;
759 	max_hval = 0;
760 
761 	wdata.amplitude = 32;
762 	wdata.amplitude_fmt = 100;
763 
764 	for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
765 		embedded_value[ix] = embedded_default[ix];
766 
767 
768 	// set up window to generate a spread of harmonics from a
769 	// single peak for HF peaks
770 	wavemult_max = (samplerate * wavemult_fact)/(256 * 50);
771 	if(wavemult_max > N_WAVEMULT) wavemult_max = N_WAVEMULT;
772 
773 	wavemult_offset = wavemult_max/2;
774 
775 	if(samplerate != 22050)
776 	{
777 		// wavemult table has preset values for 22050 Hz, we only need to
778 		// recalculate them if we have a different sample rate
779 		for(ix=0; ix<wavemult_max; ix++)
780 		{
781 			x = 127*(1.0 - cos(PI2*ix/wavemult_max));
782 			wavemult[ix] = (int)x;
783 		}
784 	}
785 
786 	WavegenInitPkData(1);
787 	WavegenInitPkData(0);
788 	pk_shape = pk_shape2;         // pk_shape2
789 
790 #ifdef INCLUDE_KLATT
791 	KlattInit();
792 #endif
793 
794 #ifdef LOG_FRAMES
795 remove("log-espeakedit");
796 remove("log-klatt");
797 #endif
798 }  // end of WavegenInit
799 
800 
GetAmplitude(void)801 int GetAmplitude(void)
802 {//===================
803 	int amp;
804 
805 	// normal, none, reduced, moderate, strong
806 	static const unsigned char amp_emphasis[5] = {16, 16, 10, 16, 22};
807 
808 	amp = (embedded_value[EMBED_A])*55/100;
809 	general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16;
810 	return(general_amplitude);
811 }
812 
813 
WavegenSetEcho(void)814 static void WavegenSetEcho(void)
815 {//=============================
816 	int delay;
817 	int amp;
818 
819 	voicing = wvoice->voicing;
820 	delay = wvoice->echo_delay;
821 	amp = wvoice->echo_amp;
822 
823 	if(delay >= N_ECHO_BUF)
824 		delay = N_ECHO_BUF-1;
825 	if(amp > 100)
826 		amp = 100;
827 
828 	memset(echo_buf,0,sizeof(echo_buf));
829 	echo_tail = 0;
830 
831 	if(embedded_value[EMBED_H] > 0)
832 	{
833 		// set echo from an embedded command in the text
834 		amp = embedded_value[EMBED_H];
835 		delay = 130;
836 	}
837 
838 	if(delay == 0)
839 		amp = 0;
840 
841 	echo_head = (delay * samplerate)/1000;
842 	echo_length = echo_head;       // ensure completion of echo at the end of speech. Use 1 delay period?
843 	if(amp == 0)
844 		echo_length = 0;
845 	if(amp > 20)
846 		echo_length = echo_head * 2;    // perhaps allow 2 echo periods if the echo is loud.
847 
848 	// echo_amp units are 1/256ths of the amplitude of the original sound.
849 	echo_amp = amp;
850 	// compensate (partially) for increase in amplitude due to echo
851 	general_amplitude = GetAmplitude();
852 	general_amplitude = ((general_amplitude * (500-amp))/500);
853 }  // end of WavegenSetEcho
854 
855 
856 
PeaksToHarmspect(wavegen_peaks_t * peaks,int pitch,int * htab,int control)857 int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control)
858 {//============================================================================
859 // Calculate the amplitude of each  harmonics from the formants
860 // Only for formants 0 to 5
861 
862 // control 0=initial call, 1=every 64 cycles
863 
864    // pitch and freqs are Hz<<16
865 
866 	int f;
867 	wavegen_peaks_t *p;
868 	int fp;   // centre freq of peak
869 	int fhi;  // high freq of peak
870 	int h;    // harmonic number
871 	int pk;
872 	int hmax;
873 	int hmax_samplerate;      // highest harmonic allowed for the samplerate
874 	int x;
875 	int ix;
876 	int h1;
877 
878 #ifdef SPECT_EDITOR
879 	if(harm_sqrt_n > 0)
880 		return(HarmToHarmspect(pitch,htab));
881 #endif
882 
883 	// initialise as much of *out as we will need
884 	if(wvoice == NULL)
885 		return(1);
886 	hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch;
887 	if(hmax >= MAX_HARMONIC)
888 		hmax = MAX_HARMONIC-1;
889 
890 	// restrict highest harmonic to half the samplerate
891 	hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch;   // only 95% of Nyquist freq
892 //	hmax_samplerate = (samplerate << 16)/(pitch*2);
893 
894 	if(hmax > hmax_samplerate)
895 		hmax = hmax_samplerate;
896 
897 	for(h=0;h<=hmax;h++)
898 		htab[h]=0;
899 
900 	h=0;
901 	for(pk=0; pk<=wvoice->n_harmonic_peaks; pk++)
902 	{
903 		p = &peaks[pk];
904 		if((p->height == 0) || (fp = p->freq)==0)
905 			continue;
906 
907 		fhi = p->freq + p->right;
908 		h = ((p->freq - p->left) / pitch) + 1;
909 		if(h <= 0) h = 1;
910 
911 		for(f=pitch*h; f < fp; f+=pitch)
912 		{
913 			htab[h++] += pk_shape[(fp-f)/(p->left>>8)] * p->height;
914 		}
915 		for(; f < fhi; f+=pitch)
916 		{
917 			htab[h++] += pk_shape[(f-fp)/(p->right>>8)] * p->height;
918 		}
919 	}
920 
921 {
922 int y;
923 int h2;
924 	// increase bass
925 	y = peaks[1].height * 10;   // addition as a multiple of 1/256s
926 	h2 = (1000<<16)/pitch;       // decrease until 1000Hz
927 	if(h2 > 0)
928 	{
929 		x = y/h2;
930 		h = 1;
931 		while(y > 0)
932 		{
933 			htab[h++] += y;
934 			y -= x;
935 		}
936 	}
937 }
938 
939 	// find the nearest harmonic for HF peaks where we don't use shape
940 	for(; pk<N_PEAKS; pk++)
941 	{
942 		x = peaks[pk].height >> 14;
943 		peak_height[pk] = (x * x * 5)/2;
944 
945 		// find the nearest harmonic for HF peaks where we don't use shape
946 		if(control == 0)
947 		{
948 			// set this initially, but make changes only at the quiet point
949 			peak_harmonic[pk] = peaks[pk].freq / pitch;
950 		}
951 		// only use harmonics up to half the samplerate
952 		if(peak_harmonic[pk] >= hmax_samplerate)
953 			peak_height[pk] = 0;
954 	}
955 
956 	// convert from the square-rooted values
957 	f = 0;
958 	for(h=0; h<=hmax; h++, f+=pitch)
959 	{
960 		x = htab[h] >> 15;
961 		htab[h] = (x * x) >> 8;
962 
963 		if((ix = (f >> 19)) < N_TONE_ADJUST)
964 		{
965 			htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13;  // index tone_adjust with Hz/8
966 		}
967 	}
968 
969 	// adjust the amplitude of the first harmonic, affects tonal quality
970 	h1 = htab[1] * option_harmonic1;
971 	htab[1] = h1/8;
972 
973 
974 	// calc intermediate increments of LF harmonics
975 	if(control & 1)
976 	{
977 		for(h=1; h<N_LOWHARM; h++)
978 		{
979 			harm_inc[h] = (htab[h] - harmspect[h]) >> 3;
980 		}
981 	}
982 
983 	return(hmax);  // highest harmonic number
984 }  // end of PeaksToHarmspect
985 
986 
987 
AdvanceParameters()988 static void AdvanceParameters()
989 {//============================
990 // Called every 64 samples to increment the formant freq, height, and widths
991 
992 	int x;
993 	int ix;
994 	static int Flutter_ix = 0;
995 
996 	// advance the pitch
997 	wdata.pitch_ix += wdata.pitch_inc;
998 	if((ix = wdata.pitch_ix>>8) > 127) ix = 127;
999 	x = wdata.pitch_env[ix] * wdata.pitch_range;
1000 	wdata.pitch = (x>>8) + wdata.pitch_base;
1001 
1002 	amp_ix += amp_inc;
1003 
1004 	/* add pitch flutter */
1005 	if(Flutter_ix >= (N_FLUTTER*64))
1006 		Flutter_ix = 0;
1007 	x = ((int)(Flutter_tab[Flutter_ix >> 6])-0x80) * flutter_amp;
1008 	Flutter_ix += Flutter_inc;
1009 	wdata.pitch += x;
1010 	if(wdata.pitch < 102400)
1011 		wdata.pitch = 102400;   // min pitch, 25 Hz  (25 << 12)
1012 
1013 	if(samplecount == samplecount_start)
1014 		return;
1015 
1016 	for(ix=0; ix <= wvoice->n_harmonic_peaks; ix++)
1017 	{
1018 		peaks[ix].freq1 += peaks[ix].freq_inc;
1019 		peaks[ix].freq = (int)peaks[ix].freq1;
1020 		peaks[ix].height1 += peaks[ix].height_inc;
1021 		if((peaks[ix].height = (int)peaks[ix].height1) < 0)
1022 			peaks[ix].height = 0;
1023 		peaks[ix].left1 += peaks[ix].left_inc;
1024 		peaks[ix].left = (int)peaks[ix].left1;
1025 		if(ix < 3)
1026 		{
1027 			peaks[ix].right1 += peaks[ix].right_inc;
1028 			peaks[ix].right = (int)peaks[ix].right1;
1029 		}
1030 		else
1031 		{
1032 			peaks[ix].right = peaks[ix].left;
1033 		}
1034 	}
1035 	for(;ix < 8; ix++)
1036 	{
1037 		// formants 6,7,8 don't have a width parameter
1038 		if(ix < 7)
1039 		{
1040 			peaks[ix].freq1 += peaks[ix].freq_inc;
1041 			peaks[ix].freq = (int)peaks[ix].freq1;
1042 		}
1043 		peaks[ix].height1 += peaks[ix].height_inc;
1044 		if((peaks[ix].height = (int)peaks[ix].height1) < 0)
1045 			peaks[ix].height = 0;
1046 	}
1047 
1048 #ifdef SPECT_EDITOR
1049 	if(harm_sqrt_n != 0)
1050 	{
1051 		// We are generating from a harmonic spectrum at a given pitch, not from formant peaks
1052 		for(ix=0; ix<harm_sqrt_n; ix++)
1053 			harm_sqrt[ix] += harm_sqrt_inc[ix];
1054 	}
1055 #endif
1056 }  //  end of AdvanceParameters
1057 
1058 
1059 #ifndef PLATFORM_RISCOS
resonator(RESONATOR * r,double input)1060 static double resonator(RESONATOR *r, double input)
1061 {//================================================
1062 	double x;
1063 
1064 	x = r->a * input + r->b * r->x1 + r->c * r->x2;
1065 	r->x2 = r->x1;
1066 	r->x1 = x;
1067 
1068  return x;
1069 }
1070 
1071 
1072 
setresonator(RESONATOR * rp,int freq,int bwidth,int init)1073 static void setresonator(RESONATOR *rp, int freq, int bwidth, int init)
1074 {//====================================================================
1075 // freq    Frequency of resonator in Hz
1076 // bwidth  Bandwidth of resonator in Hz
1077 // init    Initialize internal data
1078 
1079 	double x;
1080 	double arg;
1081 
1082 	if(init)
1083 	{
1084 		rp->x1 = 0;
1085 		rp->x2 = 0;
1086 	}
1087 
1088    // x  =  exp(-pi * bwidth * t)
1089 	arg = minus_pi_t * bwidth;
1090 	x = exp(arg);
1091 
1092 	// c  =  -(x*x)
1093 	rp->c = -(x * x);
1094 
1095 	// b = x * 2*cos(2 pi * freq * t)
1096 
1097 	arg = two_pi_t * freq;
1098 	rp->b = x * cos(arg) * 2.0;
1099 
1100 	// a = 1.0 - b - c
1101 	rp->a = 1.0 - rp->b - rp->c;
1102 }  // end if setresonator
1103 #endif
1104 
1105 
InitBreath(void)1106 void InitBreath(void)
1107 {//==================
1108 #ifndef PLATFORM_RISCOS
1109 	int ix;
1110 
1111 	minus_pi_t = -PI / samplerate;
1112 	two_pi_t = -2.0 * minus_pi_t;
1113 
1114 	for(ix=0; ix<N_PEAKS; ix++)
1115 	{
1116 		setresonator(&rbreath[ix],2000,200,1);
1117 	}
1118 #endif
1119 }  // end of InitBreath
1120 
1121 
1122 
SetBreath()1123 static void SetBreath()
1124 {//====================
1125 #ifndef PLATFORM_RISCOS
1126 	int pk;
1127 
1128 	if(wvoice->breath[0] == 0)
1129 		return;
1130 
1131 	for(pk=1; pk<N_PEAKS; pk++)
1132 	{
1133 		if(wvoice->breath[pk] != 0)
1134 		{
1135 			// breath[0] indicates that some breath formants are needed
1136 			// set the freq from the current ynthesis formant and the width from the voice data
1137 			setresonator(&rbreath[pk], peaks[pk].freq >> 16, wvoice->breathw[pk],0);
1138 		}
1139 	}
1140 #endif
1141 }  // end of SetBreath
1142 
1143 
ApplyBreath(void)1144 static int ApplyBreath(void)
1145 {//=========================
1146 	int value = 0;
1147 #ifndef PLATFORM_RISCOS
1148 	int noise;
1149 	int ix;
1150 	int amp;
1151 
1152 	// use two random numbers, for alternate formants
1153 	noise = (rand() & 0x3fff) - 0x2000;
1154 
1155 	for(ix=1; ix < N_PEAKS; ix++)
1156 	{
1157 		if((amp = wvoice->breath[ix]) != 0)
1158 		{
1159 			amp *= (peaks[ix].height >> 14);
1160 			value += (int)resonator(&rbreath[ix],noise) * amp;
1161 		}
1162 	}
1163 #endif
1164 	return (value);
1165 }
1166 
1167 
1168 
Wavegen()1169 int Wavegen()
1170 {//==========
1171 	unsigned short waveph;
1172 	unsigned short theta;
1173 	int total;
1174 	int h;
1175 	int ix;
1176 	int z, z1, z2;
1177 	int echo;
1178 	int ov;
1179 	static int maxh, maxh2;
1180 	int pk;
1181 	signed char c;
1182 	int sample;
1183 	int amp;
1184 	int modn_amp, modn_period;
1185 	static int agc = 256;
1186 	static int h_switch_sign = 0;
1187 	static int cycle_count = 0;
1188 	static int amplitude2 = 0;   // adjusted for pitch
1189 
1190 	// continue until the output buffer is full, or
1191 	// the required number of samples have been produced
1192 
1193 	for(;;)
1194 	{
1195 		if((end_wave==0) && (samplecount==nsamples))
1196 			return(0);
1197 
1198 		if((samplecount & 0x3f) == 0)
1199 		{
1200 			// every 64 samples, adjust the parameters
1201 			if(samplecount == 0)
1202 			{
1203 				hswitch = 0;
1204 				harmspect = hspect[0];
1205 				maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[0], 0);
1206 
1207 				// adjust amplitude to compensate for fewer harmonics at higher pitch
1208 //				amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
1209 				amplitude2 = (wdata.amplitude * (wdata.pitch >> 8) * wdata.amplitude_fmt)/(10000 << 3);
1210 
1211             // switch sign of harmonics above about 900Hz, to reduce max peak amplitude
1212 				h_switch_sign = 890 / (wdata.pitch >> 12);
1213 			}
1214 			else
1215 				AdvanceParameters();
1216 
1217 			// pitch is Hz<<12
1218 			phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR;
1219 			cycle_samples = samplerate/(wdata.pitch >> 12);  // sr/(pitch*2)
1220 			hf_factor = wdata.pitch >> 11;
1221 
1222 			maxh = maxh2;
1223 			harmspect = hspect[hswitch];
1224 			hswitch ^= 1;
1225 			maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[hswitch], 1);
1226 
1227 			SetBreath();
1228 		}
1229 		else
1230 		if((samplecount & 0x07) == 0)
1231 		{
1232 			for(h=1; h<N_LOWHARM && h<=maxh2 && h<=maxh; h++)
1233 			{
1234 				harmspect[h] += harm_inc[h];
1235 			}
1236 
1237 			// bring automctic gain control back towards unity
1238 			if(agc < 256) agc++;
1239 		}
1240 
1241 		samplecount++;
1242 
1243 		if(wavephase > 0)
1244 		{
1245 			wavephase += phaseinc;
1246 			if(wavephase < 0)
1247 			{
1248 				// sign has changed, reached a quiet point in the waveform
1249 				cbytes = wavemult_offset - (cycle_samples)/2;
1250 				if(samplecount > nsamples)
1251 					return(0);
1252 
1253 				cycle_count++;
1254 
1255 				for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++)
1256 				{
1257 					// find the nearest harmonic for HF peaks where we don't use shape
1258 					peak_harmonic[pk] = ((peaks[pk].freq / (wdata.pitch*8)) + 1) / 2;
1259 				}
1260 
1261 				// adjust amplitude to compensate for fewer harmonics at higher pitch
1262 //				amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
1263 				amplitude2 = (wdata.amplitude * (wdata.pitch >> 8) * wdata.amplitude_fmt)/(10000 << 3);
1264 
1265 				if(glottal_flag > 0)
1266 				{
1267 					if(glottal_flag == 3)
1268 					{
1269 						if((nsamples-samplecount) < (cycle_samples*2))
1270 						{
1271 							// Vowel before glottal-stop.
1272 							// This is the start of the penultimate cycle, reduce its amplitude
1273 							glottal_flag = 2;
1274 							amplitude2 = (amplitude2 *  glottal_reduce)/256;
1275 						}
1276 					}
1277 					else
1278 					if(glottal_flag == 4)
1279 					{
1280 						// Vowel following a glottal-stop.
1281 						// This is the start of the second cycle, reduce its amplitude
1282 						glottal_flag = 2;
1283 						amplitude2 = (amplitude2 * glottal_reduce)/256;
1284 					}
1285 					else
1286 					{
1287 						glottal_flag--;
1288 					}
1289 				}
1290 
1291 				if(amplitude_env != NULL)
1292 				{
1293 					// amplitude envelope is only used for creaky voice effect on certain vowels/tones
1294 					if((ix = amp_ix>>8) > 127) ix = 127;
1295 					amp = amplitude_env[ix];
1296 					amplitude2 = (amplitude2 * amp)/128;
1297 //					if(amp < 255)
1298 //						modulation_type = 7;
1299 				}
1300 
1301 				// introduce roughness into the sound by reducing the amplitude of
1302 				modn_period = 0;
1303 				if(voice->roughness < N_ROUGHNESS)
1304 				{
1305 					modn_period = modulation_tab[voice->roughness][modulation_type];
1306 					modn_amp = modn_period & 0xf;
1307 					modn_period = modn_period >> 4;
1308 				}
1309 
1310 				if(modn_period != 0)
1311 				{
1312 					if(modn_period==0xf)
1313 					{
1314 						// just once */
1315 						amplitude2 = (amplitude2 * modn_amp)/16;
1316 						modulation_type = 0;
1317 					}
1318 					else
1319 					{
1320 						// reduce amplitude every [modn_period} cycles
1321 						if((cycle_count % modn_period)==0)
1322 							amplitude2 = (amplitude2 * modn_amp)/16;
1323 					}
1324 				}
1325 			}
1326 		}
1327 		else
1328 		{
1329 			wavephase += phaseinc;
1330 		}
1331 		waveph = (unsigned short)(wavephase >> 16);
1332 		total = 0;
1333 
1334 		// apply HF peaks, formants 6,7,8
1335 		// add a single harmonic and then spread this my multiplying by a
1336 		// window.  This is to reduce the processing power needed to add the
1337 		// higher frequence harmonics.
1338 		cbytes++;
1339 		if(cbytes >=0 && cbytes<wavemult_max)
1340 		{
1341 			for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++)
1342 			{
1343 				theta = peak_harmonic[pk] * waveph;
1344 				total += (long)sin_tab[theta >> 5] * peak_height[pk];
1345 			}
1346 
1347 			// spread the peaks by multiplying by a window
1348 			total = (long)(total / hf_factor) * wavemult[cbytes];
1349 		}
1350 
1351 		// apply main peaks, formants 0 to 5
1352 #ifdef USE_ASSEMBLER_1
1353 		// use an optimised routine for this loop, if available
1354 		total += AddSineWaves(waveph, h_switch_sign, maxh, harmspect);  // call an assembler code routine
1355 #else
1356 		theta = waveph;
1357 
1358 		for(h=1; h<=h_switch_sign; h++)
1359 		{
1360 			total += ((int)sin_tab[theta >> 5] * harmspect[h]);
1361 			theta += waveph;
1362 		}
1363 		while(h<=maxh)
1364 		{
1365 			total -= ((int)sin_tab[theta >> 5] * harmspect[h]);
1366 			theta += waveph;
1367 			h++;
1368 		}
1369 #endif
1370 
1371 		if(voicing != 64)
1372 		{
1373 			total = (total >> 6) * voicing;
1374 		}
1375 
1376 #ifndef PLATFORM_RISCOS
1377 		if(wvoice->breath[0])
1378 		{
1379 			total +=  ApplyBreath();
1380 		}
1381 #endif
1382 
1383 		// mix with sampled wave if required
1384 		z2 = 0;
1385 		if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile)
1386 		{
1387 			if(wdata.mix_wave_scale == 0)
1388 			{
1389 				// a 16 bit sample
1390 				c = wdata.mix_wavefile[wdata.mix_wavefile_ix+wdata.mix_wavefile_offset+1];
1391 				sample = wdata.mix_wavefile[wdata.mix_wavefile_ix+wdata.mix_wavefile_offset] + (c * 256);
1392 				wdata.mix_wavefile_ix += 2;
1393 			}
1394 			else
1395 			{
1396 				// a 8 bit sample, scaled
1397 				sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_offset+wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
1398 			}
1399 			z2 = (sample * wdata.amplitude_v) >> 10;
1400 			z2 = (z2 * wdata.mix_wave_amp)/32;
1401 
1402 			if((wdata.mix_wavefile_ix + wdata.mix_wavefile_offset) >= wdata.mix_wavefile_max)  // reached the end of available WAV data
1403 				wdata.mix_wavefile_offset -= (wdata.mix_wavefile_max*3)/4;
1404 		}
1405 
1406 		z1 = z2 + (((total>>8) * amplitude2) >> 13);
1407 
1408 		echo = (echo_buf[echo_tail++] * echo_amp);
1409 		z1 += echo >> 8;
1410 		if(echo_tail >= N_ECHO_BUF)
1411 			echo_tail=0;
1412 
1413 		z = (z1 * agc) >> 8;
1414 
1415 		// check for overflow, 16bit signed samples
1416 		if(z >= 32768)
1417 		{
1418 			ov = 8388608/z1 - 1;      // 8388608 is 2^23, i.e. max value * 256
1419 			if(ov < agc) agc = ov;    // set agc to number of 1/256ths to multiply the sample by
1420 			z = (z1 * agc) >> 8;      // reduce sample by agc value to prevent overflow
1421 		}
1422 		else
1423 		if(z <= -32768)
1424 		{
1425 			ov = -8388608/z1 - 1;
1426 			if(ov < agc) agc = ov;
1427 			z = (z1 * agc) >> 8;
1428 		}
1429 		*out_ptr++ = z;
1430 		*out_ptr++ = z >> 8;
1431 
1432 		echo_buf[echo_head++] = z;
1433 		if(echo_head >= N_ECHO_BUF)
1434 			echo_head = 0;
1435 
1436 		if(out_ptr >= out_end)
1437 			return(1);
1438 	}
1439 	return(0);
1440 }  //  end of Wavegen
1441 
1442 
PlaySilence(int length,int resume)1443 static int PlaySilence(int length, int resume)
1444 {//===========================================
1445 	static int n_samples;
1446 	int value=0;
1447 
1448 	nsamples = 0;
1449 	samplecount = 0;
1450 	wavephase = 0x7fffffff;
1451 
1452 	if(length == 0)
1453 		return(0);
1454 
1455 	if(resume==0)
1456 		n_samples = length;
1457 
1458 	while(n_samples-- > 0)
1459 	{
1460 		value = (echo_buf[echo_tail++] * echo_amp) >> 8;
1461 
1462 		if(echo_tail >= N_ECHO_BUF)
1463 			echo_tail = 0;
1464 
1465 		*out_ptr++ = value;
1466 		*out_ptr++ = value >> 8;
1467 
1468 		echo_buf[echo_head++] = value;
1469 		if(echo_head >= N_ECHO_BUF)
1470 			echo_head = 0;
1471 
1472 		if(out_ptr >= out_end)
1473 			return(1);
1474 	}
1475 	return(0);
1476 }  // end of PlaySilence
1477 
1478 
1479 
PlayWave(int length,int resume,unsigned char * data,int scale,int amp)1480 static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp)
1481 {//=================================================================================
1482 	static int n_samples;
1483 	static int ix=0;
1484 	int value;
1485 	signed char c;
1486 
1487 	if(resume==0)
1488 	{
1489 		n_samples = length;
1490 		ix = 0;
1491 	}
1492 
1493 	nsamples = 0;
1494 	samplecount = 0;
1495 
1496 	while(n_samples-- > 0)
1497 	{
1498 		if(scale == 0)
1499 		{
1500 			// 16 bits data
1501 			c = data[ix+1];
1502 			value = data[ix] + (c * 256);
1503 			ix+=2;
1504 		}
1505 		else
1506 		{
1507 			// 8 bit data, shift by the specified scale factor
1508 			value = (signed char)data[ix++] * scale;
1509 		}
1510 		value *= (consonant_amp * general_amplitude);   // reduce strength of consonant
1511 		value = value >> 10;
1512 		value = (value * amp)/32;
1513 
1514 		value += ((echo_buf[echo_tail++] * echo_amp) >> 8);
1515 
1516 		if(value > 32767)
1517 			value = 32768;
1518 		else
1519 		if(value < -32768)
1520 			value = -32768;
1521 
1522 		if(echo_tail >= N_ECHO_BUF)
1523 			echo_tail = 0;
1524 
1525 		out_ptr[0] = value;
1526 		out_ptr[1] = value >> 8;
1527 		out_ptr+=2;
1528 
1529 		echo_buf[echo_head++] = (value*3)/4;
1530 		if(echo_head >= N_ECHO_BUF)
1531 			echo_head = 0;
1532 
1533 		if(out_ptr >= out_end)
1534 			return(1);
1535 	}
1536 	return(0);
1537 }
1538 
1539 
SetWithRange0(int value,int max)1540 static int SetWithRange0(int value, int max)
1541 {//=========================================
1542 	if(value < 0)
1543 		return(0);
1544 	if(value > max)
1545 		return(max);
1546 	return(value);
1547 }
1548 
1549 
SetPitchFormants()1550 static void SetPitchFormants()
1551 {//===========================
1552 	int ix;
1553 	int factor = 256;
1554 	int pitch_value;
1555 
1556 	// adjust formants to give better results for a different voice pitch
1557 	if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE)
1558 		pitch_value = MAX_PITCH_VALUE;
1559 
1560 	if(pitch_value > 50)
1561 	{
1562 		// only adjust if the pitch is higher than normal
1563 		factor = 256 + (25 * (pitch_value - 50))/50;
1564 	}
1565 
1566 	for(ix=0; ix<=5; ix++)
1567 	{
1568 		wvoice->freq[ix] = (wvoice->freq2[ix] * factor)/256;
1569 	}
1570 
1571 	factor = embedded_value[EMBED_T]*3;
1572 	wvoice->height[0] = (wvoice->height2[0] * (256 - factor*2))/256;
1573 	wvoice->height[1] = (wvoice->height2[1] * (256 - factor))/256;
1574 }
1575 
1576 
SetEmbedded(int control,int value)1577 void SetEmbedded(int control, int value)
1578 {//=====================================
1579 	// there was an embedded command in the text at this point
1580 	int sign=0;
1581 	int command;
1582 
1583 	command = control & 0x1f;
1584 	if((control & 0x60) == 0x60)
1585 		sign = -1;
1586 	else
1587 	if((control & 0x60) == 0x40)
1588 		sign = 1;
1589 
1590 	if(command < N_EMBEDDED_VALUES)
1591 	{
1592 		if(sign == 0)
1593 			embedded_value[command] = value;
1594 		else
1595 			embedded_value[command] += (value * sign);
1596 		embedded_value[command] = SetWithRange0(embedded_value[command],embedded_max[command]);
1597 	}
1598 
1599 	switch(command)
1600 	{
1601 	case EMBED_T:
1602 		WavegenSetEcho();   // and drop through to case P
1603 	case EMBED_P:
1604 		SetPitchFormants();
1605 		break;
1606 
1607 	case EMBED_A:  // amplitude
1608 		general_amplitude = GetAmplitude();
1609 		break;
1610 
1611 	case EMBED_F:   // emphasis
1612 		general_amplitude = GetAmplitude();
1613 		break;
1614 
1615 	case EMBED_H:
1616 		WavegenSetEcho();
1617 		break;
1618 	}
1619 }
1620 
1621 
WavegenSetVoice(voice_t * v)1622 void WavegenSetVoice(voice_t *v)
1623 {//=============================
1624 	static voice_t v2;
1625 
1626 	memcpy(&v2,v,sizeof(v2));
1627 	wvoice = &v2;
1628 
1629 	if(v->peak_shape==0)
1630 		pk_shape = pk_shape1;
1631 	else
1632 		pk_shape = pk_shape2;
1633 
1634 	consonant_amp = (v->consonant_amp * 26) /100;
1635 	if(samplerate <= 11000)
1636 	{
1637 		consonant_amp = consonant_amp*2;  // emphasize consonants at low sample rates
1638 		option_harmonic1 = 6;
1639 	}
1640 	WavegenSetEcho();
1641 	SetPitchFormants();
1642 	MarkerEvent(espeakEVENT_SAMPLERATE, 0, wvoice->samplerate, 0, out_ptr);
1643 //	WVoiceChanged(wvoice);
1644 }
1645 
1646 
SetAmplitude(int length,unsigned char * amp_env,int value)1647 static void SetAmplitude(int length, unsigned char *amp_env, int value)
1648 {//====================================================================
1649 	amp_ix = 0;
1650 	if(length==0)
1651 		amp_inc = 0;
1652 	else
1653 		amp_inc = (256 * ENV_LEN * STEPSIZE)/length;
1654 
1655 	wdata.amplitude = (value * general_amplitude)/16;
1656 	wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100;           // for wave mixed with voiced sounds
1657 
1658 	amplitude_env = amp_env;
1659 }
1660 
1661 
SetPitch2(voice_t * voice,int pitch1,int pitch2,int * pitch_base,int * pitch_range)1662 void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range)
1663 {//======================================================================================
1664 	int x;
1665 	int base;
1666 	int range;
1667 	int pitch_value;
1668 
1669 	if(pitch1 > pitch2)
1670 	{
1671 		x = pitch1;   // swap values
1672 		pitch1 = pitch2;
1673 		pitch2 = x;
1674 	}
1675 
1676 	if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE)
1677 		pitch_value = MAX_PITCH_VALUE;
1678 	pitch_value -= embedded_value[EMBED_T];   // adjust tone for announcing punctuation
1679 	if(pitch_value < 0)
1680 		pitch_value = 0;
1681 
1682 	base = (voice->pitch_base * pitch_adjust_tab[pitch_value])/128;
1683 	range =  (voice->pitch_range * embedded_value[EMBED_R])/50;
1684 
1685 	// compensate for change in pitch when the range is narrowed or widened
1686 	base -= (range - voice->pitch_range)*18;
1687 
1688 	*pitch_base = base + (pitch1 * range)/2;
1689 	*pitch_range = base + (pitch2 * range)/2 - *pitch_base;
1690 }
1691 
1692 
SetPitch(int length,unsigned char * env,int pitch1,int pitch2)1693 void SetPitch(int length, unsigned char *env, int pitch1, int pitch2)
1694 {//==================================================================
1695 // length in samples
1696 
1697 #ifdef LOG_FRAMES
1698 if(option_log_frames)
1699 {
1700 	f_log=fopen("log-espeakedit","a");
1701 	if(f_log != NULL)
1702 	{
1703 		fprintf(f_log,"	  pitch %3d %3d  %3dmS\n",pitch1,pitch2,(length*1000)/samplerate);
1704 		fclose(f_log);
1705 		f_log=NULL;
1706 	}
1707 }
1708 #endif
1709 	if((wdata.pitch_env = env)==NULL)
1710 		wdata.pitch_env = env_fall;  // default
1711 
1712 	wdata.pitch_ix = 0;
1713 	if(length==0)
1714 		wdata.pitch_inc = 0;
1715 	else
1716 		wdata.pitch_inc = (256 * ENV_LEN * STEPSIZE)/length;
1717 
1718 	SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range);
1719 	// set initial pitch
1720 	wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base;   // Hz << 12
1721 
1722 	flutter_amp = wvoice->flutter;
1723 
1724 }  // end of SetPitch
1725 
1726 
1727 
1728 
1729 
SetSynth(int length,int modn,frame_t * fr1,frame_t * fr2,voice_t * v)1730 void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v)
1731 {//========================================================================
1732 	int ix;
1733 	DOUBLEX next;
1734 	int length2;
1735 	int length4;
1736 	int qix;
1737 	int cmd;
1738 	static int glottal_reduce_tab1[4] = {0x30, 0x30, 0x40, 0x50};  // vowel before [?], amp * 1/256
1739 //	static int glottal_reduce_tab1[4] = {0x30, 0x40, 0x50, 0x60};  // vowel before [?], amp * 1/256
1740 	static int glottal_reduce_tab2[4] = {0x90, 0xa0, 0xb0, 0xc0};  // vowel after [?], amp * 1/256
1741 
1742 #ifdef LOG_FRAMES
1743 if(option_log_frames)
1744 {
1745 	f_log=fopen("log-espeakedit","a");
1746 	if(f_log != NULL)
1747 	{
1748 		fprintf(f_log,"%3dmS  %3d %3d %4d %4d (%3d %3d %3d %3d)  to  %3d %3d %4d %4d (%3d %3d %3d %3d)\n",length*1000/samplerate,
1749 			fr1->ffreq[0],fr1->ffreq[1],fr1->ffreq[2],fr1->ffreq[3], fr1->fheight[0],fr1->fheight[1],fr1->fheight[2],fr1->fheight[3],
1750 			fr2->ffreq[0],fr2->ffreq[1],fr2->ffreq[2],fr2->ffreq[3], fr2->fheight[0],fr2->fheight[1],fr2->fheight[2],fr2->fheight[3] );
1751 
1752 	fclose(f_log);
1753 	f_log=NULL;
1754 	}
1755 }
1756 #endif
1757 
1758 	harm_sqrt_n = 0;
1759 	end_wave = 1;
1760 
1761 	// any additional information in the param1 ?
1762 	modulation_type = modn & 0xff;
1763 
1764 	glottal_flag = 0;
1765 	if(modn & 0x400)
1766 	{
1767 		glottal_flag = 3;  // before a glottal stop
1768 		glottal_reduce = glottal_reduce_tab1[(modn >> 8) & 3];
1769 	}
1770 	if(modn & 0x800)
1771 	{
1772 		glottal_flag = 4;  // after a glottal stop
1773 		glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3];
1774 	}
1775 
1776 	for(qix=wcmdq_head+1;;qix++)
1777 	{
1778 		if(qix >= N_WCMDQ) qix = 0;
1779 		if(qix == wcmdq_tail) break;
1780 
1781 		cmd = wcmdq[qix][0];
1782 		if(cmd==WCMD_SPECT)
1783 		{
1784 			end_wave = 0;  // next wave generation is from another spectrum
1785 			break;
1786 		}
1787 		if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE))
1788 			break;   // next is not from spectrum, so continue until end of wave cycle
1789 	}
1790 
1791 	// round the length to a multiple of the stepsize
1792 	length2 = (length + STEPSIZE/2) & ~0x3f;
1793 	if(length2 == 0)
1794 		length2 = STEPSIZE;
1795 
1796 	// add this length to any left over from the previous synth
1797 	samplecount_start = samplecount;
1798 	nsamples += length2;
1799 
1800 	length4 = length2/4;
1801 
1802 	peaks[7].freq = (7800  * v->freq[7] + v->freqadd[7]*256) << 8;
1803 	peaks[8].freq = (9000  * v->freq[8] + v->freqadd[8]*256) << 8;
1804 
1805 	for(ix=0; ix < 8; ix++)
1806 	{
1807 		if(ix < 7)
1808 		{
1809 			peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8;
1810 			peaks[ix].freq = (int)peaks[ix].freq1;
1811 			next = (fr2->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8;
1812 			peaks[ix].freq_inc =  ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4;  // lower headroom for fixed point math
1813 		}
1814 
1815 		peaks[ix].height1 = (fr1->fheight[ix] * v->height[ix]) << 6;
1816 		peaks[ix].height = (int)peaks[ix].height1;
1817 		next = (fr2->fheight[ix] * v->height[ix]) << 6;
1818 		peaks[ix].height_inc =  ((next - peaks[ix].height1) * STEPSIZE) / length2;
1819 
1820 		if((ix <= 5) && (ix <= wvoice->n_harmonic_peaks))
1821 		{
1822 			peaks[ix].left1 = (fr1->fwidth[ix] * v->width[ix]) << 10;
1823 			peaks[ix].left = (int)peaks[ix].left1;
1824 			next = (fr2->fwidth[ix] * v->width[ix]) << 10;
1825 			peaks[ix].left_inc =  ((next - peaks[ix].left1) * STEPSIZE) / length2;
1826 
1827 			if(ix < 3)
1828 			{
1829 				peaks[ix].right1 = (fr1->fright[ix] * v->width[ix]) << 10;
1830 				peaks[ix].right = (int)peaks[ix].right1;
1831 				next = (fr2->fright[ix] * v->width[ix]) << 10;
1832 				peaks[ix].right_inc = ((next - peaks[ix].right1) * STEPSIZE) / length2;
1833 			}
1834 			else
1835 			{
1836 				peaks[ix].right = peaks[ix].left;
1837 			}
1838 		}
1839 	}
1840 }  // end of SetSynth
1841 
1842 
Wavegen2(int length,int modulation,int resume,frame_t * fr1,frame_t * fr2)1843 static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
1844 {//====================================================================================
1845 	if(resume==0)
1846 		SetSynth(length, modulation, fr1, fr2, wvoice);
1847 
1848 	return(Wavegen());
1849 }
1850 
Write4Bytes(FILE * f,int value)1851 void Write4Bytes(FILE *f, int value)
1852 {//=================================
1853 // Write 4 bytes to a file, least significant first
1854 	int ix;
1855 
1856 	for(ix=0; ix<4; ix++)
1857 	{
1858 		fputc(value & 0xff,f);
1859 		value = value >> 8;
1860 	}
1861 }
1862 
1863 
1864 
WavegenFill2(int fill_zeros)1865 int WavegenFill2(int fill_zeros)
1866 {//============================
1867 // Pick up next wavegen commands from the queue
1868 // return: 0  output buffer has been filled
1869 // return: 1  input command queue is now empty
1870 
1871 	long64 *q;
1872 	int length;
1873 	int result;
1874 	int marker_type;
1875 	static int resume=0;
1876 	static int echo_complete=0;
1877 
1878 	while(out_ptr < out_end)
1879 	{
1880 		if(WcmdqUsed() <= 0)
1881 		{
1882 			if(echo_complete > 0)
1883 			{
1884 				// continue to play silence until echo is completed
1885 				resume = PlaySilence(echo_complete,resume);
1886 				if(resume == 1)
1887 					return(0);  // not yet finished
1888 			}
1889 
1890 			if(fill_zeros)
1891 			{
1892 				while(out_ptr < out_end)
1893 					*out_ptr++ = 0;
1894 			}
1895 			return(1);              // queue empty, close sound channel
1896 		}
1897 
1898 		result = 0;
1899 		q = wcmdq[wcmdq_head];
1900 		length = q[1];
1901 
1902 		switch(q[0] & 0xff)
1903 		{
1904 		case WCMD_PITCH:
1905 			SetPitch(length,(unsigned char *)q[2],q[3] >> 16,q[3] & 0xffff);
1906 			break;
1907 
1908 		case WCMD_PAUSE:
1909 			if(resume==0)
1910 			{
1911 				echo_complete -= length;
1912 			}
1913 			wdata.n_mix_wavefile = 0;
1914 			wdata.amplitude_fmt = 100;
1915 #ifdef INCLUDE_KLATT
1916 			KlattReset(1);
1917 #endif
1918 			result = PlaySilence(length,resume);
1919 			break;
1920 
1921 		case WCMD_WAVE:
1922 			echo_complete = echo_length;
1923 			wdata.n_mix_wavefile = 0;
1924 #ifdef INCLUDE_KLATT
1925 			KlattReset(1);
1926 #endif
1927 			result = PlayWave(length,resume,(unsigned char*)q[2], q[3] & 0xff, q[3] >> 8);
1928 			break;
1929 
1930 		case WCMD_WAVE2:
1931 			// wave file to be played at the same time as synthesis
1932 			wdata.mix_wave_amp = q[3] >> 8;
1933 			wdata.mix_wave_scale = q[3] & 0xff;
1934 			wdata.n_mix_wavefile = (length & 0xffff);
1935 			wdata.mix_wavefile_max = (length >> 16) & 0xffff;
1936 			if(wdata.mix_wave_scale == 0)
1937 			{
1938 				wdata.n_mix_wavefile *= 2;
1939 				wdata.mix_wavefile_max *= 2;
1940 			}
1941 			wdata.mix_wavefile_ix = 0;
1942 			wdata.mix_wavefile_offset = 0;
1943 			wdata.mix_wavefile = (unsigned char *)q[2];
1944 			break;
1945 
1946 		case WCMD_SPECT2:   // as WCMD_SPECT but stop any concurrent wave file
1947 			wdata.n_mix_wavefile = 0;   // ... and drop through to WCMD_SPECT case
1948 		case WCMD_SPECT:
1949 			echo_complete = echo_length;
1950 			result = Wavegen2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
1951 			break;
1952 
1953 #ifdef INCLUDE_KLATT
1954 		case WCMD_KLATT2:   // as WCMD_SPECT but stop any concurrent wave file
1955 			wdata.n_mix_wavefile = 0;   // ... and drop through to WCMD_SPECT case
1956 		case WCMD_KLATT:
1957 			echo_complete = echo_length;
1958 			result = Wavegen_Klatt2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
1959 			break;
1960 #endif
1961 
1962 		case WCMD_MARKER:
1963 			marker_type = q[0] >> 8;
1964 			MarkerEvent(marker_type, q[1],q[2],q[3],out_ptr);
1965 #ifdef LOG_FRAMES
1966 			LogMarker(marker_type, q[2], q[3]);
1967 #endif
1968 			if(marker_type == 1)  // word marker
1969 			{
1970 				current_source_index = q[1] & 0xffffff;
1971 			}
1972 			break;
1973 
1974 		case WCMD_AMPLITUDE:
1975 			SetAmplitude(length,(unsigned char *)q[2],q[3]);
1976 			break;
1977 
1978 		case WCMD_VOICE:
1979 			WavegenSetVoice((voice_t *)q[2]);
1980 			free((voice_t *)q[2]);
1981 			break;
1982 
1983 		case WCMD_EMBEDDED:
1984 			SetEmbedded(q[1],q[2]);
1985 			break;
1986 
1987 		case WCMD_MBROLA_DATA:
1988 			result = MbrolaFill(length, resume, (general_amplitude * wvoice->voicing)/64);
1989 			break;
1990 
1991 		case WCMD_FMT_AMPLITUDE:
1992 			if((wdata.amplitude_fmt = q[1]) == 0)
1993 				wdata.amplitude_fmt = 100;  // percentage, but value=0 means 100%
1994 			break;
1995 
1996 #ifdef INCLUDE_SONIC
1997 		case WCMD_SONIC_SPEED:
1998 			sonicSpeed = (double)q[1] / 1024;
1999 			break;
2000 #endif
2001 		}
2002 
2003 		if(result==0)
2004 		{
2005 			WcmdqIncHead();
2006 			resume=0;
2007 		}
2008 		else
2009 		{
2010 			resume=1;
2011 		}
2012 	}
2013 
2014 	return(0);
2015 }  // end of WavegenFill2
2016 
2017 
2018 #ifdef INCLUDE_SONIC
2019 /* Speed up the audio samples with libsonic. */
SpeedUp(short * outbuf,int length_in,int length_out,int end_of_text)2020 static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text)
2021 {//==============================================================================
2022 	if(length_in >0)
2023 	{
2024 		if(sonicSpeedupStream == NULL)
2025 		{
2026 			sonicSpeedupStream = sonicCreateStream(22050, 1);
2027 		}
2028 		if(sonicGetSpeed(sonicSpeedupStream) != sonicSpeed)
2029 		{
2030 		        sonicSetSpeed(sonicSpeedupStream, sonicSpeed);
2031 		}
2032 
2033 		sonicWriteShortToStream(sonicSpeedupStream, outbuf, length_in);
2034 	}
2035 
2036 	if(sonicSpeedupStream == NULL)
2037 		return(0);
2038 
2039 	if(end_of_text)
2040 	{
2041 		sonicFlushStream(sonicSpeedupStream);
2042 	}
2043 	return sonicReadShortFromStream(sonicSpeedupStream, outbuf, length_out);
2044 }  // end of SpeedUp
2045 #endif
2046 
2047 
2048 /* Call WavegenFill2, and then speed up the output samples. */
WavegenFill(int fill_zeros)2049 int WavegenFill(int fill_zeros)
2050 {//============================
2051 	int finished;
2052 	unsigned char *p_start;
2053 
2054 	p_start = out_ptr;
2055 
2056 	// fill_zeros is ignored. It is now done in the portaudio callback
2057 	finished = WavegenFill2(0);
2058 
2059 #ifdef INCLUDE_SONIC
2060 	if(sonicSpeed > 1.0)
2061 	{
2062 		int length;
2063 		int max_length;
2064 
2065 		max_length = (out_end - p_start);
2066 		length =  2*SpeedUp((short *)p_start, (out_ptr-p_start)/2, max_length/2, finished);
2067 		out_ptr = p_start + length;
2068 
2069 		if(length >= max_length)
2070 			finished = 0;   // there may be more data to flush
2071 	}
2072 #endif
2073 	return finished;
2074 }  // end of WavegenFill
2075 
2076