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