1 #include <config.h>
2 /* $Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $
3 */
4 char *holmes_id = "$Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $";
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <useconfig.h>
8 #include <math.h>
9 #include "proto.h"
10 #include "nsynth.h"
11 #include "elements.h"
12 #include "darray.h"
13 #include "holmes.h"
14 #include "phfeat.h"
15 #include "getargs.h"
16
17 #if 1
18 #define AMP_ADJ 14
19 #else
20 #define AMP_ADJ 0
21 #endif
22
23 FILE *par_file;
24 FILE *jsru_file;
25 int speed = 1;
26
27 double frac = 1.0;
28
29 typedef struct
30 {
31 float v; /* boundary value */
32 int t; /* transition time */
33 }
34 slope_t;
35
36 typedef struct
37 {
38 slope_t p[nEparm];
39 }
40 trans_t;
41
42 typedef struct
43 {
44 float a;
45 float b;
46 float v;
47 }
48 filter_t, *filter_ptr;
49
50 static float filter PROTO((filter_ptr p, Float v));
51
52 static void jsru_save PROTO((double f0, float *tp));
53
54 static float
filter(p,v)55 filter(p, v)
56 filter_ptr p;
57 Float v;
58 {
59 return p->v = (p->a * v + p->b * p->v);
60 }
61
62 /* 'a' is dominant element, 'b' is dominated
63 ext is flag to say to use external times from 'a' rather
64 than internal i.e. ext != 0 if 'a' is NOT current element.
65
66 */
67
68 static void set_trans PROTO((slope_t * t, Elm_ptr a, Elm_ptr b, int ext, int e));
69
70 static void
set_trans(t,a,b,ext,e)71 set_trans(t, a, b, ext, e)
72 slope_t *t;
73 Elm_ptr a;
74 Elm_ptr b;
75 int ext;
76 int e;
77 {
78 int i;
79 for (i = 0; i < nEparm; i++)
80 {
81 t[i].t = ((ext) ? a->p[i].ed : a->p[i].id) * speed;
82 if (t[i].t)
83 t[i].v = a->p[i].fixd + (a->p[i].prop * b->p[i].stdy) * (float) 0.01;
84 else
85 t[i].v = b->p[i].stdy;
86 }
87 }
88
89 static float linear PROTO((Float a, Float b, int t, int d));
90
91 /*
92 ______________ b
93 /
94 /
95 /
96 a____________/
97 0 d
98 ---------------t---------------
99 */
100
101 static float
linear(a,b,t,d)102 linear(a, b, t, d)
103 Float a;
104 Float b;
105 int t;
106 int d;
107 {
108 if (t <= 0)
109 return a;
110 else if (t >= d)
111 return b;
112 else
113 {
114 float f = (float) t / (float) d;
115 return a + (b - a) * f;
116 }
117 }
118
119 static float interpolate PROTO((char *w, char *p, slope_t * s, slope_t * e, Float mid, int t, int d));
120
121 static float
interpolate(w,p,s,e,mid,t,d)122 interpolate(w, p, s, e, mid, t, d)
123 char *w;
124 char *p;
125 slope_t *s;
126 slope_t *e;
127 Float mid;
128 int t;
129 int d;
130 {
131 float steady = d - (s->t + e->t);
132 #ifdef DEBUG
133 fprintf(stdout, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n",
134 w, p, s->v, s->t, e->v, e->t, mid, steady);
135 #endif
136 if (steady >= 0)
137 {
138 /* Value reaches stready state somewhere ... */
139 if (t < s->t)
140 return linear(s->v, mid, t, s->t); /* initial transition */
141 else
142 {
143 t -= s->t;
144 if (t <= steady)
145 return mid; /* steady state */
146 else
147 return linear(mid, e->v, (int) (t - steady), e->t);
148 /* final transition */
149 }
150 }
151 else
152 {
153 float f = (float) 1.0 - ((float) t / (float) d);
154 float sp = linear(s->v, mid, t, s->t);
155 float ep = linear(e->v, mid, d - t, e->t);
156 return f * sp + ((float) 1.0 - f) * ep;
157 }
158 }
159
160
161 unsigned
holmes(nelm,elm,nsamp,samp_base)162 holmes(nelm, elm, nsamp, samp_base)
163 unsigned nelm;
164 unsigned char *elm;
165 unsigned nsamp;
166 short *samp_base;
167 {
168 filter_t flt[nEparm];
169 klatt_frame_t pars;
170 short *samp = samp_base;
171 Elm_ptr le = &Elements[0];
172 unsigned i = 0;
173 unsigned tstress = 0;
174 unsigned ntstress = 0;
175 slope_t stress_s;
176 slope_t stress_e;
177 float top = 1.1 * def_pars.F0hz10;
178 int j;
179 pars = def_pars;
180 pars.FNPhz = le->p[fn].stdy;
181 pars.B1phz = pars.B1hz = 60;
182 pars.B2phz = pars.B2hz = 90;
183 pars.B3phz = pars.B3hz = 150;
184 #if 0
185 pars.F4hz = 3500;
186 #endif
187 pars.B4phz = def_pars.B4phz;
188
189 /* flag new utterance */
190 parwave_init(&klatt_global);
191
192 /* Set stress attack/decay slope */
193 stress_s.t = 40;
194 stress_e.t = 40;
195 stress_e.v = 0.0;
196
197 for (j = 0; j < nEparm; j++)
198 {
199 flt[j].v = le->p[j].stdy;
200 flt[j].a = frac;
201 flt[j].b = (float) 1.0 - (float) frac;
202 }
203 while (i < nelm)
204 {
205 Elm_ptr ce = &Elements[elm[i++]];
206 unsigned dur = elm[i++];
207 i++; /* skip stress */
208 /* Skip zero length elements which are only there to affect
209 boundary values of adjacent elements
210 */
211 if (dur > 0)
212 {
213 Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
214 slope_t start[nEparm];
215 slope_t end[nEparm];
216 unsigned t;
217
218 if (ce->rk > le->rk)
219 {
220 if (par_file)
221 fprintf(par_file, "# %s < %s\n", le->name, ce->name);
222 set_trans(start, ce, le, 0, 's');
223 /* we dominate last */
224 }
225 else
226 {
227 if (par_file)
228 fprintf(par_file, "# %s >= %s\n", le->name, ce->name);
229 set_trans(start, le, ce, 1, 's');
230 /* last dominates us */
231 }
232
233 if (ne->rk > ce->rk)
234 {
235 if (par_file)
236 fprintf(par_file, "# %s < %s\n", ce->name, ne->name);
237 set_trans(end, ne, ce, 1, 'e');
238 /* next dominates us */
239 }
240 else
241 {
242 if (par_file)
243 fprintf(par_file, "# %s >= %s\n", ce->name, ne->name);
244 set_trans(end, ce, ne, 0, 'e');
245 /* we dominate next */
246 }
247
248 if (par_file)
249 {
250 int j;
251 fprintf(par_file, "# %s\n", ce->name);
252 for (j = 0; j < nEparm; j++)
253 fprintf(par_file, "%c%6s", (j) ? ' ' : '#', Ep_name[j]);
254 fprintf(par_file, "\n");
255 for (j = 0; j < nEparm; j++)
256 fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', start[j].v);
257 fprintf(par_file, "\n");
258 for (j = 0; j < nEparm; j++)
259 fprintf(par_file, "%c%6d", (j) ? ' ' : '#', start[j].t);
260 fprintf(par_file, "\n");
261 }
262
263 for (t = 0; t < dur; t++, tstress++)
264 {
265 float base = top * 0.8 /* 3 * top / 5 */;
266 float tp[nEparm];
267 int j;
268
269 if (tstress == ntstress)
270 {
271 unsigned j = i;
272 stress_s = stress_e;
273 tstress = 0;
274 ntstress = dur;
275 #ifdef DEBUG_STRESS
276 printf("Stress %g -> ", stress_s.v);
277 #endif
278 while (j <= nelm)
279 {
280 Elm_ptr e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
281 unsigned du = (j < nelm) ? elm[j++] : 0;
282 unsigned s = (j < nelm) ? elm[j++] : 3;
283 if (s || e->feat & vwl)
284 {
285 unsigned d = 0;
286 if (s)
287 stress_e.v = (float) s / 3;
288 else
289 stress_e.v = (float) 0.1;
290 do
291 {
292 d += du;
293 #ifdef DEBUG_STRESS
294 printf("%s", (e && e->dict) ? e->dict : "");
295 #endif
296 e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
297 du = elm[j++];
298 }
299 while ((e->feat & vwl) && elm[j++] == s);
300 ntstress += d / 2;
301 break;
302 }
303 ntstress += du;
304 }
305 #ifdef DEBUG_STRESS
306 printf(" %g @ %d\n", stress_e.v, ntstress);
307 #endif
308 }
309
310 for (j = 0; j < nEparm; j++)
311 tp[j] = filter(flt + j, interpolate(ce->name, Ep_name[j], &start[j], &end[j], (float) ce->p[j].stdy, t, dur));
312
313 /* Now call the synth for each frame */
314
315 pars.F0hz10 = base + (top - base) *
316 interpolate("", "f0", &stress_s, &stress_e, (float) 0, tstress, ntstress);
317
318 pars.AVdb = pars.AVpdb = tp[av];
319 pars.AF = tp[af];
320 pars.FNZhz = tp[fn];
321 pars.ASP = tp[asp];
322 pars.Aturb = tp[avc];
323 pars.B1phz = pars.B1hz = tp[b1];
324 pars.B2phz = pars.B2hz = tp[b2];
325 pars.B3phz = pars.B3hz = tp[b3];
326 pars.F1hz = tp[f1];
327 pars.F2hz = tp[f2];
328 pars.F3hz = tp[f3];
329 /* AMP_ADJ + is a bodge to get amplitudes up to klatt-compatible levels
330 Needs to be fixed properly in tables
331 */
332 /*
333 pars.ANP = AMP_ADJ + tp[an];
334 */
335 pars.AB = AMP_ADJ + tp[ab];
336 pars.A5 = AMP_ADJ + tp[a5];
337 pars.A6 = AMP_ADJ + tp[a6];
338 pars.A1 = AMP_ADJ + tp[a1];
339 pars.A2 = AMP_ADJ + tp[a2];
340 pars.A3 = AMP_ADJ + tp[a3];
341 pars.A4 = AMP_ADJ + tp[a4];
342
343 parwave(&klatt_global, &pars, samp);
344
345 samp += klatt_global.nspfr;
346 if (par_file)
347 {
348 for (j = 0; j < nEparm; j++)
349 fprintf(par_file, " %6.4g", tp[j]);
350 fprintf(par_file, "\n");
351 }
352 if (jsru_file)
353 jsru_save(pars.F0hz10 * 0.1, tp);
354 /* Declination of f0 envelope 0.25Hz / cS */
355 top -= 0.5;
356 }
357 if (par_file)
358 {
359 int j;
360 for (j = 0; j < nEparm; j++)
361 fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', end[j].v);
362 fprintf(par_file, "\n");
363 for (j = 0; j < nEparm; j++)
364 fprintf(par_file, "%c%6d", (j) ? ' ' : '#', end[j].t);
365 fprintf(par_file, "\n");
366 }
367 }
368 le = ce;
369 }
370 return (samp - samp_base);
371 }
372
373 int
init_holmes(argc,argv)374 init_holmes(argc, argv)
375 int argc;
376 char *argv[];
377 {
378 char *par_name = NULL;
379 char *jsru_name = NULL;
380 argc = getargs("Holmes",argc, argv,
381 "p", "", &par_name, "Parameter file for plot",
382 "j", "", &jsru_name, "Data for alternate synth (JSRU)",
383 "S", "%d", &speed, "Speed (1.0 is 'normal')",
384 "K", "%lg", &frac, "Parameter filter 'fraction'",
385 NULL);
386 if (help_only)
387 return argc;
388 if (par_name)
389 {
390 par_file = fopen(par_name, "w");
391 if (!par_file)
392 perror(par_name);
393 }
394 if (jsru_name)
395 {
396 jsru_file = fopen(jsru_name, "w");
397 if (!jsru_file)
398 perror(jsru_name);
399 }
400 return argc;
401 }
402
403 void
term_holmes()404 term_holmes()
405 {
406 if (par_file)
407 fclose(par_file);
408 if (jsru_file)
409 fclose(jsru_file);
410 }
411
412 static int jsru_freq PROTO((Float f, Float base, Float inc));
413 static int
jsru_freq(f,base,inc)414 jsru_freq(f, base, inc)
415 Float f;
416 Float base;
417 Float inc;
418 {
419 int i;
420 f = (f - base) / inc;
421 i = (int) f;
422 if (i >= 64)
423 i = 63;
424 return i;
425 }
426
427 static int jsru_amp PROTO((Float a));
428 static int
jsru_amp(a)429 jsru_amp(a)
430 Float a;
431 {
432 int i = a;
433 if (i <= 0)
434 i = 1;
435 if (i >= 64)
436 i = 63;
437 return i;
438 }
439
440
441 /* 0 1 2 3 4 5
442 F1 F2 F3 FN
443 flflim 125.0 550.0 1350.0 3500.0 3500.0 95.0
444 fincrm 25.0 50.0 50.0 0.0 0.0 5.0
445 */
446
447 static void
jsru_save(f0,tp)448 jsru_save(f0, tp)
449 double f0;
450 float *tp;
451 {
452 f0 = 16 * (log(f0 / 25.0) / log(2.0)) - 1;
453
454 /* fn, alf, f1, a1, f2, a2, f3, a3, ahf, v, f0, m */
455 fputc(jsru_freq(tp[fn], 95.0, 5.0), jsru_file);
456 fputc(jsru_amp(tp[an]), jsru_file);
457 fputc(jsru_freq(tp[f1], 125.0, 25.0), jsru_file);
458 fputc(jsru_amp(tp[a1]), jsru_file);
459 fputc(jsru_freq(tp[f2], 550.0, 50.0), jsru_file);
460 fputc(jsru_amp(tp[a2]), jsru_file);
461 fputc(jsru_freq(tp[f3], 1350.0, 50.0), jsru_file);
462 fputc(jsru_amp(tp[a3]), jsru_file);
463 fputc(jsru_amp(tp[a4]), jsru_file);
464 fputc(jsru_amp(tp[av]), jsru_file);
465 fputc((int) f0, jsru_file);
466 fputc((int) 32, jsru_file);
467 }
468