/* * Return the previous item in the queue for the item with the given item-id. * * @param queue The queue * @param item_id The id of the item in the queue * @param shuffle If 0 return the next item in the play-queue, if 1 the next item in the shuffle-queue * @param r_mode Repeat mode * @return The previous item */ struct queue_item * queue_prev(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode) { struct queue_item *item; item = queueitem_get_byitemid(queue, item_id); if (!item) // Item not found return NULL; if (r_mode == REPEAT_SONG && item != queue->head) return item; item = item_prev(item, shuffle); if (item == queue->head && r_mode == REPEAT_ALL) { // Repeat all and start of queue reached, return last item in the queue item = item_prev(queue->head, shuffle); } if (item == queue->head) return NULL; return item; }
cst_item *item_parent(const cst_item *i) { const cst_item *n; for (n=i; item_prev(n); n=item_prev(n)); if (n == NULL) return NULL; else return n->u; }
static const cst_val *segment_duration(const cst_item *seg) { const cst_item *s = item_as(seg,"Segment"); if (!s) return VAL_STRING_0; else if (item_prev(s) == NULL) return item_feat(s,"end"); else /* It should be okay to construct this as it will get dereferenced when the CART interpreter frees its feature cache. */ return float_val(item_feat_float(s,"end") - item_feat_float(item_prev(s),"end")); }
cst_utterance *default_phrasing(cst_utterance *u) { cst_relation *r; cst_item *w, *p, *lp=NULL; const cst_val *v; cst_cart *phrasing_cart; r = utt_relation_create(u,"Phrase"); phrasing_cart = val_cart(feat_val(u->features,"phrasing_cart")); for (p=NULL,w=relation_head(utt_relation(u,"Word")); w; w=item_next(w)) { if (p == NULL) { p = relation_append(r,NULL); lp = p; #ifdef FLITE_PLUS_HTS_ENGINE item_set_string(p,"name","BB"); #else item_set_string(p,"name","B"); #endif /* FLITE_PLUS_HTS_ENGINE */ } item_add_daughter(p,w); v = cart_interpret(w,phrasing_cart); if (cst_streq(val_string(v),"BB")) p = NULL; } if (lp && item_prev(lp)) /* follow festival */ item_set_string(lp,"name","BB"); return u; }
cst_utterance *default_pause_insertion(cst_utterance *u) { /* Add initial silences and silence at each phrase break */ const char *silence; const cst_item *w; cst_item *p, *s; silence = val_string(feat_val(u->features,"silence")); /* Insert initial silence */ s = relation_head(utt_relation(u,"Segment")); if (s == NULL) s = relation_append(utt_relation(u,"Segment"),NULL); else s = item_prepend(s,NULL); item_set_string(s,"name",silence); for (p=relation_head(utt_relation(u,"Phrase")); p; p=item_next(p)) { for (w = item_last_daughter(p); w; w=item_prev(w)) { s = path_to_item(w,"R:SylStructure.daughtern.daughtern.R:Segment"); if (s) { s = item_append(s,NULL); item_set_string(s,"name",silence); break; } } } return u; }
cst_utterance *russian_postlex_function(cst_utterance *u) { const cst_item *word,*seg; const char *answer,*name,*pair; for(word=relation_head(utt_relation(u,"Transcription"));word;word=item_next(word)) { if(item_feat_present(word,"no_pl")||item_feat_present(word,"no_vr")) continue; for(seg=item_daughter(word);seg;seg=item_next(seg)) { name=item_feat_string(seg,"name"); if(cst_member_string(name,unstressed_vowels)) { answer=val_string(cart_interpret(item_as(seg,"Segment"),&ru_vowel_reduction_cart)); if(!cst_streq(answer,"N")) item_set_string(seg,"name",answer); } else { if(cst_streq(name,"ii")&& cst_streq(ffeature_string(seg,"R:Segment.p.ph_csoft"),"-")&& !(cst_streq(item_feat_string(word,"name"),"и")&& cst_streq(ffeature_string(word,"gpos"),"content"))) { item_set_string(seg,"name","yy"); } } } } for(word=relation_tail(utt_relation(u,"Transcription"));word;word=item_prev(word)) { if(item_feat_present(word,"no_pl")) continue; for(seg=item_last_daughter(word);seg;seg=item_prev(seg)) { name=item_feat_string(seg,"name"); pair=russian_vpair(name); if(pair!=NULL) { answer=val_string(cart_interpret(item_as(seg,"Segment"),&ru_vpair_cart)); if(cst_streq(answer,"Y")) item_set_string(seg,"name",pair); } } } return u; }
static const cst_val *position_type(const cst_item *syl) { const cst_item *s = item_as(syl,"SylStructure"); if (s == 0) return (cst_val *)&val_string_single; else if (item_next(s) == 0) { if (item_prev(s) == 0) return (cst_val *)&val_string_single; else return (cst_val *)&val_string_final; } else if (item_prev(s) == 0) return (cst_val *)&val_string_initial; else return (cst_val *)&val_string_mid; }
static int ifd_has_vowel_in_syl(const cst_item *i) { const cst_item *n; for (n=i; n; n=item_prev(n)) if (ifd_is_vowel(item_feat_string(n,"name"))) return TRUE; return FALSE; }
static int cmu_grapheme_has_vowel_in_syl(const cst_item *i) { const cst_item *n; for (n=i; n; n=item_prev(n)) if (cmu_grapheme_is_vowel(ffeature_string(n,"name"))) return TRUE; return FALSE; }
static const cst_val *sub_phrases(const cst_item *syl) { const cst_item *s; int c; for (c=0,s=path_to_item(syl,"R:SylStructure.parent.R:Phrase.parent.p"); s && (c < CST_CONST_INT_MAX); s=item_prev(s),c++); return val_string_n(c); }
static const cst_val *pos_in_syl(const cst_item *seg) { const cst_item *s; int c; for (c=-1,s=item_as(seg,"SylStructure"); s; s=item_prev(s),c++); return val_string_n(c); }
static const cst_val *ssyl_in(const cst_item *syl) { /* Number of stressed syllables since last major break */ const cst_item *ss,*p,*fs; int c; ss = item_as(syl,"Syllable"); fs = path_to_item(syl,"R:SylStructure.parent.R:Phrase.parent.daughter.R:SylStructure.daughter"); /* This should actually include the first syllable, but Festival's doesn't. */ for (c=0, p=item_prev(ss); p && (!item_equal(p,fs)) && (c < CST_CONST_INT_MAX); p=item_prev(p)) { if (cst_streq("1",item_feat_string(p,"stress"))) c++; } return val_string_n(c); /* its used randomly as int and float */ }
static const cst_val *syl_codasize(const cst_item *syl) { cst_item *d; int c; for (c=0,d=item_last_daughter(item_as(syl,"SylStructure")); d; d=item_prev(d),c++) { if (cst_streq("+",val_string(ph_vc(d)))) break; } return val_string_n(c); }
static const cst_val *last_accent(const cst_item *syl) { const cst_item *s; int c; for (c=0,s=item_as(syl,"Syllable"); s && (c < CST_CONST_INT_MAX); s=item_prev(s),c++) { if (val_int(accented(s))) return val_string_n(c); } return val_string_n(c); }
static const cst_val *syl_in(const cst_item *syl) { /* Number of syllables since last major break */ const cst_item *ss,*p,*fs; int c; ss = item_as(syl,"Syllable"); fs = path_to_item(syl,"R:SylStructure.parent.R:Phrase.parent.daughter.R:SylStructure.daughter"); for (c=0, p=ss; p && (c < CST_CONST_INT_MAX); p=item_prev(p),c++) if (item_equal(p,fs)) break; return val_string_n(c); }
static const cst_val *seg_coda_ctype(const cst_item *seg, const char *ctype) { const cst_item *s; const cst_phoneset *ps = item_phoneset(seg); for (s=item_last_daughter(item_parent(item_as(seg,"SylStructure"))); s; s=item_prev(s)) { if (cst_streq("+",phone_feature_string(ps,item_feat_string(s,"name"), "vc"))) return VAL_STRING_0; if (cst_streq(ctype,phone_feature_string(ps,item_feat_string(s,"name"), "ctype"))) return VAL_STRING_1; } return VAL_STRING_0; }
static void apostrophe_s(cst_utterance *u) { cst_item *s; cst_item *schwa; const cst_phoneset *ps = u->vox->phoneset; const char *pname, *word; for (s=item_next(UTT_REL_HEAD(u,SEGMENT)); s; s=item_next(s)) { word = val_string(ffeature(s, "R:"SYLSTRUCTURE".P.P.name")); if (cst_streq("'s", word)) { pname = item_feat_string(item_prev(s),"name"); if ((strchr("fa",*phone_feature_string(ps,pname,"ctype")) != NULL) && (strchr("dbg", *phone_feature_string(ps,pname,"cplace")) == NULL)) /* needs a schwa */ { schwa = item_prepend(s,NULL); item_set_string(schwa,"name","ax"); item_prepend(item_as(s,SYLSTRUCTURE),schwa); } else if (cst_streq("-",phone_feature_string(ps,pname,"cvox"))) item_set_string(s,"name","s"); } else if (cst_streq("'ve", word) || cst_streq("'ll", word) || cst_streq("'d", word)) { if (cst_streq("-",ffeature_string(s,"p."PH_VC))) { schwa = item_prepend(s,NULL); item_set_string(schwa,"name","ax"); item_prepend(item_as(s,SYLSTRUCTURE),schwa); } } } }
static void assign_stress(cst_item *word) { int numsyls=ffeature_int(word,"word_numsyls"); const char *gpos=ffeature_string(word,"gpos"); const cst_item *word_in_phrase=item_as(word,"Phrase"); const cst_item *syls=item_as(word,"SylStructure"); const cst_item *syl=item_daughter(syls); const cst_item *transcription=item_as(word,"Transcription"); int stressed=FALSE; int n=item_feat_present(word,"stressed_syl_num")?item_feat_int(word,"stressed_syl_num"):0; const char *name=item_name(word); const char *pname=ffeature_string(word,"R:Phrase.p.name"); const char *nname=ffeature_string(word,"R:Phrase.n.name"); if(cst_streq(ffeature_string(word,"R:Token.p.name"),"по")&& (cst_streq(name,"моему")||cst_streq(name,"своему")||cst_streq(name,"твоему"))) { item_set_string(syl,"stress","1"); return; } else if((cst_streq(name,"не")||cst_streq(name,"ни"))&& (cst_streq(nname,"был")||cst_streq(nname,"были")||cst_streq(nname,"было"))) { item_set_string(syl,"stress","1"); return; } else if((cst_streq(name,"был")||cst_streq(name,"были")||cst_streq(name,"было"))&& (cst_streq(pname,"не")||cst_streq(pname,"ни"))) return; else if(cst_streq(gpos,"enc")&&item_prev(word_in_phrase)) return; else if(cst_streq(gpos,"proc")&&item_next(word_in_phrase)) return; if(!vowel_seg_between(item_daughter(transcription),item_last_daughter(transcription))) return; if(numsyls==1) { item_set_string(syl,"stress","1"); return; } for(;syl;syl=item_next(syl)) { if(is_stressed_vowel(item_feat_string(item_daughter(item_as(syl,"SylVowel")),"name"))) { item_set_string(syl,"stress","1"); stressed=TRUE; } } if(n==0) { if(stressed) return; n=val_int(cart_interpret(word,&ru_stress_cart)); if((numsyls+n) < 0) { if(numsyls <= 4) n=-2; else if(numsyls <= 6) n=-3; else n=-4; } } item_set_string(item_nth_daughter(syls,(numsyls+n)),"stress","1"); }