| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- /*************************************************************************/
- /* */
- /* Language Technologies Institute */
- /* Carnegie Mellon University */
- /* 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. */
- /* */
- /* CARNEGIE MELLON UNIVERSITY 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 CARNEGIE MELLON UNIVERSITY 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: Alan W Black (awb@cs.cmu.edu) */
- /* Date: January 2001 */
- /*************************************************************************/
- /* */
- /* CMU Lexicon definition */
- /* */
- /*************************************************************************/
- #include "flite.h"
- #include "cmu_lex.h"
- extern const int cmu_lex_entry[];
- extern const unsigned char cmu_lex_data[];
- extern const int cmu_lex_num_entries;
- extern const int cmu_lex_num_bytes;
- extern const char * const cmu_lex_phone_table[54];
- extern const char * const cmu_lex_phones_huff_table[];
- extern const char * const cmu_lex_entries_huff_table[];
- static int cmu_is_vowel(const char *p);
- static int cmu_is_silence(const char *p);
- static int cmu_has_vowel_in_list(const cst_val *v);
- static int cmu_has_vowel_in_syl(const cst_item *i);
- static int cmu_sonority(const char *p);
- static const char * const addenda0[] = { "p,", NULL };
- static const char * const addenda1[] = { "p.", NULL };
- static const char * const addenda2[] = { "p(", NULL };
- static const char * const addenda3[] = { "p)", NULL };
- static const char * const addenda4[] = { "p[", NULL };
- static const char * const addenda5[] = { "p]", NULL };
- static const char * const addenda6[] = { "p{", NULL };
- static const char * const addenda7[] = { "p}", NULL };
- static const char * const addenda8[] = { "p:", NULL };
- static const char * const addenda9[] = { "p;", NULL };
- static const char * const addenda10[] = { "p?", NULL};
- static const char * const addenda11[] = { "p!", NULL };
- static const char * const addenda12[] = { "n@", "ae1", "t", NULL };
- static const char * const addenda13[] = { "n#", "hh", "ae1","sh", NULL };
- static const char * const addenda14[] = { "n$", "d", "aa1", "l", "er", NULL };
- static const char * const addenda15[] = { "n%", "p", "er", "s", "eh1", "n", "t", NULL };
- static const char * const addenda16[] = { "n^", "k", "eh1", "r", "eh1", "t", NULL };
- static const char * const addenda17[] = { "n&","ae1","m","p","er","s","ae1","n","d", NULL };
- static const char * const addenda18[] = { "n*","ae1","s","t","er","ih1","s","k",NULL };
- static const char * const addenda19[] = { "n|","b","aa1","r",NULL };
- static const char * const addenda20[] = { "n\\","b","ae1","k","s","l","ae1","sh",NULL };
- static const char * const addenda21[] = { "n=","iy1","k","w","ax","l","z",NULL};
- static const char * const addenda22[] = { "n+","p","l","ah1","s",NULL};
- static const char * const addenda23[] = { "n~","t","ih1","l","d","ax",NULL};
- static const char * const addenda24[] = { "p'",NULL};
- static const char * const addenda25[] = { "p`",NULL};
- static const char * const addenda26[] = { "p\"",NULL};
- static const char * const addenda27[] = { "p-",NULL};
- static const char * const addenda28[] = { "p<",NULL};
- static const char * const addenda29[] = { "p>",NULL};
- static const char * const addenda30[] = { "n_","ah1","n","d","er","s","k","ao1","r",NULL};
- static const char * const addenda31[] = { "s's","z",NULL};
- static const char * const addenda32[] = { "nim","ay1","m",NULL};
- static const char * const addenda33[] = { "vdoesnt","d","ah1","z","n","t",NULL};
- static const char * const addenda34[] = { "vyoull","y","uw1","l",NULL};
- static const char * const addenda35[] = { "n/","s","l","ae1","sh",NULL};
- static const char * const addenda36[] = { "nin","ih","n",NULL};
- static const char * const addenda37[] = { "nto","t","ax",NULL};
- static const char * const addenda38[] = { "0_a","ey",NULL};
- static const char * const addenda39[] = { "vhavent","hh","ae1","v","ax","n","t",NULL};
- static const char * const addenda40[] = { "nemail","iy1","m","ey1","l",NULL};
- static const char * const addenda41[] = { "nshit","sh","ih1","t",NULL};
- static const char * const * const addenda[] = {
- addenda0,
- addenda1,
- addenda2,
- addenda3,
- addenda4,
- addenda5,
- addenda6,
- addenda7,
- addenda8,
- addenda9,
- addenda10,
- addenda11,
- addenda12,
- addenda13,
- addenda14,
- addenda15,
- addenda16,
- addenda17,
- addenda18,
- addenda19,
- addenda20,
- addenda21,
- addenda22,
- addenda23,
- addenda24,
- addenda25,
- addenda26,
- addenda27,
- addenda28,
- addenda29,
- addenda30,
- addenda31,
- addenda32,
- addenda33,
- addenda34,
- addenda35,
- addenda36,
- addenda37,
- addenda38,
- addenda39,
- addenda40,
- addenda41,
- NULL };
- static int cmu_is_silence(const char *p)
- {
- if (cst_streq(p,"pau"))
- return TRUE;
- else
- return FALSE;
- }
- static int cmu_has_vowel_in_list(const cst_val *v)
- {
- const cst_val *t;
- for (t=v; t; t=val_cdr(t))
- if (cmu_is_vowel(val_string(val_car(t))))
- return TRUE;
- return FALSE;
- }
- static int cmu_has_vowel_in_syl(const cst_item *i)
- {
- const cst_item *n;
- for (n=i; n; n=item_prev(n))
- if (cmu_is_vowel(item_feat_string(n,"name")))
- return TRUE;
- return FALSE;
- }
- static int cmu_is_vowel(const char *p)
- {
- /* this happens to work for US English phoneset */
- if (strchr("aeiou",p[0]) == NULL)
- return FALSE;
- else
- return TRUE;
- }
- static int cmu_sonority(const char *p)
- {
- /* A bunch of hacks for US English phoneset */
- if (cmu_is_vowel(p) || (cmu_is_silence(p)))
- return 5;
- else if (strchr("wylr",p[0]) != NULL)
- return 4; /* glides/liquids */
- else if (strchr("nm",p[0]) != NULL)
- return 3; /* nasals */
- else if (strchr("bdgjlmnnnrvwyz",p[0]) != NULL)
- return 2; /* voiced obstruents */
- else
- return 1;
- }
- int cmu_syl_boundary(const cst_item *i,const cst_val *rest)
- {
- /* Returns TRUE if this should be a syllable boundary */
- /* This is of course phone set dependent */
- int p, n, nn;
- if (rest == NULL)
- return TRUE;
- else if (cmu_is_silence(val_string(val_car(rest))))
- return TRUE;
- else if (!cmu_has_vowel_in_list(rest)) /* no more vowels so rest *all* coda */
- return FALSE;
- else if (!cmu_has_vowel_in_syl(i)) /* need a vowel */
- return FALSE;
- else if (cmu_is_vowel(val_string(val_car(rest))))
- return TRUE;
- else if (val_cdr(rest) == NULL)
- return FALSE;
- else
- { /* so there is following vowel, and multiple phones left */
- p = cmu_sonority(item_feat_string(i,"name"));
- n = cmu_sonority(val_string(val_car(rest)));
- nn = cmu_sonority(val_string(val_car(val_cdr(rest))));
- if ((p <= n) && (n <= nn))
- return TRUE;
- else
- return FALSE;
- }
- }
- static int cmulex_dist_to_vowel(const cst_val *rest)
- {
- if (rest == 0)
- return 0; /* shouldn't get here */
- else if (cmu_is_vowel(val_string(val_car(rest))))
- return 0;
- else
- return 1+cmulex_dist_to_vowel(val_cdr(rest));
- }
- static const char * const cmulex_onset_trigrams[] = {
- "str", "spy", "spr", "spl", "sky", "skw", "skr", "skl", NULL
- };
- static const char * const cmulex_onset_bigrams[] = {
- "zw", "zl",
- "vy", "vr", "vl",
- "thw", "thr",
- "ty", "tw",
- "tr", /* "ts", */
- "shw", "shr", "shn", "shm", "shl",
- "sw", "sv", "st", "sr", "sp", "sn", "sm", "sl", "sk", "sf",
- "py", "pw", "pr", "pl",
- "ny",
- "my", "mr",
- "ly",
- "ky", "kw", "kr", "kl",
- "hhy", "hhw", "hhr", "hhl",
- "gy", "gw", "gr", "gl",
- "fy", "fr", "fl",
- "dy", "dw", "dr",
- "by", "bw", "br", "bl",
- NULL
- };
- static int cmulex_onset_bigram(const cst_val *rest)
- {
- char x[10];
- int i;
- cst_sprintf(x,"%s%s",val_string(val_car(rest)),
- val_string(val_car(val_cdr(rest))));
- for (i=0; cmulex_onset_bigrams[i]; i++)
- if (cst_streq(x,cmulex_onset_bigrams[i]))
- return TRUE;
- return FALSE;
- }
- static int cmulex_onset_trigram(const cst_val *rest)
- {
- char x[15];
- int i;
- cst_sprintf(x,"%s%s%s",val_string(val_car(rest)),
- val_string(val_car(val_cdr(rest))),
- val_string(val_car(val_cdr(val_cdr(rest)))));
- for (i=0; cmulex_onset_trigrams[i]; i++)
- if (cst_streq(x,cmulex_onset_trigrams[i]))
- return TRUE;
- return FALSE;
- }
- int cmu_syl_boundary_mo(const cst_item *i,const cst_val *rest)
- {
- /* syl boundary maximal onset */
- int d2v;
- if (rest == NULL)
- return TRUE;
- else if (cmu_is_silence(val_string(val_car(rest))))
- return TRUE;
- else if (!cmu_has_vowel_in_list(rest))
- /* no more vowels so rest *all* coda */
- return FALSE;
- else if (!cmu_has_vowel_in_syl(i)) /* need a vowel */
- /* no vowel yet in syl so keep copying */
- return FALSE;
- else if (cmu_is_vowel(val_string(val_car(rest))))
- /* next is a vowel, syl has vowel, so this is a break */
- return TRUE;
- else if (cst_streq("ng",val_string(val_car(rest))))
- /* next is "ng" which can't start a word internal syl */
- return FALSE;
- else
- {
- /* want to know if from rest to the next vowel is a valid onset */
- d2v = cmulex_dist_to_vowel(rest);
- if (d2v < 2)
- return TRUE;
- else if (d2v > 3)
- return FALSE;
- else if (d2v == 2)
- return cmulex_onset_bigram(rest);
- else /* if (d2v == 3) */
- return cmulex_onset_trigram(rest);
- return TRUE;
- }
- }
- cst_lexicon cmu_lex;
- cst_lts_rules cmu_lts_rules;
- extern const char * const cmu_lts_phone_table[];
- extern const char * const cmu_lts_letter_table[];
- extern const cst_lts_addr cmu_lts_letter_index[];
- extern const cst_lts_model cmu_lts_model[];
- cst_lexicon *cmulex_init()
- {
- /* We actually need the init function match the directory name */
- return cmu_lex_init();
- }
- cst_lexicon *cmu_lex_init()
- {
- /* I'd like to do this as a const but it needs everything in this */
- /* file and already the bits are too big for some compilers */
-
- if (cmu_lts_rules.name)
- return &cmu_lex; /* Already initialized */
- cmu_lts_rules.name = "cmu";
- cmu_lts_rules.letter_index = cmu_lts_letter_index;
- #ifdef CST_NO_STATIC_LTS_MODEL
- /* cmu_lts_rules.models will be set elsewhere */
- #else
- cmu_lts_rules.models = cmu_lts_model;
- #endif
- cmu_lts_rules.phone_table = cmu_lts_phone_table;
- cmu_lts_rules.context_window_size = 4;
- cmu_lts_rules.context_extra_feats = 1;
- cmu_lts_rules.letter_table = 0 /* cmu_lts_letter_table */;
- cmu_lex.name = "cmu";
- cmu_lex.num_entries = cmu_lex_num_entries;
- #ifdef CST_NO_STATIC_LEX
- /* cmu_lex.data will be set elsewhere */
- #else
- /* as the data is const, we cast it through void * */
- cmu_lex.data = (unsigned char *)(void *)cmu_lex_data;
- #endif
- cmu_lex.num_bytes = cmu_lex_num_bytes;
- cmu_lex.phone_table = (char **) cmu_lex_phone_table;
- cmu_lex.syl_boundary = cmu_syl_boundary_mo;
- cmu_lex.addenda = (char ***) addenda;
- cmu_lex.lts_rule_set = (cst_lts_rules *) &cmu_lts_rules;
- cmu_lex.phone_hufftable = cmu_lex_phones_huff_table;
- cmu_lex.entry_hufftable = cmu_lex_entries_huff_table;
- cmu_lex.postlex = cmu_postlex;
- return &cmu_lex;
- }
|