static int ifd_syl_boundary(const cst_item *i,const cst_val *v) { /* Returns TRUE if this should be a syllable boundary */ /* This is of course phone set dependent */ int p, n, nn; if (v == NULL) return TRUE; else if (ifd_is_silence(val_string(val_car(v)))) return TRUE; else if (!ifd_has_vowel_in_list(v)) /* no more vowels so rest *all* coda */ return FALSE; else if (!ifd_has_vowel_in_syl(i)) /* need a vowel */ return FALSE; else if (ifd_is_vowel(val_string(val_car(v)))) return TRUE; else if (val_cdr(v) == NULL) return FALSE; else { /* so there is following vowel, and multiple phones left */ p = ifd_sonority(item_feat_string(i,"name")); n = ifd_sonority(val_string(val_car(v))); nn = ifd_sonority(val_string(val_car(val_cdr(v)))); if ((p <= n) && (n <= nn)) return TRUE; else return FALSE; } }
cst_val *lts_apply_val(const cst_val *wlist,const char *feats,const cst_lts_rules *r) { /* for symbol to symbol mapping */ const cst_val *v; cst_val *p; char *word; int i,j; word = cst_alloc(char,val_length(wlist)+1); for (v=wlist,i=0; v; v=val_cdr(v),i++) { for (j=0; r->letter_table[j]; j++) if (cst_streq(val_string(val_car(v)),r->letter_table[j])) { word[i] = j; break; } if (!r->letter_table[j]) { #if 0 printf("awb_debug unknown letter >%s<\n",val_string(val_car(v))); #endif i--; /* can't find this letter so skip it */ } } p = lts_apply(word,feats,r); cst_free(word); return p; }
int main(int argc, char **argv) { cst_wave *nw, *all; cst_val *files; const cst_val *w; cst_val *wavelist; cst_features *args; int i,j; float ntime; int stime; const char *nwfile; args = new_features(); files = cst_args(argv,argc, "usage: combine_waves OPTIONS\n" "Combine waves into single waveform\n" "-o <string> Output waveform\n" "-f <int> Input sample rate (for raw input)\n" "-itype <string> Input type, raw or headered\n" "-wavelist <string> File containing times and wave filenames\n", args); wavelist = get_wavelist(get_param_string(args,"-wavelist","-")); if (wavelist == 0) return -1; all = new_wave(); for (w = wavelist; w; w = val_cdr(w)) { ntime = decode_time(val_string(val_car(w))); nwfile = val_string(val_car(val_cdr(w))); nw = new_wave(); if (cst_wave_load_riff(nw,nwfile) != CST_OK_FORMAT) { fprintf(stderr, "combine_waves: can't read file or wrong format \"%s\"\n", nwfile); continue; } stime = ntime * nw->sample_rate; cst_wave_resize(all,stime+nw->num_samples,1); for (i=0,j=stime; i<nw->num_samples; i++,j++) { /* this will cause overflows */ all->samples[j] += nw->samples[i]; } delete_wave(nw); } cst_wave_save_riff(all,get_param_string(args,"-o","-")); return 0; }
int cmu_grapheme_syl_boundary(const cst_item *i,const cst_val *rest) { if (!rest) return TRUE; else if (!cmu_grapheme_contains_vowel(rest)) return FALSE; else if (!cmu_grapheme_has_vowel_in_syl(i)) return FALSE; #if 0 else if (rest && val_cdr(rest) && cst_streq("n",val_string(val_car(rest))) && !cmu_grapheme_is_vowel(val_string(val_car(rest)))) return FALSE; else if (rest && val_cdr(rest) && cmu_grapheme_is_vowel(ffeature_string(i,"name")) && !cmu_grapheme_is_vowel(val_string(val_car(rest))) && !cmu_grapheme_is_vowel(val_string(val_car(val_cdr(rest))))) return FALSE; else if (rest && val_cdr(rest) && val_cdr(val_cdr(rest)) && !cmu_grapheme_is_vowel(val_string(val_car(rest))) && !cmu_grapheme_is_vowel(val_string(val_car(val_cdr(rest)))) && !cmu_grapheme_is_vowel(val_string(val_car(val_cdr(val_cdr(rest)))))) return FALSE; else if (rest && val_cdr(rest) && (cst_streq(val_string(val_car(rest)), val_string(val_car(val_cdr(rest)))))) return FALSE; #endif else return TRUE; }
const cst_val *val_assoc_string(const char *v1,const cst_val *al) { const cst_val *i; for (i=al; i; i=val_cdr(i)) { if (cst_streq(v1,val_string(val_car(val_car(i))))) return val_car(i); } return 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 context_match(const cst_val *PATTERN, const cst_val *STRING, const cst_val *sets) { if (!PATTERN) return TRUE; else if (!STRING) return FALSE; else if (val_cdr(PATTERN) && (cst_streq("*",val_string(val_car(PATTERN))))) return context_match(val_cdr(val_cdr(PATTERN)),STRING,sets) || /* skip */ context_match(val_cdr(PATTERN),STRING,sets) || /* last match */ (item_match(val_car(val_cdr(PATTERN)),val_car(STRING),sets) && context_match(val_cdr(val_cdr(PATTERN)), /* loop match */ val_cdr(STRING),sets)); #if 0 else if (val_cdr(PATTERN) && (cst_streq("+",val_string(val_car(PATTERN))))) return context_match(val_cdr(PATTERN),STRING,sets) || /* last match */ (item_match(val_car(val_cdr(PATTERN)),val_car(STRING),sets) && context_match(val_cdr(val_cdr(PATTERN)), /* loop match */ val_cdr(STRING),sets)); #endif else if (item_match(val_car(PATTERN),val_car(STRING),sets)) return context_match(val_cdr(PATTERN),val_cdr(STRING),sets); else return FALSE; }
cst_val *en_exp_ordinal(const char *rawnumstring) { /* return ordinal for digit string */ cst_val *card, *o; const cst_val *t; const char *l; const char *ord; char *numstring; int i,j; numstring = cst_strdup(rawnumstring); for (j=i=0; i < cst_strlen(rawnumstring); i++) if (rawnumstring[i] != ',') { numstring[j] = rawnumstring[i]; j++; } numstring[j] = '\0'; card = val_reverse(en_exp_number(numstring)); cst_free(numstring); l = val_string(val_car(card)); ord = 0; for (i=0; i<10; i++) if (cst_streq(l,digit2num[i])) ord = ord2num[i]; if (!ord) for (i=0; i<10; i++) if (cst_streq(l,digit2teen[i])) ord = ord2teen[i]; if (!ord) for (i=0; i<10; i++) if (cst_streq(l,digit2enty[i])) ord = ord2enty[i]; if (cst_streq(l,"hundred")) ord = "hundredth"; if (cst_streq(l,"thousand")) ord = "thousandth"; if (cst_streq(l,"billion")) ord = "billtionth"; if (!ord) /* dunno, so don't convert anything */ return card; o = cons_val(string_val(ord),0); for (t=val_cdr(card); t; t=val_cdr(t)) o = cons_val(val_car(t),o); delete_val(card); return o; }
static int WordSylSeg(cst_utterance *u) { cst_item *word; cst_relation *sylstructure,*seg,*syl; cst_val *phones; const cst_val *p; cst_item *ssword,*segitem; syl = utt_relation_create(u,"Syllable"); sylstructure = utt_relation_create(u,"SylStructure"); seg = utt_relation_create(u,"Segment"); for (word=relation_head(utt_relation(u,"Word")); word; word=item_next(word)) { printf("word: %s\n",item_feat_string(word,"name")); ssword = relation_append(sylstructure,word); phones = lex_lookup((cst_lexicon *)&cmu_lex,item_feat_string(word,"name"),0); for (p=phones; p; p=val_cdr(p)) { segitem = relation_append(seg,NULL); item_set(segitem,"name",val_car(p)); printf("seg: %s\n",item_feat_string(segitem,"name")); item_add_daughter(ssword,segitem); } delete_val_list(phones); } return TRUE; }
void val_print(cst_file fd,const cst_val *v) { const cst_val *p; if (v == NULL) cst_fprintf(fd,"[null]"); else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT) cst_fprintf(fd,"%d",val_int(v)); else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT) cst_fprintf(fd,"%f",val_float(v)); else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING) cst_fprintf(fd,"%s",val_string(v)); else if (cst_val_consp(v)) { cst_fprintf(fd,"("); for (p=v; p; ) { val_print(fd,val_car(p)); p=val_cdr(p); if (p) cst_fprintf(fd," "); } cst_fprintf(fd,")"); } else cst_fprintf(fd,"[Val %s 0x%p]", cst_val_defs[CST_VAL_TYPE(v)/2].name,CST_VAL_VOID(v)); }
static const cst_val *find_rewrite_rule(const cst_val *LC, const cst_val *RC, const cst_lts_rewrites *r) { /* Search through rewrite rules to find matching one */ const cst_val *i, *RLC, *RA, *RRC; for (i=r->rules; i; i=val_cdr(i)) { /* val_print(stdout, val_car(i)); printf("\n"); */ RLC = val_car(val_car(i)); RA = val_car(val_cdr(val_car(i))); RRC = val_car(val_cdr(val_cdr(val_car(i)))); if (rule_matches(LC,RC,RLC,RA,RRC,r->sets)) return val_car(i); } fprintf(stderr,"LTS_REWRITES: unable to find a matching rules for:\n"); fprintf(stderr,"CL: "); val_print(stderr,LC); fprintf(stderr,"\n"); fprintf(stderr,"RC: "); val_print(stderr,RC); fprintf(stderr,"\n"); return NULL; }
static int ifd_has_vowel_in_list(const cst_val *v) { const cst_val *t; for (t=v; t; t=val_cdr(t)) if (ifd_is_vowel(val_string(val_car(v)))) return TRUE; 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)); }
int val_member_string(const char *v1,const cst_val *l) { const cst_val *i; for (i=l; i; i=val_cdr(i)) { if (cst_streq(v1,val_string(val_car(i)))) return TRUE; } return FALSE; }
int val_member(const cst_val *v1,const cst_val *l) { const cst_val *i; for (i=l; i; i=val_cdr(i)) { if (val_equal(val_car(i),v1)) return TRUE; } return FALSE; }
cst_voice *flite_voice_select(const char *name) { const cst_val *v; cst_voice *voice; if (flite_voice_list == NULL) return NULL; /* oops, not good */ if (name == NULL) return val_voice(val_car(flite_voice_list)); for (v=flite_voice_list; v; v=val_cdr(v)) { voice = val_voice(val_car(v)); if (cst_streq(name,voice->name)) return voice; } return flite_voice_select(NULL); }
static int cmu_grapheme_contains_vowel(const cst_val *r) { const cst_val *x; for (x=r; x; x=val_cdr(x)) { if (cmu_grapheme_is_vowel(val_string(val_car(x)))) return TRUE; } return FALSE; }
cst_val *cmu_grapheme_lex_lts_function(const struct lexicon_struct *l, const char *word, const char *pos, const cst_features *feats) { cst_val *phones = 0; cst_val *utflets = 0; const cst_val *v; char ord[10]; int i,phindex; /* string to utf8 chars */ utflets = cst_utf8_explode(word); for (v=utflets; v; v=val_cdr(v)) { /* We will add the found phones in reverse order and reverse then */ /* afterwards */ cst_utf8_as_hex(val_string(val_car(v)),ord); phindex = cst_find_u2sampa(ord); if (phindex < 0) printf("awb_debug no sampa %s %s\n",val_string(val_car(v)),ord); for (i=4; (phindex>=0) && (i>0); i--) { if (unicode_sampa_mapping[phindex][i]) phones = cons_val(string_val(unicode_sampa_mapping[phindex][i]), phones); } } phones = val_reverse(phones); #if 1 printf("cmu_grapheme_lex.c: word \"%s\" ",word); val_print(stdout,phones); printf("\n"); #endif delete_val(utflets); return phones; }
static cst_val *add_lts_boundary_marks(const cst_val *l) { cst_val *l1; const cst_val *v; l1 = cons_val(string_val("#"),NULL); for (v=l;v;v=val_cdr(v)) { l1=cons_val(val_car(v),l1); } l1 = cons_val(string_val("#"),l1); l1 = val_reverse(l1); return l1; }
static int rule_matches(const cst_val *LC, const cst_val *RC, const cst_val *RLC, const cst_val *RA, const cst_val *RRC, const cst_val *sets) { const cst_val *rc, *ra; /* Check [ X ] bit */ for (rc=RC,ra=RA; ra; ra=val_cdr(ra),rc=val_cdr(rc)) { if (!rc) return FALSE; if (!cst_streq(val_string(val_car(ra)), val_string(val_car(rc)))) return FALSE; } /* Check LC bit: LC may have some limited regex stuff */ if (context_match(RLC,LC,sets) && context_match(RRC,rc,sets)) return TRUE; else return FALSE; }
cst_string *cst_implode(const cst_val *sl) { const cst_val *v; int l=0; char *s; for (v=sl; v; v=val_cdr(v)) { if (val_stringp(val_car(v))) l += cst_strlen(val_string(val_car(v))); } s = cst_alloc(cst_string,l+1); for (v=sl; v; v=val_cdr(v)) { if (val_stringp(val_car(v))) cst_sprintf(s,"%s%s",s,val_string(val_car(v))); } return s; }
int val_equal(const cst_val *v1, const cst_val *v2) { if (v1 == v2) return TRUE; /* its eq so its equal */ else if (v1 == 0) return FALSE; else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE(v2)) { if (cst_val_consp(v1)) return ((val_equal(val_car(v1),val_car(v2))) && (val_equal(val_cdr(v1),val_cdr(v2)))); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_INT) return (val_int(v1) == val_int(v2)); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_FLOAT) return (val_float(v1) == val_float(v2)); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_STRING) return (cst_streq(CST_VAL_STRING(v1),CST_VAL_STRING(v2))); else return CST_VAL_VOID(v1) == CST_VAL_VOID(v2); } else return FALSE; }
cst_val *lts_rewrites(const cst_val *itape, const cst_lts_rewrites *r) { /* Returns list of rewritten "letters" to "phones" by r */ cst_val *LC; const cst_val *RC, *i; const cst_val *rule; cst_val *otape; LC = cons_val(val_car(itape),NULL); RC = val_cdr(itape); otape = NULL; while (val_cdr(RC)) { rule = find_rewrite_rule(LC,RC,r); if (!rule) break; /* val_print(stdout,rule); printf("\n"); */ /* Shift itape head */ for (i=val_car(val_cdr(rule)); i; i=val_cdr(i)) { LC = cons_val(val_car(RC),LC); RC = val_cdr(RC); } /* Output things to otape */ for (i=val_car(val_cdr(val_cdr(val_cdr(rule)))); i; i=val_cdr(i)) otape = cons_val(val_car(i),otape); } delete_val_list(LC); return val_reverse(otape); }
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; } }
static int ru_syl_boundary(const cst_item *i,const cst_val *v) { const char *p; const char *n; const char *nn; if (v == NULL) return TRUE; n=val_string(val_car(v)); if (is_silence(n)) return TRUE; if (!has_vowel_in_list(v)) return FALSE; if (!has_vowel_in_syl(i)) return FALSE; if (is_vowel(n)) return TRUE; if (val_cdr(v) == NULL) return FALSE; p = item_feat_string(i,"name"); nn = val_string(val_car(val_cdr(v))); if(is_vowel(p)) { if(is_vowel(nn)) return TRUE; if(is_sonorant(n)&&!is_sonorant(nn)) return FALSE; if(is_j(n)) return FALSE; return TRUE; } if(is_sonorant(p)) return TRUE; if(is_j(p)) return TRUE; return FALSE; }
cst_utterance *default_textanalysis(cst_utterance *u) { cst_item *t,*word; cst_relation *word_rel; cst_val *words; const cst_val *w; const cst_val *ttwv; word_rel = utt_relation_create(u,"Word"); ttwv = feat_val(u->features, "tokentowords_func"); for (t=relation_head(utt_relation(u,"Token")); t; t=item_next(t)) { if (ttwv) words = (cst_val *)(*val_itemfunc(ttwv))(t); else words = default_tokentowords(t); for (w=words; w; w=val_cdr(w)) { word = item_add_daughter(t,NULL); if (cst_val_consp(val_car(w))) { /* Has extra features */ item_set_string(word,"name",val_string(val_car(val_car(w)))); feat_copy_into(val_features(val_cdr(val_car(w))), item_feats(word)); } else item_set_string(word,"name",val_string(val_car(w))); relation_append(word_rel,word); } delete_val(words); } return u; }
static void flite_voice_list_print(void) { cst_voice *voice; const cst_val *v; printf("Voices available: "); for (v=flite_voice_list; v; v=val_cdr(v)) { voice = val_voice(val_car(v)); printf("%s ",voice->name); } printf("\n"); return; }
char *ru_implode(const cst_val *l) { const cst_val *v; size_t n=1; char *s,*p; for(v=l;(v!=NULL);v=val_cdr(v)) { if(val_stringp(val_car(v))) n+=strlen(val_string(val_car(v))); } s=cst_alloc(char,n); p=s; for(v=l;(v!=NULL);v=val_cdr(v)) { if(val_stringp(val_car(v))) { n=strlen(val_string(val_car(v))); memcpy(p,val_string(val_car(v)),n); p+=n; } } *p='\0'; return s; }
static int item_match(const cst_val *PATT, const cst_val *THING, const cst_val *sets) { const cst_val *sss; if (cst_streq(val_string(PATT),val_string(THING))) return TRUE; for (sss=sets; sss; sss=val_cdr(sss)) { if (cst_streq(val_string(val_car(val_car(sss))),val_string(PATT))) { /* Its a set not a letter */ if (val_member_string(val_string(THING),val_cdr(val_car(sss)))) { return TRUE; } else { return FALSE; } } } return FALSE; }
cst_utterance *default_lexical_insertion(cst_utterance *u) { cst_item *word; cst_relation *sylstructure,*seg,*syl; cst_lexicon *lex; const cst_val *lex_addenda = NULL; const cst_val *p, *wp = NULL; char *phone_name; char *stress = "0"; const char *pos; cst_val *phones; cst_item *ssword, *sssyl, *segitem, *sylitem, *seg_in_syl; lex = val_lexicon(feat_val(u->features,"lexicon")); if (lex->lex_addenda) lex_addenda = lex->lex_addenda; syl = utt_relation_create(u,"Syllable"); sylstructure = utt_relation_create(u,"SylStructure"); seg = utt_relation_create(u,"Segment"); for (word=relation_head(utt_relation(u,"Word")); word; word=item_next(word)) { ssword = relation_append(sylstructure,word); pos = ffeature_string(word,"pos"); phones = NULL; wp = NULL; /* printf("awb_debug word %s pos %s gpos %s\n", item_feat_string(word,"name"), pos, ffeature_string(word,"gpos")); */ /* FIXME: need to make sure that textanalysis won't split tokens with explicit pronunciation (or that it will propagate such to words, then we can remove the path here) */ if (item_feat_present(item_parent(item_as(word, "Token")), "phones")) phones = (cst_val *) item_feat(item_parent(item_as(word, "Token")), "phones"); else { wp = val_assoc_string(item_feat_string(word, "name"),lex_addenda); if (wp) phones = (cst_val *)val_cdr(val_cdr(wp)); else phones = lex_lookup(lex,item_feat_string(word,"name"),pos); } for (sssyl=NULL,sylitem=NULL,p=phones; p; p=val_cdr(p)) { if (sylitem == NULL) { sylitem = relation_append(syl,NULL); sssyl = item_add_daughter(ssword,sylitem); stress = "0"; } segitem = relation_append(seg,NULL); phone_name = cst_strdup(val_string(val_car(p))); if (phone_name[cst_strlen(phone_name)-1] == '1') { stress = "1"; phone_name[cst_strlen(phone_name)-1] = '\0'; } else if (phone_name[cst_strlen(phone_name)-1] == '0') { stress = "0"; phone_name[cst_strlen(phone_name)-1] = '\0'; } item_set_string(segitem,"name",phone_name); seg_in_syl = item_add_daughter(sssyl,segitem); #if 0 printf("awb_debug ph %s\n",phone_name); #endif if ((lex->syl_boundary)(seg_in_syl,val_cdr(p))) { #if 0 printf("awb_debug SYL\n"); #endif sylitem = NULL; if (sssyl) item_set_string(sssyl,"stress",stress); } cst_free(phone_name); } if (!item_feat_present(item_parent(item_as(word, "Token")), "phones") && ! wp) delete_val(phones); } return u; }