us_f0_model.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*************************************************************************/
  2. /* */
  3. /* Language Technologies Institute */
  4. /* Carnegie Mellon University */
  5. /* Copyright (c) 2001 */
  6. /* All Rights Reserved. */
  7. /* */
  8. /* Permission is hereby granted, free of charge, to use and distribute */
  9. /* this software and its documentation without restriction, including */
  10. /* without limitation the rights to use, copy, modify, merge, publish, */
  11. /* distribute, sublicense, and/or sell copies of this work, and to */
  12. /* permit persons to whom this work is furnished to do so, subject to */
  13. /* the following conditions: */
  14. /* 1. The code must retain the above copyright notice, this list of */
  15. /* conditions and the following disclaimer. */
  16. /* 2. Any modifications must be clearly marked as such. */
  17. /* 3. Original authors' names are not deleted. */
  18. /* 4. The authors' names are not used to endorse or promote products */
  19. /* derived from this software without specific prior written */
  20. /* permission. */
  21. /* */
  22. /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
  23. /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
  24. /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
  25. /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
  26. /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
  27. /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
  28. /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
  29. /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
  30. /* THIS SOFTWARE. */
  31. /* */
  32. /*************************************************************************/
  33. /* Author: Alan W Black (awb@cs.cmu.edu) */
  34. /* Date: January 2001 */
  35. /*************************************************************************/
  36. /* */
  37. /* An F0 model */
  38. /* This is derived fromthe f2b model freely distributed in Festival */
  39. /* */
  40. /*************************************************************************/
  41. #include "cst_hrg.h"
  42. #include "cst_phoneset.h"
  43. #include "us_f0.h"
  44. static void apply_lr_model(cst_item *s,
  45. const us_f0_lr_term *f0_lr_terms,
  46. float *start,
  47. float *mid,
  48. float *end)
  49. {
  50. int i;
  51. const cst_val *v=0;
  52. float fv;
  53. /* Interceptors */
  54. *start = f0_lr_terms[0].start;
  55. *mid = f0_lr_terms[0].mid;
  56. *end = f0_lr_terms[0].end;
  57. for (i=1; f0_lr_terms[i].feature; i++)
  58. {
  59. if (!cst_streq(f0_lr_terms[i].feature,f0_lr_terms[i-1].feature))
  60. v = ffeature(s,f0_lr_terms[i].feature);
  61. if (f0_lr_terms[i].type)
  62. {
  63. if (cst_streq(val_string(v),f0_lr_terms[i].type))
  64. fv = 1.0;
  65. else
  66. fv = 0.0;
  67. }
  68. else
  69. fv = val_float(v);
  70. (*start) += fv*f0_lr_terms[i].start;
  71. (*mid) += fv*f0_lr_terms[i].mid;
  72. (*end) += fv*f0_lr_terms[i].end;
  73. /* printf("f %s start %f mid %f end %f\n",
  74. f0_lr_terms[i].feature,
  75. *start,*mid,*end); */
  76. }
  77. }
  78. static void add_target_point(cst_relation *targ,float pos, float f0)
  79. {
  80. cst_item *t;
  81. /* printf("target %f at %f\n",f0,pos); */
  82. t = relation_append(targ,NULL);
  83. item_set_float(t,"pos",pos);
  84. /* them there can sometimes do silly things, so guard for that */
  85. if (f0 > 500.0)
  86. item_set_float(t,"f0",500.0);
  87. else if (f0 < 50.0)
  88. item_set_float(t,"f0",50.0);
  89. else
  90. item_set_float(t,"f0",f0);
  91. }
  92. /* model mean and stddev take from f2b/kal_diphone */
  93. #define model_mean 170.0
  94. #define model_stddev 34
  95. #define map_f0(v,m,s) ((((v-model_mean)/model_stddev)*s)+m)
  96. static int post_break(cst_item *syl)
  97. {
  98. if ((item_prev(syl) == 0) ||
  99. (cst_streq("pau",
  100. ffeature_string(syl,
  101. "R:SylStructure.daughter.R:Segment.p.name"))))
  102. return TRUE;
  103. else
  104. return FALSE;
  105. }
  106. static int pre_break(cst_item *syl)
  107. {
  108. if ((item_next(syl) == 0) ||
  109. (cst_streq("pau",
  110. ffeature_string(syl,
  111. "R:SylStructure.daughtern.R:Segment.n.name"))))
  112. return TRUE;
  113. else
  114. return FALSE;
  115. }
  116. static float vowel_mid(cst_item *syl)
  117. {
  118. /* return time point mid way in vowel in this syl */
  119. cst_item *s;
  120. cst_item *ts;
  121. const cst_phoneset *ps = item_phoneset(syl);
  122. ts = item_daughter(item_as(syl,"SylStructure"));
  123. for (s=ts; s; s = item_next(s))
  124. {
  125. if (cst_streq("+", phone_feature_string(ps,item_feat_string(s,"name"),
  126. "vc")))
  127. {
  128. return (item_feat_float(s,"end")+
  129. ffeature_float(s,"R:Segment.p.end"))/2.0;
  130. }
  131. }
  132. /* no segments, shouldn't happen */
  133. if (ts == 0)
  134. return 0;
  135. /* no vowel in syllable, shouldn't happen */
  136. return (item_feat_float(ts,"end")+
  137. ffeature_float(ts,"R:Segment.p.end"))/2.0;
  138. }
  139. cst_utterance *us_f0_model(cst_utterance *u)
  140. {
  141. /* F0 target model: Black and Hunt ICSLP96, three points per syl */
  142. cst_item *syl, *t, *nt;
  143. cst_relation *targ_rel;
  144. float mean, stddev, local_mean, local_stddev;
  145. float start, mid, end, lend;
  146. float seg_end;
  147. if (feat_present(u->features,"no_f0_target_model"))
  148. return u;
  149. targ_rel = utt_relation_create(u,"Target");
  150. mean = get_param_float(u->features,"int_f0_target_mean", 100.0);
  151. mean *= get_param_float(u->features,"f0_shift", 1.0);
  152. stddev = get_param_float(u->features,"int_f0_target_stddev", 12.0);
  153. lend = 0;
  154. for (syl=relation_head(utt_relation(u,"Syllable"));
  155. syl;
  156. syl = item_next(syl))
  157. {
  158. /* printf("word %s, accent %s endtone %s\n",
  159. ffeature_string(syl,"R:SylStructure.parent.name"),
  160. ffeature_string(syl,"accent"),
  161. ffeature_string(syl,"endtone")); */
  162. if (!item_daughter(item_as(syl,"SylStructure")))
  163. continue; /* no segs in syl */
  164. local_mean = ffeature_float(syl,"R:SylStructure.parent.R:Token.parent.local_f0_shift");
  165. if (local_mean)
  166. local_mean *= mean;
  167. else
  168. local_mean = mean;
  169. local_stddev = ffeature_float(syl,"R:SylStructure.parent.R:Token.parent.local_f0_range");
  170. if (local_stddev == 0.0)
  171. local_stddev = stddev;
  172. apply_lr_model(syl,f0_lr_terms,&start,&mid,&end);
  173. if (post_break(syl))
  174. lend = map_f0(start,local_mean,local_stddev);
  175. add_target_point(targ_rel,
  176. ffeature_float(syl,
  177. "R:SylStructure.daughter.R:Segment.p.end"),
  178. map_f0((start+lend)/2.0,local_mean,local_stddev));
  179. add_target_point(targ_rel,
  180. vowel_mid(syl),
  181. map_f0(mid,local_mean,local_stddev));
  182. lend = map_f0(end,local_mean,local_stddev);
  183. if (pre_break(syl))
  184. add_target_point(targ_rel,
  185. ffeature_float(syl,"R:SylStructure.daughtern.end"),
  186. map_f0(end,local_mean,local_stddev));
  187. }
  188. /* Guarantee targets go from start to end of utterance */
  189. t = relation_head(targ_rel);
  190. if (t == 0)
  191. add_target_point(targ_rel,0,mean);
  192. else if (item_feat_float(t,"pos") > 0)
  193. {
  194. nt = item_prepend(t,NULL);
  195. item_set_float(nt,"pos",0.0);
  196. item_set_float(nt,"f0",item_feat_float(t,"f0"));
  197. }
  198. t = relation_tail(targ_rel);
  199. seg_end = item_feat_float(relation_tail(utt_relation(u,"Segment")),"end");
  200. if (item_feat_float(t,"pos") < seg_end)
  201. add_target_point(targ_rel,seg_end,item_feat_float(t,"f0"));
  202. return u;
  203. }