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,
22
/* $Id: phtoelm.c,v 1.2 2006/06/12 14:12:52 stephena Exp $
24
char *phtoelm_id = "$Id: phtoelm.c,v 1.2 2006/06/12 14:12:52 stephena Exp $";
30
#include "useconfig.h"
36
trie_ptr phtoelm = NULL;
38
static Elm_ptr find_elm(char *s);
44
while (e < Elements + num_Elements) {
45
if (!strcmp(s, e->name)) {
63
while ((s = va_arg(ap, char *))) {
64
Elm_ptr e = find_elm(s);
66
*x++ = (e - Elements);
68
fprintf(stderr, "Cannot find %s for [%s]\n", s, p);
72
buf[0] = (x - buf) - 1;
73
x = (char *) malloc(buf[0] + 1);
74
memcpy(x, buf, buf[0] + 1);
75
trie_insert(&phtoelm, p, x);
81
#include "phtoelm.def"
85
enter_trans(char *trans, int verbose)
87
trie_ptr table = NULL;
88
FILE *f = fopen(trans, "r");
93
fprintf(stderr, "Reading %s\n", trans);
94
while ((s = fgets(buf, sizeof(buf), f))) {
97
while (isspace((unsigned) *s))
100
while (*s && !isspace((unsigned) *s))
102
while (isspace((unsigned) *s))
104
x = (char *) trie_lookup(&phtoelm, &s);
108
fprintf(stderr, "%s does not map (leaves %s)\n", p, s);
111
trie_insert(&table, p, x);
124
#define StressDur(e,s,l) ((e->ud + (e->du - e->ud) * s / 3)*speed)
126
#define StressDur(e,s,l) ((void)(s),(l ? e->du*speed : (e->du + e->ud)/2)*speed)
130
decline_f0(float F0Hz, darray_ptr f0, float f, unsigned t)
133
/* Magic constant - ugh */
135
/* Do not drop forever */
138
return darray_float(f0, f);
142
phone_to_elm(rsynth_t * rsynth, int n, char *phone, darray_ptr elm,
145
float F0Hz = rsynth->speaker->F0Hz;
146
float speed = rsynth->speed;
154
float f = darray_float(f0, F0Hz * 1.1F);
157
while (s < limit && *s) {
158
char *e = (char *) trie_lookup(&phtoelm, &s);
163
Elm_ptr p = &Elements[x];
164
darray_append(elm, x);
165
/* StressDur works because only vowels have ud != du,
166
and we set stress just before a vowel
168
t += darray_append(elm,
169
(int) (StressDur(p, stress, islong)));
173
else if (seen_vowel) {
181
case '\'': /* Primary stress */
183
case ',': /* Secondary stress */
185
case '+': /* Tertiary stress */
190
/* f0 has been declining since f0t */
191
f = decline_f0(F0Hz, f0, f, t - f0t);
193
/* Now stress pulse pushes f0 up "instantly" */
195
darray_float(f0, f + F0Hz * stress * 0.02);
197
case '-': /* hyphen in input */
199
case ':': /* Length mark */
203
fprintf(stderr, "Ignoring %c in '%.*s'\n", ch, n, phone);
208
/* Add final decline to f0 contour */
209
decline_f0(F0Hz, f0, f, t - f0t);
214
rsynth_phones(rsynth_t * rsynth, char *phone, int len)
219
darray_init(&elm, sizeof(char), len);
220
darray_init(&f0, sizeof(float), len);
221
if ((frames = phone_to_elm(rsynth, len, phone, &elm, &f0))) {
222
if (rsynth_verbose(rsynth))
223
fprintf(stderr, "[%.*s]\n", len, phone);
225
rsynth_interpolate(rsynth,
226
(unsigned char *) darray_find(&elm, 0),elm.items,
227
(float *) darray_find(&f0,0),
235
rsynth_pho(rsynth_t * rsynth, const char *path, int dodur, char *trans)
237
int verbose = rsynth_verbose(rsynth);
238
FILE *f = fopen(path, "r");
242
if (trans && *trans && strcmp(trans, "sampa"))
243
table = enter_trans(trans, verbose);
251
float f0a[1024] = { rsynth->speaker->F0Hz };
252
unsigned nf0 = 0; /* index of last f0 value */
253
unsigned f0t = 0; /* time of last f0 value */
254
darray_init(&elm, sizeof(char), 1024);
256
fprintf(stderr, "Frame is %.3gms\n",
257
rsynth->samples_frame * 1000.0 / rsynth->sr);
259
while ((s = fgets(buffer, sizeof(buffer), f))) {
260
/* skip leading space - should not be any but ... */
261
while (isspace((unsigned) *s))
263
if (*s && *s != ';') {
266
char *e = (char *) trie_lookup(&table, &s);
269
if (e && isspace((unsigned) *s)) {
274
double ms = strtod(s, &s);
276
ms * (rsynth->sr / rsynth->samples_frame) / 1000;
281
for (i = 0; i < n; i++) {
283
Elm_ptr p = &Elements[x];
284
if (!p->du || p->feat & stp)
291
/* Stops don't change length */
293
delta = frames - edur;
295
/* FIXME - revisit the rounding process */
298
"'%.*s' %gms %d elem %g frames vs %g nat d=%g) %d stops\n",
299
(pe - ps), ps, ms, n, frames, edur, delta,
302
for (i = 0; i < n; i++) {
304
Elm_ptr p = &Elements[x];
305
darray_append(&elm, x);
306
if (!p->du || p->feat & stp)
307
pt += darray_append(&elm, p->ud);
312
1) ? rint(delta * (p->ud -
318
"%s d=%d vs nstp=%g delta=%g take=%g\n",
319
p->name, p->ud, edur, delta,
327
(int) (p->ud + share));
330
pt += darray_append(&elm, p->du);
333
/* Now have elements entered and duration of phone computed */
334
if (verbose && dodur) {
336
1.0 * pt * rsynth->samples_frame / rsynth->sr *
338
if (fabs(got - ms) > 0.5) {
340
"'%.*s' want=%gms got=%.3g (%+3.0f%%)\n",
341
(pe - ps), ps, ms, got,
342
100 * (got - ms) / ms);
345
while (isspace((unsigned) *s))
348
float percent = strtod(s, &s);
349
float f0 = strtod(s, &s);
351
(unsigned) (t + (percent * pt / 100));
353
/* time has advanced */
354
f0a[++nf0] = (nt - f0t);
359
/* same time - change target inplace */
362
while (isspace((unsigned) *s))
368
fputs(buffer, stderr);
369
fprintf(stderr, "Unknown phone:%s", ps);
375
float f0 = f0a[nf0++];
377
f0a[nf0++] = t - f0t;
381
rsynth_interpolate(rsynth,
382
(unsigned char *) darray_find(&elm, 0),
383
elm.items, f0a, nf0));
392
rsynth_term(rsynth_t * rsynth)
395
rsynth_flush(rsynth, 0);
396
trie_free(&phtoelm, &free);
397
#ifdef DO_RANGE_CHECKS
398
fprintf(stderr, "Max range %g @ %s:%d\n", range_max, __FILE__,
401
if (rsynth->voice_file)
402
fclose(rsynth->voice_file);
403
if (rsynth->parm_file)
404
fclose(rsynth->parm_file);