1 /***************************************************************************
2 * Copyright (C) 2005 to 2007 by Jonathan Duddington *
3 * email: jonsd@users.sourceforge.net *
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. *
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. *
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 ***************************************************************************/
22 // this version keeps wavemult window as a constant fraction
23 // of the cycle length - but that spreads out the HF peaks too much
31 #include "speak_lib.h"
34 #include "synthesize.h"
37 //#undef INCLUDE_KLATT
40 #include "portaudio.h"
42 // determine portaudio version by looking for a #define which is not in V18
43 #ifdef paNeverDropInput
44 #define USE_PORTAUDIO 19
46 #define USE_PORTAUDIO 18
55 #define PI2 6.283185307
61 int option_waveout = 0;
62 static int option_harmonic1 = 10; // 10
63 int option_log_frames = 0;
64 static int flutter_amp = 64;
66 static int general_amplitude = 60;
67 static int consonant_amp = 26; // 24
69 int embedded_value[N_EMBEDDED_VALUES];
71 static int PHASE_INC_FACTOR;
72 int samplerate = 0; // this is set by Wavegeninit()
73 int samplerate_native=0;
74 extern int option_device_number;
75 extern int option_quiet;
77 static wavegen_peaks_t peaks[N_PEAKS];
78 static int peak_harmonic[N_PEAKS];
79 static int peak_height[N_PEAKS];
81 #define N_ECHO_BUF 5500 // max of 250mS at 22050 Hz
84 static int echo_length = 0; // period (in sample\) to ensure completion of echo at the end of speech, set in WavegenSetEcho()
85 static int echo_amp = 0;
86 static short echo_buf[N_ECHO_BUF];
89 static RESONATOR rbreath[N_PEAKS];
91 static int harm_sqrt_n = 0;
95 static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps
96 static int *harmspect;
98 static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between then
99 static int max_hval=0;
101 static int nsamples=0; // number to do
102 static int modulation_type = 0;
103 static int glottal_flag = 0;
104 static int glottal_reduce = 0;
111 static unsigned char *amplitude_env = NULL;
113 static int samplecount=0; // number done
114 static int samplecount_start=0; // count at start of this segment
115 static int end_wave=0; // continue to end of wave cycle
116 static int wavephase;
118 static int cycle_samples; // number of samples in a cycle at current pitch
120 static int hf_factor;
122 static double minus_pi_t;
123 static double two_pi_t;
126 unsigned char *out_ptr;
127 unsigned char *out_start;
128 unsigned char *out_end;
131 // the queue of operations passed to wavegen from sythesize
132 long wcmdq[N_WCMDQ][4];
137 int embedded_default[N_EMBEDDED_VALUES] = {0,50,170,100,50, 0,0, 0,170,0,0,0,0,0};
138 static int embedded_max[N_EMBEDDED_VALUES] = {0,0x7fff,600,300,99,99,99, 0,600,0,0,0,0,4};
140 #define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word
141 int current_source_index=0;
145 #if (USE_PORTAUDIO == 18)
146 static PortAudioStream *pa_stream=NULL;
148 #if (USE_PORTAUDIO == 19)
149 static PaStream *pa_stream=NULL;
152 /* default pitch envelope, a steady fall */
155 #define int(x) (int)(x)
157 unsigned char Pitch_env0[ENV_LEN] = {
158 255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225,
159 223,221,219,217,215,213,211,209,207,205,203,201,199,197,195,193,
160 191,189,187,185,183,181,179,177,175,173,171,169,167,165,163,161,
161 159,157,155,153,151,149,147,145,143,141,139,137,135,133,131,129,
162 127,125,123,121,119,117,115,113,111,109,107,105,103,101, 99, 97,
163 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67, 65,
164 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33,
165 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1
170 unsigned char Pitch_long[ENV_LEN] = {
171 254,249,250,251,252,253,254,254, 255,255,255,255,254,254,253,252,
172 251,250,249,247,244,242,238,234, 230,225,221,217,213,209,206,203,
173 199,195,191,187,183,179,175,172, 168,165,162,159,156,153,150,148,
174 145,143,140,138,136,134,132,130, 128,126,123,120,117,114,111,107,
175 104,100,96,91, 86,82,77,73, 70,66,63,60, 58,55,53,51,
176 49,47,46,45, 43,42,40,38, 36,34,31,28, 26,24,22,20,
177 18,16,14,12, 11,10,9,8, 8,8,8,8, 9,8,8,8,
178 8,8,7,7, 6,6,6,5, 4,4,3,3, 2,1,1,0
182 // 1st index=roughness
183 // 2nd index=modulation_type
184 // value: bits 0-3 amplitude (16ths), bits 4-7 every n cycles
185 #define N_ROUGHNESS 8
186 static unsigned char modulation_tab[N_ROUGHNESS][8] = {
187 {0, 0x00, 0x00, 0x00, 0, 0x46, 0xf2, 0x29},
188 {0, 0x2f, 0x00, 0x2f, 0, 0x45, 0xf2, 0x29},
189 {0, 0x2f, 0x00, 0x2e, 0, 0x45, 0xf2, 0x28},
190 {0, 0x2e, 0x00, 0x2d, 0, 0x34, 0xf2, 0x28},
191 {0, 0x2d, 0x2d, 0x2c, 0, 0x34, 0xf2, 0x28},
192 {0, 0x2b, 0x2b, 0x2b, 0, 0x34, 0xf2, 0x28},
193 {0, 0x2a, 0x2a, 0x2a, 0, 0x34, 0xf2, 0x28},
194 {0, 0x29, 0x29, 0x29, 0, 0x34, 0xf2, 0x28},
197 // Flutter table, to add natural variations to the pitch
198 #define N_FLUTTER 0x170
199 static int Flutter_inc;
200 static const unsigned char Flutter_tab[N_FLUTTER] = {
201 0x80, 0x9b, 0xb5, 0xcb, 0xdc, 0xe8, 0xed, 0xec,
202 0xe6, 0xdc, 0xce, 0xbf, 0xb0, 0xa3, 0x98, 0x90,
203 0x8c, 0x8b, 0x8c, 0x8f, 0x92, 0x94, 0x95, 0x92,
204 0x8c, 0x83, 0x78, 0x69, 0x59, 0x49, 0x3c, 0x31,
205 0x2a, 0x29, 0x2d, 0x36, 0x44, 0x56, 0x69, 0x7d,
206 0x8f, 0x9f, 0xaa, 0xb1, 0xb2, 0xad, 0xa4, 0x96,
207 0x87, 0x78, 0x69, 0x5c, 0x53, 0x4f, 0x4f, 0x55,
208 0x5e, 0x6b, 0x7a, 0x88, 0x96, 0xa2, 0xab, 0xb0,
210 0xb1, 0xae, 0xa8, 0xa0, 0x98, 0x91, 0x8b, 0x88,
211 0x89, 0x8d, 0x94, 0x9d, 0xa8, 0xb2, 0xbb, 0xc0,
212 0xc1, 0xbd, 0xb4, 0xa5, 0x92, 0x7c, 0x63, 0x4a,
213 0x32, 0x1e, 0x0e, 0x05, 0x02, 0x05, 0x0f, 0x1e,
214 0x30, 0x44, 0x59, 0x6d, 0x7f, 0x8c, 0x96, 0x9c,
215 0x9f, 0x9f, 0x9d, 0x9b, 0x99, 0x99, 0x9c, 0xa1,
216 0xa9, 0xb3, 0xbf, 0xca, 0xd5, 0xdc, 0xe0, 0xde,
217 0xd8, 0xcc, 0xbb, 0xa6, 0x8f, 0x77, 0x60, 0x4b,
219 0x3a, 0x2e, 0x28, 0x29, 0x2f, 0x3a, 0x48, 0x59,
220 0x6a, 0x7a, 0x86, 0x90, 0x94, 0x95, 0x91, 0x89,
221 0x80, 0x75, 0x6b, 0x62, 0x5c, 0x5a, 0x5c, 0x61,
222 0x69, 0x74, 0x80, 0x8a, 0x94, 0x9a, 0x9e, 0x9d,
223 0x98, 0x90, 0x86, 0x7c, 0x71, 0x68, 0x62, 0x60,
224 0x63, 0x6b, 0x78, 0x88, 0x9b, 0xaf, 0xc2, 0xd2,
225 0xdf, 0xe6, 0xe7, 0xe2, 0xd7, 0xc6, 0xb2, 0x9c,
226 0x84, 0x6f, 0x5b, 0x4b, 0x40, 0x39, 0x37, 0x38,
228 0x3d, 0x43, 0x4a, 0x50, 0x54, 0x56, 0x55, 0x52,
229 0x4d, 0x48, 0x42, 0x3f, 0x3e, 0x41, 0x49, 0x56,
230 0x67, 0x7c, 0x93, 0xab, 0xc3, 0xd9, 0xea, 0xf6,
231 0xfc, 0xfb, 0xf4, 0xe7, 0xd5, 0xc0, 0xaa, 0x94,
232 0x80, 0x71, 0x64, 0x5d, 0x5a, 0x5c, 0x61, 0x68,
233 0x70, 0x77, 0x7d, 0x7f, 0x7f, 0x7b, 0x74, 0x6b,
234 0x61, 0x57, 0x4e, 0x48, 0x46, 0x48, 0x4e, 0x59,
235 0x66, 0x75, 0x84, 0x93, 0x9f, 0xa7, 0xab, 0xaa,
237 0xa4, 0x99, 0x8b, 0x7b, 0x6a, 0x5b, 0x4e, 0x46,
238 0x43, 0x45, 0x4d, 0x5a, 0x6b, 0x7f, 0x92, 0xa6,
239 0xb8, 0xc5, 0xcf, 0xd3, 0xd2, 0xcd, 0xc4, 0xb9,
240 0xad, 0xa1, 0x96, 0x8e, 0x89, 0x87, 0x87, 0x8a,
241 0x8d, 0x91, 0x92, 0x91, 0x8c, 0x84, 0x78, 0x68,
242 0x55, 0x41, 0x2e, 0x1c, 0x0e, 0x05, 0x01, 0x05,
243 0x0f, 0x1f, 0x34, 0x4d, 0x68, 0x81, 0x9a, 0xb0,
244 0xc1, 0xcd, 0xd3, 0xd3, 0xd0, 0xc8, 0xbf, 0xb5,
246 0xab, 0xa4, 0x9f, 0x9c, 0x9d, 0xa0, 0xa5, 0xaa,
247 0xae, 0xb1, 0xb0, 0xab, 0xa3, 0x96, 0x87, 0x76,
248 0x63, 0x51, 0x42, 0x36, 0x2f, 0x2d, 0x31, 0x3a,
249 0x48, 0x59, 0x6b, 0x7e, 0x8e, 0x9c, 0xa6, 0xaa,
250 0xa9, 0xa3, 0x98, 0x8a, 0x7b, 0x6c, 0x5d, 0x52,
251 0x4a, 0x48, 0x4a, 0x50, 0x5a, 0x67, 0x75, 0x82
254 // waveform shape table for HF peaks, formants 6,7,8
255 #define N_WAVEMULT 128
256 static int wavemult_offset=0;
257 static int wavemult_max=0;
259 // the presets are for 22050 Hz sample rate.
260 // A different rate will need to recalculate the presets in WavegenInit()
261 static unsigned char wavemult[N_WAVEMULT] = {
262 0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 27, 32, 37, 43, 49,
263 55, 62, 69, 76, 83, 90, 98,105,113,121,128,136,144,152,159,166,
264 174,181,188,194,201,207,213,218,224,228,233,237,240,244,246,249,
265 251,252,253,253,253,253,252,251,249,246,244,240,237,233,228,224,
266 218,213,207,201,194,188,181,174,166,159,152,144,136,128,121,113,
267 105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14,
268 11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
272 // set from y = pow(2,x) * 128, x=-1 to 1
273 unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = {
274 64, 65, 66, 67, 68, 69, 70, 71,
275 72, 73, 74, 75, 76, 77, 78, 79,
276 80, 81, 82, 83, 84, 86, 87, 88,
277 89, 91, 92, 93, 94, 96, 97, 98,
278 100,101,103,104,105,107,108,110,
279 111,113,115,116,118,119,121,123,
280 124,126,128,130,132,133,135,137,
281 139,141,143,145,147,149,151,153,
282 155,158,160,162,164,167,169,171,
283 174,176,179,181,184,186,189,191,
284 194,197,199,202,205,208,211,214,
285 217,220,223,226,229,232,236,239,
286 242,246,249,252, 254,255 };
288 int WavegenFill(int fill_zeros);
292 static void LogMarker(int type, int value)
293 {//=======================================
294 if(option_log_frames == 0)
297 if((type == espeakEVENT_PHONEME) || (type == espeakEVENT_SENTENCE))
299 f_log=fopen("log-espeakedit","a");
302 if(type == espeakEVENT_PHONEME)
303 fprintf(f_log,"Phoneme [%s]\n",WordToString(value));
318 Pa_AbortStream(pa_stream);
326 i = wcmdq_head - wcmdq_tail;
327 if(i <= 0) i += N_WCMDQ;
333 return(N_WCMDQ - WcmdqFree());
340 if(wcmdq_tail >= N_WCMDQ) wcmdq_tail=0;
343 static void WcmdqIncHead()
344 {//=======================
346 if(wcmdq_head >= N_WCMDQ) wcmdq_head=0;
351 // data points from which to make the presets for pk_shape1 and pk_shape2
352 #define PEAKSHAPEW 256
353 static const float pk_shape_x[2][8] = {
354 {0,-0.6f, 0.0f, 0.6f, 1.4f, 2.5f, 4.5f, 5.5f},
355 {0,-0.6f, 0.0f, 0.6f, 1.4f, 2.0f, 4.5f, 5.5f }};
356 static const float pk_shape_y[2][8] = {
357 {0, 67, 81, 67, 31, 14, 0, -6} ,
358 {0, 77, 81, 77, 31, 7, 0, -6 }};
360 unsigned char pk_shape1[PEAKSHAPEW+1] = {
361 255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246,
362 245,244,242,241,239,238,236,234,233,231,229,227,225,223,220,218,
363 216,213,211,209,207,205,203,201,199,197,195,193,191,189,187,185,
364 183,180,178,176,173,171,169,166,164,161,159,156,154,151,148,146,
365 143,140,138,135,132,129,126,123,120,118,115,112,108,105,102, 99,
366 96, 95, 93, 91, 90, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73,
367 72, 70, 69, 68, 67, 66, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55,
368 55, 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 46,
369 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 44, 43,
370 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33,
371 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24,
372 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 18, 17, 17, 16,
373 16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10,
374 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5,
375 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2,
376 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
379 static unsigned char pk_shape2[PEAKSHAPEW+1] = {
380 255,254,254,254,254,254,254,254,254,254,253,253,253,253,252,252,
381 252,251,251,251,250,250,249,249,248,248,247,247,246,245,245,244,
382 243,243,242,241,239,237,235,233,231,229,227,225,223,221,218,216,
383 213,211,208,205,203,200,197,194,191,187,184,181,178,174,171,167,
384 163,160,156,152,148,144,140,136,132,127,123,119,114,110,105,100,
385 96, 94, 91, 88, 86, 83, 81, 78, 76, 74, 71, 69, 66, 64, 62, 60,
386 57, 55, 53, 51, 49, 47, 44, 42, 40, 38, 36, 34, 32, 30, 29, 27,
387 25, 23, 21, 19, 18, 16, 14, 12, 11, 9, 7, 6, 4, 3, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 static unsigned char *pk_shape;
401 static void WavegenInitPkData(int which)
402 {//=====================================
403 // this is only needed to set up the presets for pk_shape1 and pk_shape2
404 // These have already been pre-calculated and preset
413 pk_shape = pk_shape1;
415 pk_shape = pk_shape2;
418 for(ix=0;ix<PEAKSHAPEW;ix++)
420 x = (4.5*ix)/PEAKSHAPEW;
421 if(x >= pk_shape_x[which][p+3]) p++;
422 y[ix] = polint(&pk_shape_x[which][p],&pk_shape_y[which][p],3,x);
423 if(y[ix] > maxy) maxy = y[ix];
425 for(ix=0;ix<PEAKSHAPEW;ix++)
427 p = (int)(y[ix]*255/maxy);
428 pk_shape[ix] = (p >= 0) ? p : 0;
430 pk_shape[PEAKSHAPEW]=0;
432 } // end of WavegenInitPkData
437 // PortAudio interface
439 static int userdata[4];
440 static PaError pa_init_err=0;
441 static int out_channels=1;
443 #if USE_PORTAUDIO == 18
444 static int WaveCallback(void *inputBuffer, void *outputBuffer,
445 unsigned long framesPerBuffer, PaTimestamp outTime, void *userData )
447 static int WaveCallback(const void *inputBuffer, void *outputBuffer,
448 long unsigned int framesPerBuffer, const PaStreamCallbackTimeInfo *outTime,
449 PaStreamCallbackFlags flags, void *userData )
456 out_ptr = out_start = (unsigned char *)outputBuffer;
457 out_end = out_ptr + framesPerBuffer*2;
463 result = WavegenFill(1);
466 count_samples += framesPerBuffer;
469 // synchronous-playback mode, allow the calling process to abort the speech
470 event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list
471 event_list[event_list_ix].user_data = 0;
473 if(synth_callback(NULL,0,event_list) == 1)
475 SpeakNextClause(NULL,NULL,2); // stop speaking
483 // swap the order of bytes in each sound sample in the portaudio buffer
485 out_ptr = (unsigned char *)outputBuffer;
486 out_end = out_ptr + framesPerBuffer*2;
487 while(out_ptr < out_end)
490 out_ptr[0] = out_ptr[1];
497 if(out_channels == 2)
499 // sound output can only do stereo, not mono. Duplicate each sound sample to
500 // produce 2 channels.
501 out_ptr = (unsigned char *)outputBuffer;
502 for(ix=framesPerBuffer-1; ix>=0; ix--)
505 p[3] = p[1] = out_ptr[ix*2 + 1];
506 p[2] = p[0] = out_ptr[ix*2];
510 #if USE_PORTAUDIO == 18
511 #ifdef PLATFORM_WINDOWS
516 static int end_timer = 0;
531 } // end of WaveCallBack
534 #if USE_PORTAUDIO == 19
535 /* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19
538 static PaError Pa_OpenDefaultStream2( PaStream** stream,
539 int inputChannelCount,
540 int outputChannelCount,
541 PaSampleFormat sampleFormat,
543 unsigned long framesPerBuffer,
544 PaStreamCallback *streamCallback,
548 PaStreamParameters hostApiOutputParameters;
550 if(option_device_number >= 0)
551 hostApiOutputParameters.device = option_device_number;
553 hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
555 if( hostApiOutputParameters.device == paNoDevice )
556 return paDeviceUnavailable;
558 hostApiOutputParameters.channelCount = outputChannelCount;
559 hostApiOutputParameters.sampleFormat = sampleFormat;
560 /* defaultHighOutputLatency is used below instead of
561 defaultLowOutputLatency because it is more important for the default
562 stream to work reliably than it is for it to work with the lowest
565 hostApiOutputParameters.suggestedLatency =
566 Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
567 hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
569 result = Pa_OpenStream(
570 stream, NULL, &hostApiOutputParameters, sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
577 int WavegenOpenSound()
578 {//===================
582 if(option_waveout || option_quiet)
584 // writing to WAV file, not to portaudio
588 #if USE_PORTAUDIO == 18
589 active = Pa_StreamActive(pa_stream);
591 active = Pa_IsStreamActive(pa_stream);
600 #if USE_PORTAUDIO == 18
601 err2 = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata);
603 if(err2 == paInvalidChannelCount)
605 // failed to open with mono, try stereo
607 err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,samplerate,512,N_WAV_BUF,WaveCallback,(void *)userdata);
610 err2 = Pa_OpenDefaultStream2(&pa_stream,0,1,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata);
612 if(err2 == paInvalidChannelCount)
614 // failed to open with mono, try stereo
616 err2 = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)samplerate,512,WaveCallback,(void *)userdata);
620 err = Pa_StartStream(pa_stream);
622 #if USE_PORTAUDIO == 19
623 if(err == paStreamIsNotStopped)
625 // not sure why we need this, but PA v19 seems to need it
626 err = Pa_StopStream(pa_stream);
627 err = Pa_StartStream(pa_stream);
633 // exit speak if we can't open the sound device - this is OK if speak is being run for each utterance
642 int WavegenCloseSound()
643 {//====================
646 // check whether speaking has finished, and close the stream
647 if(pa_stream != NULL)
649 #if USE_PORTAUDIO == 18
650 active = Pa_StreamActive(pa_stream);
652 active = Pa_IsStreamActive(pa_stream);
654 if(WcmdqUsed() == 0) // also check that the queue is empty
658 Pa_CloseStream(pa_stream);
665 WavegenOpenSound(); // still items in the queue, shouldn't be closed
672 int WavegenInitSound()
673 {//===================
679 // PortAudio sound output library
680 err = Pa_Initialize();
684 fprintf(stderr,"Failed to initialise the PortAudio sound\n");
690 int WavegenOpenSound()
691 {//===================
694 int WavegenCloseSound()
695 {//====================
698 int WavegenInitSound()
699 {//===================
705 void WavegenInit(int rate, int wavemult_fact)
706 {//==========================================
710 if(wavemult_fact == 0)
711 wavemult_fact=60; // default
714 samplerate = samplerate_native = rate;
715 PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32
716 Flutter_inc = (64 * samplerate)/rate;
719 wavephase = 0x7fffffff;
722 wdata.amplitude = 32;
723 wdata.prev_was_synth = 0;
725 for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
726 embedded_value[ix] = embedded_default[ix];
729 // set up window to generate a spread of harmonics from a
730 // single peak for HF peaks
731 wavemult_max = (samplerate * wavemult_fact)/(256 * 50);
732 if(wavemult_max > N_WAVEMULT) wavemult_max = N_WAVEMULT;
734 wavemult_offset = wavemult_max/2;
736 if(samplerate != 22050)
738 // wavemult table has preset values for 22050 Hz, we only need to
739 // recalculate them if we have a different sample rate
740 for(ix=0; ix<wavemult_max; ix++)
742 x = 127*(1.0 - cos(PI2*ix/wavemult_max));
743 wavemult[ix] = (int)x;
747 WavegenInitPkData(1);
748 WavegenInitPkData(0);
749 pk_shape = pk_shape2; // pk_shape2
756 remove("log-espeakedit");
758 } // end of WavegenInit
761 int GetAmplitude(void)
762 {//===================
765 // normal, none, reduced, moderate, strong
766 static const unsigned char amp_emphasis[5] = {16, 16, 10, 16, 22};
768 amp = (embedded_value[EMBED_A])*55/100;
769 general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16;
770 return(general_amplitude);
774 static void WavegenSetEcho(void)
775 {//=============================
779 voicing = wvoice->voicing;
780 delay = wvoice->echo_delay;
781 amp = wvoice->echo_amp;
783 if(delay >= N_ECHO_BUF)
784 delay = N_ECHO_BUF-1;
788 memset(echo_buf,0,sizeof(echo_buf));
791 if(embedded_value[EMBED_H] > 0)
793 // set echo from an embedded command in the text
794 amp = embedded_value[EMBED_H];
797 if(embedded_value[EMBED_T] > 0)
799 // announcing punctuation
800 amp = embedded_value[EMBED_T] * 8;
807 echo_head = (delay * samplerate)/1000;
808 echo_length = echo_head; // ensure completion of echo at the end of speech. Use 1 delay period?
812 echo_length = echo_head * 2; // perhaps allow 2 echo periods if the echo is loud.
814 // echo_amp units are 1/256ths of the amplitude of the original sound.
816 // compensate (partially) for increase in amplitude due to echo
817 general_amplitude = GetAmplitude();
818 general_amplitude = ((general_amplitude * (500-amp))/500);
819 } // end of WavegenSetEcho
823 int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control)
824 {//============================================================================
825 // Calculate the amplitude of each harmonics from the formants
826 // Only for formants 0 to 5
828 // control 0=initial call, 1=every 64 cycles
830 // pitch and freqs are Hz<<16
834 int fp; // centre freq of peak
835 int fhi; // high freq of peak
836 int h; // harmonic number
839 int hmax_samplerate; // highest harmonic allowed for the samplerate
846 return(HarmToHarmspect(pitch,htab));
849 // initialise as much of *out as we will need
852 hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch;
853 if(hmax >= MAX_HARMONIC)
854 hmax = MAX_HARMONIC-1;
856 // restrict highest harmonic to half the samplerate
857 hmax_samplerate = (((samplerate * 19)/40) << 16)/pitch; // only 95% of Nyquist freq
858 // hmax_samplerate = (samplerate << 16)/(pitch*2);
860 if(hmax > hmax_samplerate)
861 hmax = hmax_samplerate;
867 for(pk=0; pk<=wvoice->n_harmonic_peaks; pk++)
870 if((p->height == 0) || (fp = p->freq)==0)
873 fhi = p->freq + p->right;
874 h = ((p->freq - p->left) / pitch) + 1;
877 for(f=pitch*h; f < fp; f+=pitch)
879 htab[h++] += pk_shape[(fp-f)/(p->left>>8)] * p->height;
881 for(; f < fhi; f+=pitch)
883 htab[h++] += pk_shape[(f-fp)/(p->right>>8)] * p->height;
891 y = peaks[1].height * 10; // addition as a multiple of 1/256s
892 h2 = (1000<<16)/pitch; // decrease until 1000Hz
905 // find the nearest harmonic for HF peaks where we don't use shape
906 for(; pk<N_PEAKS; pk++)
908 x = peaks[pk].height >> 14;
909 peak_height[pk] = (x * x * 5)/2;
911 // find the nearest harmonic for HF peaks where we don't use shape
914 // set this initially, but make changes only at the quiet point
915 peak_harmonic[pk] = peaks[pk].freq / pitch;
917 // only use harmonics up to half the samplerate
918 if(peak_harmonic[pk] >= hmax_samplerate)
922 // convert from the square-rooted values
924 for(h=0; h<=hmax; h++, f+=pitch)
927 htab[h] = (x * x) >> 8;
929 if((ix = (f >> 19)) < N_TONE_ADJUST)
931 htab[h] = (htab[h] * wvoice->tone_adjust[ix]) >> 13; // index tone_adjust with Hz/8
935 // adjust the amplitude of the first harmonic, affects tonal quality
936 h1 = htab[1] * option_harmonic1;
940 // calc intermediate increments of LF harmonics
943 for(h=1; h<N_LOWHARM; h++)
945 harm_inc[h] = (htab[h] - harmspect[h]) >> 3;
949 return(hmax); // highest harmonic number
950 } // end of PeaksToHarmspect
954 static void AdvanceParameters()
955 {//============================
956 // Called every 64 samples to increment the formant freq, height, and widths
960 static int Flutter_ix = 0;
963 wdata.pitch_ix += wdata.pitch_inc;
964 if((ix = wdata.pitch_ix>>8) > 127) ix = 127;
965 x = wdata.pitch_env[ix] * wdata.pitch_range;
966 wdata.pitch = (x>>8) + wdata.pitch_base;
970 /* add pitch flutter */
971 if(Flutter_ix >= (N_FLUTTER*64))
973 x = ((int)(Flutter_tab[Flutter_ix >> 6])-0x80) * flutter_amp;
974 Flutter_ix += Flutter_inc;
976 if(wdata.pitch < 102400)
977 wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12)
979 if(samplecount == samplecount_start)
982 for(ix=0; ix <= wvoice->n_harmonic_peaks; ix++)
984 peaks[ix].freq1 += peaks[ix].freq_inc;
985 peaks[ix].freq = (int)(peaks[ix].freq1);
986 peaks[ix].height1 += peaks[ix].height_inc;
987 if((peaks[ix].height = (int)(peaks[ix].height1)) < 0)
988 peaks[ix].height = 0;
989 peaks[ix].left1 += peaks[ix].left_inc;
990 peaks[ix].left = (int)(peaks[ix].left1);
993 peaks[ix].right1 += peaks[ix].right_inc;
994 peaks[ix].right = (int)(peaks[ix].right1);
998 peaks[ix].right = peaks[ix].left;
1003 // formants 6,7,8 don't have a width parameter
1006 peaks[ix].freq1 += peaks[ix].freq_inc;
1007 peaks[ix].freq = (int)(peaks[ix].freq1);
1009 peaks[ix].height1 += peaks[ix].height_inc;
1010 if((peaks[ix].height = (int)(peaks[ix].height1)) < 0)
1011 peaks[ix].height = 0;
1015 if(harm_sqrt_n != 0)
1017 // We are generating from a harmonic spectrum at a given pitch, not from formant peaks
1018 for(ix=0; ix<harm_sqrt_n; ix++)
1019 harm_sqrt[ix] += harm_sqrt_inc[ix];
1022 } // end of AdvanceParameters
1025 #ifndef PLATFORM_RISCOS
1026 static double resonator(RESONATOR *r, double input)
1027 {//================================================
1030 x = r->a * input + r->b * r->x1 + r->c * r->x2;
1039 static void setresonator(RESONATOR *rp, int freq, int bwidth, int init)
1040 {//====================================================================
1041 // freq Frequency of resonator in Hz
1042 // bwidth Bandwidth of resonator in Hz
1043 // init Initialize internal data
1054 // x = exp(-pi * bwidth * t)
1055 arg = minus_pi_t * bwidth;
1061 // b = x * 2*cos(2 pi * freq * t)
1063 arg = two_pi_t * freq;
1064 rp->b = x * cos(arg) * 2.0;
1067 rp->a = 1.0 - rp->b - rp->c;
1068 } // end if setresonator
1072 void InitBreath(void)
1073 {//==================
1074 #ifndef PLATFORM_RISCOS
1077 minus_pi_t = -PI / samplerate;
1078 two_pi_t = -2.0 * minus_pi_t;
1080 for(ix=0; ix<N_PEAKS; ix++)
1082 setresonator(&rbreath[ix],2000,200,1);
1085 } // end of InitBreath
1089 static void SetBreath()
1090 {//====================
1091 #ifndef PLATFORM_RISCOS
1094 if(wvoice->breath[0] == 0)
1097 for(pk=1; pk<N_PEAKS; pk++)
1099 if(wvoice->breath[pk] != 0)
1101 // breath[0] indicates that some breath formants are needed
1102 // set the freq from the current ynthesis formant and the width from the voice data
1103 setresonator(&rbreath[pk], peaks[pk].freq >> 16, wvoice->breathw[pk],0);
1107 } // end of SetBreath
1110 static int ApplyBreath(void)
1111 {//=========================
1113 #ifndef PLATFORM_RISCOS
1118 // use two random numbers, for alternate formants
1119 noise = (rand() & 0x3fff) - 0x2000;
1121 for(ix=1; ix < N_PEAKS; ix++)
1123 if((amp = wvoice->breath[ix]) != 0)
1125 amp *= (peaks[ix].height >> 14);
1126 value += (int)(resonator(&rbreath[ix],noise) * amp);
1137 unsigned short waveph;
1138 unsigned short theta;
1145 static int maxh, maxh2;
1150 int modn_amp, modn_period;
1151 static int agc = 256;
1152 static int h_switch_sign = 0;
1153 static int cycle_count = 0;
1154 static int amplitude2 = 0; // adjusted for pitch
1156 // continue until the output buffer is full, or
1157 // the required number of samples have been produced
1161 if((end_wave==0) && (samplecount==nsamples))
1164 if((samplecount & 0x3f) == 0)
1166 // every 64 samples, adjust the parameters
1167 if(samplecount == 0)
1170 harmspect = hspect[0];
1171 maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[0], 0);
1173 // adjust amplitude to compensate for fewer harmonics at higher pitch
1174 amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
1176 // switch sign of harmonics above about 900Hz, to reduce max peak amplitude
1177 h_switch_sign = 890 / (wdata.pitch >> 12);
1180 AdvanceParameters();
1183 phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR;
1184 cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2)
1185 hf_factor = wdata.pitch >> 11;
1188 harmspect = hspect[hswitch];
1190 maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[hswitch], 1);
1195 if((samplecount & 0x07) == 0)
1197 for(h=1; h<N_LOWHARM && h<=maxh2 && h<=maxh; h++)
1199 harmspect[h] += harm_inc[h];
1202 // bring automctic gain control back towards unity
1203 if(agc < 256) agc++;
1210 wavephase += phaseinc;
1213 // sign has changed, reached a quiet point in the waveform
1214 cbytes = wavemult_offset - (cycle_samples)/2;
1215 if(samplecount > nsamples)
1220 for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++)
1222 // find the nearest harmonic for HF peaks where we don't use shape
1223 peak_harmonic[pk] = peaks[pk].freq / (wdata.pitch*16);
1226 // adjust amplitude to compensate for fewer harmonics at higher pitch
1227 amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
1229 if(glottal_flag > 0)
1231 if(glottal_flag == 3)
1233 if((nsamples-samplecount) < (cycle_samples*2))
1235 // Vowel before glottal-stop.
1236 // This is the start of the penultimate cycle, reduce its amplitude
1238 amplitude2 = (amplitude2 * glottal_reduce)/256;
1242 if(glottal_flag == 4)
1244 // Vowel following a glottal-stop.
1245 // This is the start of the second cycle, reduce its amplitude
1247 amplitude2 = (amplitude2 * glottal_reduce)/256;
1255 if(amplitude_env != NULL)
1257 // amplitude envelope is only used for creaky voice effect on certain vowels/tones
1258 if((ix = amp_ix>>8) > 127) ix = 127;
1259 amp = amplitude_env[ix];
1260 amplitude2 = (amplitude2 * amp)/128;
1262 // modulation_type = 7;
1265 // introduce roughness into the sound by reducing the amplitude of
1267 if(voice->roughness < N_ROUGHNESS)
1269 modn_period = modulation_tab[voice->roughness][modulation_type];
1270 modn_amp = modn_period & 0xf;
1271 modn_period = modn_period >> 4;
1274 if(modn_period != 0)
1276 if(modn_period==0xf)
1279 amplitude2 = (amplitude2 * modn_amp)/16;
1280 modulation_type = 0;
1284 // reduce amplitude every [modn_period} cycles
1285 if((cycle_count % modn_period)==0)
1286 amplitude2 = (amplitude2 * modn_amp)/16;
1293 wavephase += phaseinc;
1295 waveph = (unsigned short)(wavephase >> 16);
1298 // apply HF peaks, formants 6,7,8
1299 // add a single harmonic and then spread this my multiplying by a
1300 // window. This is to reduce the processing power needed to add the
1301 // higher frequence harmonics.
1303 if(cbytes >=0 && cbytes<wavemult_max)
1305 for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++)
1307 theta = peak_harmonic[pk] * waveph;
1308 total += (long)sin_tab[theta >> 5] * peak_height[pk];
1311 // spread the peaks by multiplying by a window
1312 total = (long)(total / hf_factor) * wavemult[cbytes];
1315 // apply main peaks, formants 0 to 5
1316 #ifdef USE_ASSEMBLER_1
1317 // use an optimised routine for this loop, if available
1318 total += AddSineWaves(waveph, h_switch_sign, maxh, harmspect); // call an assembler code routine
1322 for(h=1; h<=h_switch_sign; h++)
1324 total += ((int)(sin_tab[theta >> 5]) * harmspect[h]);
1329 total -= ((int)(sin_tab[theta >> 5]) * harmspect[h]);
1337 total = (total >> 6) * voicing;
1340 #ifndef PLATFORM_RISCOS
1341 if(wvoice->breath[0])
1343 total += ApplyBreath();
1347 // mix with sampled wave if required
1349 if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile)
1351 if(wdata.mix_wave_scale == 0)
1354 c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1];
1355 sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256);
1356 wdata.mix_wavefile_ix += 2;
1360 // a 8 bit sample, scaled
1361 sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
1363 z2 = (sample * wdata.amplitude_v) >> 10;
1364 z2 = (z2 * wdata.mix_wave_amp)/32;
1367 z1 = z2 + (((total>>8) * amplitude2) >> 13);
1369 echo = (echo_buf[echo_tail++] * echo_amp);
1371 if(echo_tail >= N_ECHO_BUF)
1374 z = (z1 * agc) >> 8;
1376 // check for overflow, 16bit signed samples
1379 ov = 8388608/z1 - 1; // 8388608 is 2^23, i.e. max value * 256
1380 if(ov < agc) agc = ov; // set agc to number of 1/256ths to multiply the sample by
1381 z = (z1 * agc) >> 8; // reduce sample by agc value to prevent overflow
1386 ov = -8388608/z1 - 1;
1387 if(ov < agc) agc = ov;
1388 z = (z1 * agc) >> 8;
1391 *out_ptr++ = z >> 8;
1393 echo_buf[echo_head++] = z;
1394 if(echo_head >= N_ECHO_BUF)
1397 if(out_ptr >= out_end)
1404 static int PlaySilence(int length, int resume)
1405 {//===========================================
1406 static int n_samples;
1418 while(n_samples-- > 0)
1420 value = (echo_buf[echo_tail++] * echo_amp) >> 8;
1422 if(echo_tail >= N_ECHO_BUF)
1426 *out_ptr++ = value >> 8;
1428 echo_buf[echo_head++] = value;
1429 if(echo_head >= N_ECHO_BUF)
1432 if(out_ptr >= out_end)
1436 } // end of PlaySilence
1440 static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp)
1441 {//=================================================================================
1442 static int n_samples;
1456 while(n_samples-- > 0)
1462 value = data[ix] + (c * 256);
1467 // 8 bit data, shift by the specified scale factor
1468 value = (signed char)data[ix++] * scale;
1470 value *= (consonant_amp * general_amplitude); // reduce strength of consonant
1471 value = value >> 10;
1472 value = (value * amp)/32;
1474 value += ((echo_buf[echo_tail++] * echo_amp) >> 8);
1482 if(echo_tail >= N_ECHO_BUF)
1486 out_ptr[1] = value >> 8;
1489 echo_buf[echo_head++] = (value*3)/4;
1490 if(echo_head >= N_ECHO_BUF)
1493 if(out_ptr >= out_end)
1500 static int SetWithRange0(int value, int max)
1501 {//=========================================
1510 void SetEmbedded(int control, int value)
1511 {//=====================================
1512 // there was an embedded command in the text at this point
1519 command = control & 0x1f;
1520 if((control & 0x60) == 0x60)
1523 if((control & 0x60) == 0x40)
1526 if(command < N_EMBEDDED_VALUES)
1529 embedded_value[command] = value;
1531 embedded_value[command] += (value * sign);
1532 embedded_value[command] = SetWithRange0(embedded_value[command],embedded_max[command]);
1538 WavegenSetEcho(); // and drop through to case P
1540 // adjust formants to give better results for a different voice pitch
1541 if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE)
1542 pitch_value = MAX_PITCH_VALUE;
1544 factor = 256 + (25 * (pitch_value - 50))/50;
1545 for(ix=0; ix<=5; ix++)
1547 wvoice->freq[ix] = (wvoice->freq2[ix] * factor)/256;
1549 factor = embedded_value[EMBED_T]*3;
1550 wvoice->height[0] = (wvoice->height2[0] * (256 - factor*2))/256;
1551 wvoice->height[1] = (wvoice->height2[1] * (256 - factor))/256;
1554 case EMBED_A: // amplitude
1555 general_amplitude = GetAmplitude();
1558 case EMBED_F: // emphasiis
1559 general_amplitude = GetAmplitude();
1569 void WavegenSetVoice(voice_t *v)
1570 {//=============================
1573 memcpy(&v2,v,sizeof(v2));
1576 if(v->peak_shape==0)
1577 pk_shape = pk_shape1;
1579 pk_shape = pk_shape2;
1581 consonant_amp = (v->consonant_amp * 26) /100;
1582 if(samplerate <= 11000)
1584 consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates
1585 option_harmonic1 = 6;
1591 static void SetAmplitude(int length, unsigned char *amp_env, int value)
1592 {//====================================================================
1597 amp_inc = (256 * ENV_LEN * STEPSIZE)/length;
1599 wdata.amplitude = (value * general_amplitude)/16;
1600 wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds
1602 amplitude_env = amp_env;
1606 void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range)
1607 {//======================================================================================
1615 x = pitch1; // swap values
1620 if((pitch_value = embedded_value[EMBED_P]) > MAX_PITCH_VALUE)
1621 pitch_value = MAX_PITCH_VALUE;
1622 pitch_value -= embedded_value[EMBED_T]; // adjust tone for announcing punctuation
1626 base = (voice->pitch_base * pitch_adjust_tab[pitch_value])/128;
1627 range = (voice->pitch_range * embedded_value[EMBED_R])/50;
1629 // compensate for change in pitch when the range is narrowed or widened
1630 base -= (range - voice->pitch_range)*18;
1632 *pitch_base = base + (pitch1 * range);
1633 *pitch_range = base + (pitch2 * range) - *pitch_base;
1637 void SetPitch(int length, unsigned char *env, int pitch1, int pitch2)
1638 {//==================================================================
1639 // length in samples
1642 if(option_log_frames)
1644 f_log=fopen("log-espeakedit","a");
1647 fprintf(f_log," pitch %3d %3d %3dmS\n",pitch1,pitch2,(length*1000)/samplerate);
1653 if((wdata.pitch_env = env)==NULL)
1654 wdata.pitch_env = env_fall; // default
1658 wdata.pitch_inc = 0;
1660 wdata.pitch_inc = (256 * ENV_LEN * STEPSIZE)/length;
1662 SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range);
1663 // set initial pitch
1664 wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12
1666 flutter_amp = wvoice->flutter;
1668 } // end of SetPitch
1674 void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v)
1675 {//========================================================================
1682 static int glottal_reduce_tab1[4] = {0x30, 0x30, 0x40, 0x50}; // vowel before [?], amp * 1/256
1683 // static int glottal_reduce_tab1[4] = {0x30, 0x40, 0x50, 0x60}; // vowel before [?], amp * 1/256
1684 static int glottal_reduce_tab2[4] = {0x90, 0xa0, 0xb0, 0xc0}; // vowel after [?], amp * 1/256
1687 if(option_log_frames)
1689 f_log=fopen("log-espeakedit","a");
1692 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,
1693 fr1->ffreq[0],fr1->ffreq[1],fr1->ffreq[2],fr1->ffreq[3], fr1->fheight[0],fr1->fheight[1],fr1->fheight[2],fr1->fheight[3],
1694 fr2->ffreq[0],fr2->ffreq[1],fr2->ffreq[2],fr2->ffreq[3], fr2->fheight[0],fr2->fheight[1],fr2->fheight[2],fr2->fheight[3] );
1705 // any additional information in the param1 ?
1706 modulation_type = modn & 0xff;
1711 glottal_flag = 3; // before a glottal stop
1712 glottal_reduce = glottal_reduce_tab1[(modn >> 8) & 3];
1716 glottal_flag = 4; // after a glottal stop
1717 glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3];
1720 for(qix=wcmdq_head+1;;qix++)
1722 if(qix >= N_WCMDQ) qix = 0;
1723 if(qix == wcmdq_tail) break;
1725 cmd = wcmdq[qix][0];
1728 end_wave = 0; // next wave generation is from another spectrum
1731 if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE))
1732 break; // next is not from spectrum, so continue until end of wave cycle
1735 // round the length to a multiple of the stepsize
1736 length2 = (length + STEPSIZE/2) & ~0x3f;
1740 // add this length to any left over from the previous synth
1741 samplecount_start = samplecount;
1742 nsamples += length2;
1744 length4 = length2/4;
1746 peaks[7].freq = (7800 * v->freq[7] + v->freqadd[7]*256) << 8;
1747 peaks[8].freq = (9000 * v->freq[8] + v->freqadd[8]*256) << 8;
1749 for(ix=0; ix < 8; ix++)
1753 peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8;
1754 peaks[ix].freq = (int)(peaks[ix].freq1);
1755 next = (fr2->ffreq[ix] * v->freq[ix] + v->freqadd[ix]*256) << 8;
1756 peaks[ix].freq_inc = ((next - peaks[ix].freq1) * (STEPSIZE/4)) / length4; // lower headroom for fixed point math
1759 peaks[ix].height1 = (fr1->fheight[ix] * v->height[ix]) << 6;
1760 peaks[ix].height = (int)(peaks[ix].height1);
1761 next = (fr2->fheight[ix] * v->height[ix]) << 6;
1762 peaks[ix].height_inc = ((next - peaks[ix].height1) * STEPSIZE) / length2;
1764 if(ix <= wvoice->n_harmonic_peaks)
1766 peaks[ix].left1 = (fr1->fwidth[ix] * v->width[ix]) << 10;
1767 peaks[ix].left = int(peaks[ix].left1);
1768 next = (fr2->fwidth[ix] * v->width[ix]) << 10;
1769 peaks[ix].left_inc = ((next - peaks[ix].left1) * STEPSIZE) / length2;
1773 peaks[ix].right1 = (fr1->fright[ix] * v->width[ix]) << 10;
1774 peaks[ix].right = int(peaks[ix].right1);
1775 next = (fr2->fright[ix] * v->width[ix]) << 10;
1776 peaks[ix].right_inc = ((next - peaks[ix].right1) * STEPSIZE) / length2;
1780 peaks[ix].right = peaks[ix].left;
1784 } // end of SetSynth
1787 static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
1788 {//====================================================================================
1790 SetSynth(length, modulation, fr1, fr2, wvoice);
1795 void Write4Bytes(FILE *f, int value)
1796 {//=================================
1797 // Write 4 bytes to a file, least significant first
1800 for(ix=0; ix<4; ix++)
1802 fputc(value & 0xff,f);
1810 int WavegenFill(int fill_zeros)
1811 {//============================
1812 // Pick up next wavegen commands from the queue
1813 // return: 0 output buffer has been filled
1814 // return: 1 input command queue is now empty
1819 static int resume=0;
1820 static int echo_complete=0;
1823 if(mbrola_name[0] != 0)
1824 return(MbrolaFill(fill_zeros));
1827 while(out_ptr < out_end)
1829 if(WcmdqUsed() <= 0)
1831 if(echo_complete > 0)
1833 // continue to play silence until echo is completed
1834 resume = PlaySilence(echo_complete,resume);
1836 return(0); // not yet finished
1841 while(out_ptr < out_end)
1844 return(1); // queue empty, close sound channel
1848 q = wcmdq[wcmdq_head];
1854 SetPitch(length,(unsigned char *)q[2],q[3] >> 16,q[3] & 0xffff);
1860 echo_complete -= length;
1862 wdata.n_mix_wavefile = 0;
1863 wdata.prev_was_synth = 0;
1864 result = PlaySilence(length,resume);
1868 echo_complete = echo_length;
1869 wdata.n_mix_wavefile = 0;
1870 wdata.prev_was_synth = 0;
1871 result = PlayWave(length,resume,(unsigned char*)q[2], q[3] & 0xff, q[3] >> 8);
1875 // wave file to be played at the same time as synthesis
1876 wdata.mix_wave_amp = q[3] >> 8;
1877 wdata.mix_wave_scale = q[3] & 0xff;
1878 if(wdata.mix_wave_scale == 0)
1879 wdata.n_mix_wavefile = length*2;
1881 wdata.n_mix_wavefile = length;
1882 wdata.mix_wavefile_ix = 0;
1883 wdata.mix_wavefile = (unsigned char *)q[2];
1886 case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file
1887 wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
1889 echo_complete = echo_length;
1890 result = Wavegen2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
1893 #ifdef INCLUDE_KLATT
1894 case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file
1895 wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
1897 echo_complete = echo_length;
1898 result = Wavegen_Klatt2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
1903 MarkerEvent(q[1],q[2],q[3],out_ptr);
1905 LogMarker(q[1],q[3]);
1909 current_source_index = q[2] & 0xffffff;
1913 case WCMD_AMPLITUDE:
1914 SetAmplitude(length,(unsigned char *)q[2],q[3]);
1918 WavegenSetVoice((voice_t *)q[1]);
1919 free((voice_t *)q[1]);
1923 SetEmbedded(q[1],q[2]);
1939 } // end of WavegenFill