2
Copyright (c) 1994,2001-2003 Nick Ing-Simmons. All rights reserved.
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Library General Public
6
License as published by the Free Software Foundation; either
7
version 2 of the License, or (at your option) any later version.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public
15
License along with this library; if not, write to the Free
16
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21
/* $Id: holmes.c,v 1.2 2006/06/12 14:12:52 stephena Exp $
23
char *holmes_id = "$Id: holmes.c,v 1.2 2006/06/12 14:12:52 stephena Exp $";
27
#include "useconfig.h"
33
float v; /* boundary value */
34
long t; /* transition time */
43
} filter_t, *filter_ptr;
46
filter(filter_ptr p, float v)
48
return p->v = (p->a * v + p->b * p->v);
51
/* 'a' is dominant element, 'b' is dominated
52
ext is flag to say to use external times from 'a' rather
53
than internal i.e. ext != 0 if 'a' is NOT current element.
58
set_trans(slope_t * t, int i, Elm_ptr a, Elm_ptr b, int ext, int e,
61
t[i].t = (long) (((ext) ? a->p[i].ed : a->p[i].id) * speed);
63
float afrac = a->p[i].prop * 0.01F;
64
t[i].v = a->p[i].stdy * (1.0F - afrac) + (afrac * b->p[i].stdy);
67
t[i].v = b->p[i].stdy;
78
---------------t---------------
82
linear(float a, float b, long t, long d)
89
float f = (float) t / (float) d;
90
return a + (b - a) * f;
95
interpolate(char *w, char *p, slope_t * s, slope_t * e, float mid, long t,
98
float steady = d - (s->t + e->t);
100
fprintf(stdout, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n",
101
w, p, s->v, s->t, e->v, e->t, mid, steady);
104
/* Value reaches stready state somewhere ... */
106
return linear(s->v, mid, t, s->t); /* initial transition */
110
return mid; /* steady state */
112
return linear(mid, e->v, (int) (t - steady), e->t);
113
/* final transition */
117
float f = (float) 1.0 - ((float) t / (float) d);
118
float sp = linear(s->v, mid, t, s->t);
119
float ep = linear(e->v, mid, d - t, e->t);
120
return f * sp + ((float) 1.0 - f) * ep;
124
#define CHECK_SPACING(a,b) \
127
fprintf(stdout,"%s=%g < %s=%g+200\n",#a,a,#b,b); \
132
rsynth_interpolate(rsynth_t * rsynth,
133
unsigned char *elm, unsigned nelm,
134
float *f0, unsigned nf0)
136
filter_t flt[nEparm];
138
Elm_ptr le = &Elements[0];
144
float f0s = rsynth->speaker->F0Hz;
147
float speed = rsynth->speed;
150
if (nf0 < 3 || !f0 || (rsynth->flags & RSYNTH_MONOTONE)) {
154
for (i = 0; i < nelm; i += 2) {
157
if ((rsynth->flags & RSYNTH_MONOTONE)) {
158
f0[0] = rsynth->speaker->F0Hz; /* top */
159
f0[2] = f0[0]; /* bottom */
162
f0[0] = 1.1 * rsynth->speaker->F0Hz; /* top */
163
f0[2] = 0.6 * f0[0]; /* bottom */
168
fprintf(stderr, "f0 (%g) %5.1f %gs %5.1f\n", rsynth->F0hz,
169
f0[0], 1.0 * f0[1] * rsynth->samples_frame / rsynth->samp_rate,
175
/* flag new utterance */
178
/* Experimental feature:
179
frac is the proporion of the new value that is fed into lowpass
180
filter. This is added to (1-frac) of old value.
181
So a value of 1.0 means no smoothing. A value of 0.5 seems ok
182
and tracks look smoother. Smoothing is insurance against
183
interpollation bugs and mis-features changing parameters too fast.
185
Revisit this with some theory...
187
for (j = 0; j < nEparm; j++) {
188
flt[j].v = le->p[j].stdy;
189
flt[j].a = rsynth->smooth;
190
flt[j].b = 1.0F - rsynth->smooth;
193
Elm_ptr ce = &Elements[elm[i++]];
194
unsigned dur = elm[i++];
195
if (rsynth->flags & RSYNTH_ETRACE) {
196
printf("%s.%ld ", ce->name,
197
1000 * dur * rsynth->samples_frame / rsynth->sr);
199
/* Skip zero length elements which are only there to affect
200
boundary values of adjacent elements.
201
Note this mainly refers to "QQ" element in fricatives
202
as stops have a non-zero length central element.
205
Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
206
slope_t start[nEparm];
211
for (i = 0; i < nEparm; i++) {
214
if (ce->p[i].rk > le->p[i].rk) {
215
if (rsynth->parm_file)
216
fprintf(rsynth->parm_file,
217
"# %3s %2s(%2d) < %2s(%2d)\n", Ep_name[i],
218
le->name, le->p[i].rk, ce->name,
220
set_trans(start, i, ce, le, 0, 's', speed);
221
/* we dominate last */
224
if (rsynth->parm_file)
225
fprintf(rsynth->parm_file,
226
"# %3s %2s(%2d) >= %2s(%2d)\n", Ep_name[i],
227
le->name, le->p[i].rk, ce->name,
229
set_trans(start, i, le, ce, 1, 's', speed);
230
/* last dominates us */
233
if (ne->p[i].rk > ce->p[i].rk) {
234
if (rsynth->parm_file)
235
fprintf(rsynth->parm_file,
236
"# %3s %2s(%2d) < %2s(%2d)\n", Ep_name[i],
237
ce->name, ce->p[i].rk, ne->name,
239
set_trans(end, i, ne, ce, 1, 'e', speed);
240
/* next dominates us */
243
if (rsynth->parm_file)
244
fprintf(rsynth->parm_file,
245
"# %3s %2s(%2d) >= %2s(%2d)\n", Ep_name[i],
246
ce->name, ce->p[i].rk, ne->name,
248
set_trans(end, i, ce, ne, 0, 'e', speed);
249
/* we dominate next */
254
if (rsynth->parm_file) {
256
fprintf(rsynth->parm_file, "# %s\n", ce->name);
257
fprintf(rsynth->parm_file, "%c%6s %6s", '#', "f0", "ao");
258
for (j = 0; j < nEparm; j++)
259
fprintf(rsynth->parm_file, "%c%6s", ' ', Ep_name[j]);
260
fprintf(rsynth->parm_file, "\n#%6s %6s", "", "");
261
for (j = 0; j < nEparm; j++)
262
fprintf(rsynth->parm_file, "%c%6.4g", ' ', start[j].v);
263
fprintf(rsynth->parm_file, "\n#%6s %6s", "", "");
264
for (j = 0; j < nEparm; j++)
265
fprintf(rsynth->parm_file, "%c%6ld", ' ', start[j].t);
266
fprintf(rsynth->parm_file, "\n");
269
for (t = 0; t < dur; t++, tf0++) {
273
for (j = 0; j < nEparm; j++) {
276
interpolate(ce->name, Ep_name[j], &start[j],
277
&end[j], (float) ce->p[j].stdy,
281
while (tf0 == ntf0) {
284
ntf0 = (unsigned) *f0++;
287
fprintf(stderr, "f0 %5.1f %gs %5.1f\n", f0s,
288
1.0 * ntf0 * samples_frame / samp_rate, f0e);
292
/* interpolate the f0 value */
293
F0Hz = linear(f0s, f0e, tf0, ntf0);
295
if (rsynth->flags & RSYNTH_F0TRACE) {
296
printf(" %5.1fHz", F0Hz);
299
/* Now call the synth for each frame */
300
CHECK_SPACING(ep[f2], ep[f1]);
301
CHECK_SPACING(ep[f3], ep[f2]);
302
CHECK_SPACING(rsynth->speaker->F4hz, ep[f3]);
304
samp += rsynth_frame(rsynth, F0Hz, ep, ce->name);
306
if (rsynth->parm_file) {
307
fprintf(rsynth->parm_file, " %6.4g %6.4g",
308
F0Hz, 10 * log10(peak));
309
for (j = 0; j < nEparm; j++)
310
fprintf(rsynth->parm_file, " %6.4g", ep[j]);
311
fprintf(rsynth->parm_file, "\n");
314
if (rsynth->parm_file) {
316
fprintf(rsynth->parm_file, "#%6s %6s", "", "");
317
for (j = 0; j < nEparm; j++)
318
fprintf(rsynth->parm_file, " %6.4g", end[j].v);
319
fprintf(rsynth->parm_file, "\n");
320
fprintf(rsynth->parm_file, "#%6s %6s", "", "");
321
for (j = 0; j < nEparm; j++)
322
fprintf(rsynth->parm_file, " %6ld", end[j].t);
323
fprintf(rsynth->parm_file, "\n");
328
if (rsynth->flags & (RSYNTH_ETRACE | RSYNTH_F0TRACE)) {