192 lines
6.6 KiB
C
192 lines
6.6 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Cepstral, LLC */
|
|
/* Copyright (c) 2001 */
|
|
/* All Rights Reserved. */
|
|
/* */
|
|
/* Permission is hereby granted, free of charge, to use and distribute */
|
|
/* this software and its documentation without restriction, including */
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
/* distribute, sublicense, and/or sell copies of this work, and to */
|
|
/* permit persons to whom this work is furnished to do so, subject to */
|
|
/* the following conditions: */
|
|
/* 1. The code must retain the above copyright notice, this list of */
|
|
/* conditions and the following disclaimer. */
|
|
/* 2. Any modifications must be clearly marked as such. */
|
|
/* 3. Original authors' names are not deleted. */
|
|
/* 4. The authors' names are not used to endorse or promote products */
|
|
/* derived from this software without specific prior written */
|
|
/* permission. */
|
|
/* */
|
|
/* CEPSTRAL, LLC AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL */
|
|
/* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED */
|
|
/* WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL */
|
|
/* CEPSTRAL, LLC NOR THE CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, */
|
|
/* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER */
|
|
/* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION */
|
|
/* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR */
|
|
/* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
/* */
|
|
/*************************************************************************/
|
|
/* Author: David Huggins-Daines (dhd@cepstral.com) */
|
|
/* Date: December 2001 */
|
|
/*************************************************************************/
|
|
/* */
|
|
/* flite_sapi_usenglish.c: US English specific functions for Flite/SAPI */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
#include "flite_sapi_usenglish.h"
|
|
#include "cst_string.h"
|
|
|
|
static const char *sapi_usenglish_phones[] = {
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "pau", "1",
|
|
"2", "aa", "ae", "ah", "ao", "aw", "ax", "ay", "b",
|
|
"ch", "d", "dh", "eh", "er", "ey", "f", "g", "hh", "ih",
|
|
"iy", "jh", "k", "l", "m", "n", "ng", "ow", "oy", "p",
|
|
"r", "s", "sh", "t", "th", "uh", "uw", "v", "w", "y",
|
|
"z", "zh"
|
|
};
|
|
static const int sapi_usenglish_nphones = (sizeof(sapi_usenglish_phones)
|
|
/ sizeof(sapi_usenglish_phones[0]));
|
|
|
|
static const char *vis0[] = {"pau", NULL};
|
|
static const char *vis1[] = {"ae", "ax", "ah", NULL};
|
|
static const char *vis2[] = {"aa", NULL};
|
|
static const char *vis3[] = {"ao", NULL};
|
|
static const char *vis4[] = {"ey", "eh", "uh", NULL};
|
|
static const char *vis5[] = {"er", NULL};
|
|
static const char *vis6[] = {"y", "iy", "ih", NULL};
|
|
static const char *vis7[] = {"w", "uw", NULL};
|
|
static const char *vis8[] = {"ow", NULL};
|
|
static const char *vis9[] = {"aw", NULL};
|
|
static const char *vis10[] = {"oy", NULL};
|
|
static const char *vis11[] = {"ay", NULL};
|
|
static const char *vis12[] = {"hh", NULL};
|
|
static const char *vis13[] = {"r", NULL};
|
|
static const char *vis14[] = {"l", NULL};
|
|
static const char *vis15[] = {"s", "z", NULL};
|
|
static const char *vis16[] = {"sh", "ch", "jh", "zh", NULL};
|
|
static const char *vis17[] = {"th", "dh", NULL};
|
|
static const char *vis18[] = {"f", "v", NULL};
|
|
static const char *vis19[] = {"d", "t", "n", NULL};
|
|
static const char *vis20[] = {"k", "g", "ng", NULL};
|
|
static const char *vis21[] = {"p", "b", "m", NULL};
|
|
|
|
static const struct {
|
|
int vis;
|
|
const char *const *phones;
|
|
} sapi_usenglish_visemes[] = {
|
|
{ SP_VISEME_0, vis0 },
|
|
{ SP_VISEME_1, vis1 },
|
|
{ SP_VISEME_2, vis2 },
|
|
{ SP_VISEME_3, vis3 },
|
|
{ SP_VISEME_4, vis4 },
|
|
{ SP_VISEME_5, vis5 },
|
|
{ SP_VISEME_6, vis6 },
|
|
{ SP_VISEME_7, vis7 },
|
|
{ SP_VISEME_8, vis8 },
|
|
{ SP_VISEME_9, vis9 },
|
|
{ SP_VISEME_10, vis10 },
|
|
{ SP_VISEME_11, vis11 },
|
|
{ SP_VISEME_12, vis12 },
|
|
{ SP_VISEME_13, vis13 },
|
|
{ SP_VISEME_14, vis14 },
|
|
{ SP_VISEME_15, vis15 },
|
|
{ SP_VISEME_16, vis16 },
|
|
{ SP_VISEME_17, vis17 },
|
|
{ SP_VISEME_18, vis18 },
|
|
{ SP_VISEME_19, vis19 },
|
|
{ SP_VISEME_20, vis20 },
|
|
{ SP_VISEME_21, vis21 },
|
|
{ -1, NULL }
|
|
};
|
|
|
|
int
|
|
flite_sapi_usenglish_phoneme(cst_item *s)
|
|
{
|
|
const char *name;
|
|
int i;
|
|
|
|
if (s == NULL)
|
|
return 0;
|
|
|
|
name = item_name(s);
|
|
for (i = 0; i < sapi_usenglish_nphones; ++i)
|
|
if (sapi_usenglish_phones[i]
|
|
&& cst_streq(sapi_usenglish_phones[i], name))
|
|
break;
|
|
if (i == sapi_usenglish_nphones)
|
|
return 0;
|
|
return i;
|
|
}
|
|
|
|
int
|
|
flite_sapi_usenglish_viseme(cst_item *s)
|
|
{
|
|
const char *name;
|
|
int i;
|
|
|
|
/* FIXME: Is 0 a valid viseme or not? */
|
|
if (s == NULL)
|
|
return -1;
|
|
|
|
name = item_name(s);
|
|
for (i = 0; sapi_usenglish_visemes[i].phones; ++i)
|
|
if (cst_member_string(name, sapi_usenglish_visemes[i].phones))
|
|
break;
|
|
return sapi_usenglish_visemes[i].vis;
|
|
}
|
|
|
|
int
|
|
flite_sapi_usenglish_feature(cst_item *s)
|
|
{
|
|
int feat = 0;
|
|
|
|
if (s == NULL)
|
|
return 0;
|
|
|
|
if (ffeature_int(s, "R:SylStructure.parent.stress"))
|
|
feat |= SPVFEATURE_STRESSED;
|
|
if (ffeature_int(s, "R:SylStructure.parent.accented"))
|
|
feat |= SPVFEATURE_EMPHASIS;
|
|
|
|
return feat;
|
|
}
|
|
|
|
cst_val *
|
|
flite_sapi_usenglish_pronounce(SPPHONEID *pids)
|
|
{
|
|
SPPHONEID *p;
|
|
cst_val *phones = NULL;
|
|
|
|
for (p = pids; *p; ++p) {
|
|
const char *pname;
|
|
|
|
if (*p >= sapi_usenglish_nphones)
|
|
continue;
|
|
pname = sapi_usenglish_phones[*p];
|
|
if (pname == NULL)
|
|
continue;
|
|
if (isdigit(pname[0])) {
|
|
/* stress numbers */
|
|
if (phones) {
|
|
char *psname;
|
|
cst_val *car, *cdr;
|
|
|
|
car = (cst_val *) val_car(phones);
|
|
cdr = (cst_val *) val_cdr(phones);
|
|
psname = cst_alloc(char,
|
|
strlen(val_string(car))
|
|
+ strlen(pname) + 1);
|
|
sprintf(psname, "%s%s", val_string(car), pname);
|
|
phones = cons_val(string_val(psname), cdr);
|
|
cst_free(psname);
|
|
delete_val(car);
|
|
}
|
|
} else
|
|
phones = cons_val(string_val(pname), phones);
|
|
}
|
|
return val_reverse(phones);
|
|
}
|