Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
8.7 KiB

  1. /******************************************************************************
  2. * Duration.cpp *
  3. *--------------*
  4. *
  5. *------------------------------------------------------------------------------
  6. * Copyright (C) 1999 Microsoft Corporation Date: 04/28/99
  7. * All Rights Reserved
  8. *
  9. *********************************************************************** MC ****/
  10. //--- Additional includes
  11. #include "stdafx.h"
  12. #ifndef SPDebug_h
  13. #include <spdebug.h>
  14. #endif
  15. #ifndef Frontend_H
  16. #include "Frontend.h"
  17. #endif
  18. #ifndef AlloOps_H
  19. #include "AlloOps.h"
  20. #endif
  21. //-----------------------------
  22. // Data.cpp
  23. //-----------------------------
  24. extern const unsigned long g_AlloFlags[];
  25. extern const float g_BoundryDurTbl[];
  26. extern const float g_BoundryStretchTbl[];
  27. /*****************************************************************************
  28. * CDuration::Pause_Insertion *
  29. *----------------------------*
  30. * Description:
  31. * Duration Rule #1 - Pause Insertion
  32. *
  33. ********************************************************************** MC ***/
  34. void CDuration::Pause_Insertion( long userDuration, long silBreak )
  35. {
  36. SPDBG_FUNC( "CDuration::Pause_Insertion" );
  37. if( userDuration )
  38. {
  39. m_DurHold = ((float)userDuration / 1000);
  40. m_TotalDurScale = 1.0;
  41. }
  42. else if( silBreak )
  43. {
  44. m_DurHold = ((float)silBreak / 1000);
  45. }
  46. else
  47. {
  48. if( m_CurBoundary != NULL_BOUNDARY)
  49. {
  50. m_DurHold = g_BoundryDurTbl[(long)m_CurBoundary];
  51. //m_DurHold *= m_TotalDurScale;
  52. //----------------------------
  53. // Clip to limits
  54. //----------------------------
  55. if( m_DurHold > MAX_SIL_DUR )
  56. {
  57. m_DurHold = MAX_SIL_DUR;
  58. }
  59. /*else if( m_DurHold < MIN_ALLO_DUR )
  60. {
  61. m_DurHold = MIN_ALLO_DUR;
  62. }*/
  63. }
  64. }
  65. } /* CDuration::Pause_Insertion */
  66. /*****************************************************************************
  67. * CDuration::PhraseFinal_Lengthen *
  68. *---------------------------------*
  69. * Description:
  70. * Duration Rule #2 - Phrase-final Lengthening
  71. *
  72. ********************************************************************** MC ***/
  73. void CDuration::PhraseFinal_Lengthen( long /*cellCount*/ )
  74. {
  75. SPDBG_FUNC( "CDuration::PhraseFinal_Lengthen" );
  76. float stretchGain;
  77. if( m_cur_SyllableType & TERM_END_SYLL)
  78. {
  79. if( (m_cur_Stress) && (m_cur_VowelFlag) )
  80. {
  81. stretchGain = g_BoundryStretchTbl[(long)m_NextBoundary];
  82. m_DurHold *= stretchGain;
  83. //----------------------------
  84. // Clip to limits
  85. //----------------------------
  86. if( m_DurHold > MAX_ALLO_DUR )
  87. {
  88. m_DurHold = MAX_ALLO_DUR;
  89. }
  90. else if( m_DurHold < MIN_ALLO_DUR )
  91. {
  92. m_DurHold = MIN_ALLO_DUR;
  93. }
  94. }
  95. }
  96. } /* CDuration::PhraseFinal_Lengthen */
  97. #define EMPH_VOWEL_GAIN 1.0f
  98. #define EMPH_CONS_GAIN 1.25f
  99. #define EMPH_VOWEL_MIN 0.060f
  100. #define EMPH_CONS_MIN 0.020f
  101. #define EMPH_MIN_DUR 0.150f
  102. /*****************************************************************************
  103. * CDuration::Emphatic_Lenghen *
  104. *-----------------------------*
  105. * Description:
  106. * Duration Rule #8 - Lengthening for emphasis
  107. *
  108. ********************************************************************** MC ***/
  109. long CDuration::Emphatic_Lenghen( long lastStress )
  110. {
  111. SPDBG_FUNC( "CDuration::Emphatic_Lenghen" );
  112. long eFlag;
  113. bool isEmph;
  114. eFlag = lastStress;
  115. if( m_cur_Stress & EMPHATIC_STRESS )
  116. {
  117. isEmph = true;
  118. }
  119. else
  120. {
  121. isEmph = false;
  122. }
  123. if( (m_cur_PhonCtrl & WORD_INITIAL_CONSONANT) ||
  124. ( m_cur_VowelFlag && (!isEmph)) )
  125. {
  126. eFlag = false; // start of a new word OR non-emph vowel
  127. }
  128. if( isEmph )
  129. {
  130. eFlag = true; // continue lengthening until above condition is met
  131. }
  132. if( eFlag )
  133. {
  134. /*if( m_DurHold < EMPH_MIN_DUR )
  135. {
  136. m_durationPad += EMPH_MIN_DUR - m_DurHold;
  137. }*/
  138. float durDiff;
  139. if( m_cur_VowelFlag)
  140. {
  141. durDiff = (m_DurHold * EMPH_VOWEL_GAIN) - m_DurHold;
  142. if( durDiff < EMPH_VOWEL_MIN )
  143. {
  144. durDiff = EMPH_VOWEL_MIN;
  145. }
  146. }
  147. else
  148. {
  149. durDiff = (m_DurHold * EMPH_CONS_GAIN) - m_DurHold;
  150. if( durDiff < EMPH_CONS_MIN )
  151. {
  152. durDiff = EMPH_CONS_MIN;
  153. }
  154. }
  155. m_durationPad += durDiff; // lengthen phon for emph
  156. }
  157. return eFlag;
  158. } /* CDuration::Emphatic_Lenghen */
  159. /*****************************************************************************
  160. * CDuration::AlloDuration *
  161. *-------------------------*
  162. * Description:
  163. * Calculate durations
  164. *
  165. ********************************************************************** MC ***/
  166. void CDuration::AlloDuration( CAlloList *pAllos, float rateRatio )
  167. {
  168. SPDBG_FUNC( "CDuration::AlloDuration" );
  169. long eFlag;
  170. CAlloCell *pPrevCell, *pCurCell, *pNextCell, *pNext2Cell;
  171. long numOfCells;
  172. long userDuration, silBreak;
  173. numOfCells = pAllos->GetCount();
  174. if( numOfCells > 0 )
  175. {
  176. eFlag = false;
  177. //------------------------------
  178. // Fill the pipeline
  179. //------------------------------
  180. pPrevCell = pAllos->GetHeadCell();
  181. pCurCell = pAllos->GetNextCell();
  182. pNextCell = pAllos->GetNextCell();
  183. pNext2Cell = pAllos->GetNextCell();
  184. //------------------------------
  185. // 1st allo is always SIL
  186. //------------------------------
  187. pPrevCell->m_ftDuration = pPrevCell->m_UnitDur = PITCH_BUF_RES; // initial SIL
  188. while( pCurCell )
  189. {
  190. //------------------
  191. // Current
  192. //------------------
  193. m_cur_Phon = pCurCell->m_allo;
  194. m_cur_PhonCtrl = pCurCell->m_ctrlFlags;
  195. m_cur_SyllableType = m_cur_PhonCtrl & SYLLABLE_TYPE_FIELD;
  196. m_cur_Stress = m_cur_PhonCtrl & STRESS_FIELD;
  197. m_cur_PhonFlags = ::g_AlloFlags[m_cur_Phon];
  198. userDuration = pCurCell->m_user_Break;
  199. silBreak = pCurCell->m_Sil_Break;
  200. if( m_cur_PhonFlags & KVOWELF)
  201. {
  202. m_cur_VowelFlag = true;
  203. }
  204. else
  205. {
  206. m_cur_VowelFlag = false;
  207. }
  208. m_CurBoundary = pCurCell->m_TuneBoundaryType;
  209. m_NextBoundary = pCurCell->m_NextTuneBoundaryType;
  210. m_TotalDurScale = rateRatio * pCurCell->m_DurScale * pCurCell->m_ProsodyDurScale;
  211. // m_DurHold = pCurCell->m_UnitDur;
  212. m_DurHold = 1.f;
  213. m_durationPad = 0;
  214. if( pCurCell->m_user_Emph > 0 )
  215. {
  216. m_cur_Stress |= EMPHATIC_STRESS;
  217. }
  218. //------------------
  219. // Prev
  220. //------------------
  221. m_prev_Phon = pPrevCell->m_allo;
  222. m_prev_PhonCtrl = pPrevCell->m_ctrlFlags;
  223. m_prev_PhonFlags = ::g_AlloFlags[m_prev_Phon];
  224. //------------------
  225. // Next
  226. //------------------
  227. if( pNextCell )
  228. {
  229. m_next_Phon = pNextCell->m_allo;
  230. m_next_PhonCtrl = pNextCell->m_ctrlFlags;
  231. }
  232. else
  233. {
  234. m_next_Phon = _SIL_;
  235. m_next_PhonCtrl = 0;
  236. }
  237. m_next_PhonFlags = ::g_AlloFlags[m_next_Phon];
  238. //------------------
  239. // 2 phons ahead
  240. //------------------
  241. if( pNext2Cell )
  242. {
  243. m_next2_Phon = pNext2Cell->m_allo;
  244. m_next2_PhonCtrl = pNext2Cell->m_ctrlFlags;
  245. }
  246. else
  247. {
  248. m_next2_Phon = _SIL_;
  249. m_next2_PhonCtrl = 0;
  250. }
  251. m_next2_PhonFlags = ::g_AlloFlags[m_next2_Phon];
  252. if( m_cur_Phon == _SIL_ )
  253. {
  254. //-------------------------------------------
  255. // #1 - Pause Insertion
  256. //-------------------------------------------
  257. Pause_Insertion( userDuration, silBreak );
  258. }
  259. else
  260. {
  261. //-------------------------------------------
  262. // #2 - Phrase-final Lengthening
  263. //-------------------------------------------
  264. PhraseFinal_Lengthen( numOfCells );
  265. //-------------------------------------------
  266. // #8 Lengthening for emphasis
  267. //-------------------------------------------
  268. eFlag = Emphatic_Lenghen( eFlag );
  269. }
  270. pCurCell->m_ftDuration = ((m_DurHold + m_durationPad) / m_TotalDurScale);
  271. //---------------------------------
  272. // Shift the pipeline once
  273. //---------------------------------
  274. pPrevCell = pCurCell;
  275. pCurCell = pNextCell;
  276. pNextCell = pNext2Cell;
  277. pNext2Cell = pAllos->GetNextCell();
  278. }
  279. }
  280. } /* CDuration::AlloDuration */