Leaked source code of windows server 2003
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.

1073 lines
33 KiB

  1. /******************************************************************************
  2. * PitchProsody.cpp *
  3. *--------------------*
  4. *
  5. * This is an implementation of the PitchProsody class.
  6. *------------------------------------------------------------------------------
  7. * Copyright (C) 1999 Microsoft Corporation Date: 04/28/99
  8. * All Rights Reserved
  9. *
  10. *********************************************************************** MC ****/
  11. //--- Additional includes
  12. #include "stdafx.h"
  13. #ifndef SPDebug_h
  14. #include <spdebug.h>
  15. #endif
  16. #ifndef AlloOps_H
  17. #include "AlloOps.h"
  18. #endif
  19. #ifndef Frontend_H
  20. #include "Frontend.h"
  21. #endif
  22. //-----------------------------
  23. // Data.cpp
  24. //-----------------------------
  25. extern const float g_PitchScale[];
  26. //--------------------------------
  27. // Interpolation direction
  28. //--------------------------------
  29. enum INTERP_DIR
  30. {
  31. GOING_UP,
  32. GOING_DOWN,
  33. };
  34. #define M_PI 3.14159265358979323846
  35. #define MAX_ORDER 4096
  36. /*****************************************************************************
  37. * HzToOct *
  38. *---------*
  39. * Description:
  40. * Convert liner freq ro exp pitch
  41. * 0.69314718 is log of 2
  42. * 1.021975 is offset for middle C
  43. *
  44. ********************************************************************** MC ***/
  45. float HzToOct( float cps)
  46. {
  47. SPDBG_FUNC( "HzToOct" );
  48. return (float)(log(cps / 1.021975) / 0.69314718);
  49. } /* HzToOct */
  50. /*****************************************************************************
  51. * OctToHz *
  52. *---------*
  53. * Description:
  54. * Convert from exp pitch to linear freq
  55. ********************************************************************** MC ***/
  56. float OctToHz( float oct)
  57. {
  58. SPDBG_FUNC( "OctToHz" );
  59. return (float)(pow(2, oct) * 1.021975);
  60. } /* OctToHz */
  61. /*****************************************************************************
  62. * CPitchProsody::DoPitchControl *
  63. *-------------------------------*
  64. * Description:
  65. * Scale speech pitch to user control
  66. *
  67. ********************************************************************** MC ***/
  68. float CPitchProsody::DoPitchControl( long pitchControl, float basePitch )
  69. {
  70. SPDBG_FUNC( "CPitchProsody::DoPitchControl" );
  71. float newPitch;
  72. if( pitchControl < 0 )
  73. {
  74. //--------------------------------
  75. // DECREASE the pitch
  76. //--------------------------------
  77. if( pitchControl < MIN_USER_PITCH )
  78. {
  79. pitchControl = MIN_USER_PITCH; // clip to min
  80. }
  81. newPitch = (float)basePitch / g_PitchScale[0 - pitchControl];
  82. }
  83. else
  84. {
  85. //--------------------------------
  86. // INCREASE the pitch
  87. //--------------------------------
  88. if( pitchControl > MAX_USER_PITCH )
  89. {
  90. pitchControl = MAX_USER_PITCH; // clip to max
  91. }
  92. newPitch = (float)basePitch * g_PitchScale[pitchControl];
  93. }
  94. return newPitch;
  95. } /* CPitchProsody::DoPitchControl */
  96. /*****************************************************************************
  97. * CPitchProsody::SetDefaultPitch *
  98. *--------------------------------*
  99. * Description:
  100. * Init pitch knots to monotone in case there's a failure in this object.
  101. *
  102. ********************************************************************** MC ***/
  103. void CPitchProsody::SetDefaultPitch()
  104. {
  105. SPDBG_FUNC( "CPitchProsody::SetDefaultPitch" );
  106. CAlloCell *pCurCell;
  107. pCurCell = m_pAllos->GetHeadCell();
  108. while( pCurCell )
  109. {
  110. float relTime, timeK;
  111. float normalPitch;
  112. long knot;
  113. normalPitch = pCurCell->m_Pitch_LO + ((pCurCell->m_Pitch_HI - pCurCell->m_Pitch_LO) / 2);
  114. timeK = pCurCell->m_ftDuration / KNOTS_PER_PHON;
  115. relTime = 0;
  116. for( knot = 0; knot < KNOTS_PER_PHON; knot++ )
  117. {
  118. pCurCell->m_ftPitch[knot] = normalPitch;
  119. pCurCell->m_ftTime[knot] = relTime;
  120. relTime += timeK;
  121. }
  122. pCurCell = m_pAllos->GetNextCell();
  123. }
  124. } /* CPitchProsody::SetDefaultPitch */
  125. /*****************************************************************************
  126. * CPitchProsody::AlloPitch *
  127. *--------------------------*
  128. * Description:
  129. * Tag pitch highlights
  130. *
  131. ********************************************************************** MC ***/
  132. void CPitchProsody::AlloPitch( CAlloList *pAllos, float baseLine, float pitchRange )
  133. {
  134. SPDBG_FUNC( "CAlloOps::AlloPitch" );
  135. CAlloCell *pCurCell;
  136. bool skipInitialSil;
  137. long quantTotal, index;
  138. m_pAllos = pAllos;
  139. m_numOfCells = m_pAllos->GetCount();
  140. m_Tune_Style = DESCEND_TUNE; // NOTE: maybe set from rules
  141. m_TotalDur = 0;
  142. quantTotal = 0;
  143. m_OffsTime = 0;
  144. skipInitialSil = true;
  145. //------------------------------
  146. // Calculate total duration
  147. // (exclude surrounding silence)
  148. //------------------------------
  149. index = 0;
  150. pCurCell = m_pAllos->GetHeadCell();
  151. while( pCurCell )
  152. {
  153. if( (skipInitialSil) && (pCurCell->m_allo == _SIL_) )
  154. {
  155. //---------------------------------
  156. // Skip leading silence
  157. //---------------------------------
  158. m_OffsTime += pCurCell->m_ftDuration;
  159. }
  160. else if( (index == (m_numOfCells -1)) && (pCurCell->m_allo == _SIL_) )
  161. {
  162. //---------------------------------
  163. // Skip term silence
  164. //---------------------------------
  165. break;
  166. }
  167. else
  168. {
  169. pCurCell->m_PitchBufStart = quantTotal;
  170. m_TotalDur += pCurCell->m_ftDuration;
  171. quantTotal = (long)(m_TotalDur / PITCH_BUF_RES);
  172. pCurCell->m_PitchBufEnd = quantTotal;
  173. skipInitialSil = false;
  174. }
  175. index++;
  176. pCurCell = pAllos->GetNextCell();
  177. }
  178. //------------------------------
  179. // Init pitch range
  180. //------------------------------
  181. pCurCell = m_pAllos->GetHeadCell();
  182. while( pCurCell )
  183. {
  184. float hzVal, pitchK, rangeTemp;
  185. //---------------------------------------
  186. // Scale to possible pitch control
  187. //---------------------------------------
  188. rangeTemp = pitchRange * pCurCell->m_PitchRangeScale;
  189. hzVal = DoPitchControl( pCurCell->m_user_Pitch, baseLine );
  190. pitchK = HzToOct( hzVal ) + pCurCell->m_PitchBaseOffs;
  191. pCurCell->m_Pitch_HI = OctToHz( pitchK + rangeTemp );
  192. pCurCell->m_Pitch_LO = OctToHz( pitchK - rangeTemp );
  193. pCurCell = pAllos->GetNextCell();
  194. }
  195. //--------------------------------------------
  196. // In case we fail somewhere, set values to
  197. // a known valid state (monotone).
  198. //--------------------------------------------
  199. SetDefaultPitch();
  200. if( m_TotalDur > 0 )
  201. {
  202. //--------------------------------------------
  203. // Generate pitch targets
  204. //--------------------------------------------
  205. PitchTrack();
  206. }
  207. } /* CPitchProsody::AlloPitch */
  208. /*****************************************************************************
  209. * LineInterpContour *
  210. *--------------------*
  211. * Description:
  212. * Does linear interpolation over the pitch contour
  213. *
  214. ********************************************************************** MC ***/
  215. void LineInterpContour( long cNumOfPoints, float *pPoints )
  216. {
  217. SPDBG_FUNC( "LineInterpContour" );
  218. long endAnch,startAnch, i;
  219. float bPoint1, ePoint1;
  220. //----------------------------------------------------
  221. // Scan forward from beginning to find 1st non-zero enrty
  222. // Use it as the START point.
  223. //----------------------------------------------------
  224. for( startAnch = 0; startAnch < cNumOfPoints; startAnch++ )
  225. {
  226. if( pPoints[startAnch] != 0 )
  227. {
  228. break;
  229. }
  230. }
  231. bPoint1 = pPoints[startAnch];
  232. //----------------------------------------------------
  233. // Scan back from end to find 1st non-zero enrty
  234. // Use it as the END point.
  235. //----------------------------------------------------
  236. for( endAnch = cNumOfPoints-1; endAnch >= 0; endAnch-- )
  237. {
  238. if( pPoints[endAnch] != 0 )
  239. {
  240. break;
  241. }
  242. }
  243. ePoint1 = pPoints[endAnch];
  244. long firstp = 0;
  245. long lastp = 0;
  246. while( firstp < cNumOfPoints )
  247. {
  248. //-------------------------------------------
  249. // Find beginning and end of current section
  250. //-------------------------------------------
  251. while( pPoints[firstp] != 0 )
  252. {
  253. if( ++firstp >= cNumOfPoints-1 )
  254. {
  255. break;
  256. }
  257. }
  258. if( firstp >= cNumOfPoints-1 )
  259. {
  260. //--------------------------------------
  261. // There's nothing to interpolate!
  262. //--------------------------------------
  263. break;
  264. }
  265. lastp = firstp+1;
  266. while( pPoints[lastp] == 0 )
  267. {
  268. if( ++lastp >= cNumOfPoints )
  269. {
  270. lastp = cNumOfPoints;
  271. break;
  272. }
  273. }
  274. lastp--;
  275. if( lastp >= firstp )
  276. {
  277. if( (lastp >= cNumOfPoints) || (firstp >= cNumOfPoints) )
  278. {
  279. break;
  280. }
  281. //-------------------------------------------
  282. // Do the interpolate
  283. //-------------------------------------------
  284. float bPoint,ePoint;
  285. if( firstp == 0 )
  286. {
  287. bPoint = bPoint1;
  288. }
  289. else
  290. {
  291. bPoint = pPoints[firstp - 1];
  292. }
  293. if( lastp == cNumOfPoints-1 )
  294. {
  295. ePoint = ePoint1;
  296. }
  297. else
  298. {
  299. ePoint = pPoints[lastp + 1];
  300. }
  301. float pointSpread = ePoint - bPoint;
  302. float timeSpread = (float) ((lastp - firstp)+2);
  303. float inc = pointSpread / timeSpread;
  304. float theBase = bPoint;
  305. for( i = firstp; i <= lastp; i++ )
  306. {
  307. theBase += inc;
  308. pPoints[i] = theBase;
  309. }
  310. }
  311. else
  312. {
  313. pPoints[firstp] = pPoints[lastp+1];
  314. }
  315. firstp = lastp+1;
  316. }
  317. } /* LineInterpContour */
  318. /*****************************************************************************
  319. * Interpolate2 *
  320. *---------------*
  321. * Description:
  322. * Do a 2nd order interpolation, a little nicer than just linear
  323. *
  324. ********************************************************************** MC ***/
  325. void Interpolate2( INTERP_DIR direction, float *m_theFitPoints, long theStart, long len, float theAmp, float theBase)
  326. {
  327. SPDBG_FUNC( "Interpolate2" );
  328. long midPoint = len / 2;
  329. long i;
  330. theAmp -= theBase;
  331. for( i = theStart; i < theStart + len;i++ )
  332. {
  333. if (direction == GOING_UP)
  334. {
  335. if( i < theStart + midPoint )
  336. {
  337. m_theFitPoints[i] = theBase +
  338. (2 * theAmp) * ((((float)i - (float)theStart) / (float)len) *
  339. (((float)i - (float)theStart) / (float)len));
  340. }
  341. else
  342. {
  343. m_theFitPoints[i] = (theBase + theAmp) -
  344. ((2 * theAmp) * ((1 - ((float)i - (float)theStart) / (float)len) *
  345. (1 - ((float)i - (float)theStart) / (float)len)));
  346. }
  347. }
  348. else if( direction == GOING_DOWN )
  349. {
  350. if( i < theStart + midPoint )
  351. {
  352. m_theFitPoints[i] = theBase +
  353. theAmp - (2 * theAmp) * ((((float)i - (float)theStart) / (float)len) *
  354. (((float)i - (float)theStart) / (float)len));
  355. }
  356. else
  357. {
  358. m_theFitPoints[i] = theBase +
  359. (2 * theAmp) * ((1 - ((float)i - (float)theStart) / (float)len) *
  360. (1 - ((float)i - (float)theStart) / (float)len));
  361. }
  362. }
  363. }
  364. } /* Interpolate2 */
  365. /*****************************************************************************
  366. * SecondOrderInterp *
  367. *--------------------*
  368. * Description:
  369. * Does 2nd order interpolation over the pitch contour
  370. *
  371. ********************************************************************** MC ***/
  372. void SecondOrderInterp( long cNumOfPoints, float *pPoints )
  373. {
  374. SPDBG_FUNC( "SecondOrderInterp" );
  375. long endAnch,startAnch;
  376. float bPoint1, ePoint1;
  377. //----------------------------------------------------
  378. // Scan forward from beginning to find 1st non-zero enrty
  379. // Use it as the START point.
  380. //----------------------------------------------------
  381. for( startAnch = 0; startAnch < cNumOfPoints; startAnch++ )
  382. {
  383. if( pPoints[startAnch] != 0 )
  384. {
  385. break;
  386. }
  387. }
  388. bPoint1 = pPoints[startAnch];
  389. //----------------------------------------------------
  390. // Scan back from end to find 1st non-zero enrty
  391. // Use it as the END point.
  392. //----------------------------------------------------
  393. for( endAnch = cNumOfPoints-1; endAnch >= 0; endAnch-- )
  394. {
  395. if( pPoints[endAnch] != 0 )
  396. {
  397. break;
  398. }
  399. }
  400. ePoint1 = pPoints[endAnch];
  401. long firstp = 0;
  402. long lastp = 0;
  403. while( firstp < cNumOfPoints-1 )
  404. {
  405. //------------------------------------------------
  406. // Find beginning and end of current section
  407. //------------------------------------------------
  408. while( pPoints[firstp] != 0 )
  409. {
  410. if( ++firstp >= cNumOfPoints-1 )
  411. {
  412. break;
  413. }
  414. }
  415. if( firstp >= cNumOfPoints-1 )
  416. {
  417. //--------------------------------------
  418. // There's nothing to interpolate!
  419. //--------------------------------------
  420. break;
  421. }
  422. lastp = firstp + 1;
  423. while( pPoints[lastp] == 0 )
  424. {
  425. if( ++lastp >= cNumOfPoints )
  426. {
  427. lastp = cNumOfPoints;
  428. break;
  429. }
  430. }
  431. lastp--;
  432. if( lastp >= firstp )
  433. {
  434. if( (lastp >= cNumOfPoints) || (firstp >= cNumOfPoints) )
  435. {
  436. break;
  437. }
  438. //--------------------------------
  439. // Do the interpolate
  440. //--------------------------------
  441. float bPoint, ePoint;
  442. if( firstp == 0 )
  443. {
  444. bPoint = bPoint1;
  445. }
  446. else
  447. {
  448. bPoint = pPoints[firstp - 1];
  449. }
  450. long theIndex = lastp + 1;
  451. if( lastp == cNumOfPoints-1 )
  452. {
  453. ePoint = ePoint1;
  454. }
  455. else
  456. {
  457. ePoint = pPoints[theIndex];
  458. }
  459. //--------------------------------
  460. // call the 2nd order routine
  461. //--------------------------------
  462. if( ePoint - bPoint > 0 )
  463. {
  464. Interpolate2( GOING_UP, pPoints, firstp, (lastp - firstp) + 1, ePoint, bPoint );
  465. }
  466. else
  467. {
  468. Interpolate2( GOING_DOWN, pPoints, firstp, (lastp - firstp) + 1, bPoint, ePoint );
  469. }
  470. }
  471. else
  472. {
  473. pPoints[firstp] = pPoints[lastp+1];
  474. }
  475. firstp = lastp+1;
  476. }
  477. //---------------------------------
  478. // IIR Filter
  479. //---------------------------------
  480. #define kPointDelay 1
  481. float filter_Out1, filter_In_Gain, filter_FB_Gain;
  482. float lastPoint;
  483. long i;
  484. //--------------------------------------------------
  485. // Skip filter if audio len less than delay
  486. //--------------------------------------------------
  487. if( cNumOfPoints > kPointDelay )
  488. {
  489. filter_In_Gain = 0.10f;
  490. filter_FB_Gain = 1.0f - filter_In_Gain;
  491. filter_Out1 = pPoints[0];
  492. for( i = 0; i < cNumOfPoints; i++ )
  493. {
  494. filter_Out1 = (filter_In_Gain * pPoints[i]) + (filter_FB_Gain * filter_Out1);
  495. pPoints[i] = filter_Out1;
  496. }
  497. for( i = kPointDelay; i < cNumOfPoints; i++ )
  498. {
  499. pPoints[i-kPointDelay] = pPoints[i];
  500. }
  501. i = (cNumOfPoints - kPointDelay) -1;
  502. lastPoint = pPoints[i++];
  503. for( ; i < cNumOfPoints; i++ )
  504. {
  505. pPoints[i] = lastPoint;
  506. }
  507. }
  508. } /* SecondOrderInterp */
  509. /*****************************************************************************
  510. * CPitchProsody::NewTarget *
  511. *---------------------------*
  512. * Description:
  513. * Insert pitch target into 'm_pContBuf'
  514. *
  515. ********************************************************************** MC ***/
  516. void CPitchProsody::NewTarget( long index, float value )
  517. {
  518. SPDBG_FUNC( "CPitchProsody::NewTarget" );
  519. m_pContBuf[index] = value;
  520. //--- Debug Macro - add pitch to target list for later debugging output
  521. TTSDBG_ADDPITCHTARGET( m_OffsTime + (PITCH_BUF_RES * index), value, m_CurAccent );
  522. } /* CPitchProsody::NewTarget */
  523. /*****************************************************************************
  524. * CPitchProsody::GetKnots *
  525. *-------------------------*
  526. * Description:
  527. * Assign pitch knots based on entries in a contour buffer.
  528. *
  529. ********************************************************************** MC ***/
  530. void CPitchProsody::GetKnots ()
  531. {
  532. SPDBG_FUNC( "CPitchProsody::GetKnots" );
  533. CAlloCell *pCurCell;
  534. float distK, scale;
  535. float pitchRange;
  536. long knot, loc, index;
  537. bool skipInitialSil;
  538. skipInitialSil = true;
  539. pCurCell = m_pAllos->GetHeadCell();
  540. index = 0;
  541. while( pCurCell )
  542. {
  543. if( index >= m_numOfCells-1 )
  544. {
  545. //-----------------------
  546. // Skip last allo
  547. //-----------------------
  548. break;
  549. }
  550. if( (!skipInitialSil) || (pCurCell->m_allo != _SIL_) )
  551. {
  552. pitchRange = pCurCell->m_Pitch_HI - pCurCell->m_Pitch_LO;
  553. distK = 1.0f / KNOTS_PER_PHON;
  554. scale = 0;
  555. for( knot = 0; knot < KNOTS_PER_PHON; knot++ )
  556. {
  557. loc = pCurCell->m_PitchBufStart + (long)((pCurCell->m_PitchBufEnd - pCurCell->m_PitchBufStart) * scale);
  558. pCurCell->m_ftPitch[knot] = pCurCell->m_Pitch_LO + (m_pContBuf[loc] * pitchRange);
  559. pCurCell->m_ftTime[knot] = scale * pCurCell->m_ftDuration;
  560. scale += distK;
  561. }
  562. skipInitialSil = false;
  563. }
  564. pCurCell = m_pAllos->GetNextCell();
  565. index++;
  566. }
  567. } /* CPitchProsody::GetKnots */
  568. /*****************************************************************************
  569. * CPitchProsody::PitchTrack *
  570. *----------------------------*
  571. * Description:
  572. * Tag pitch highlights
  573. *
  574. ********************************************************************** MC ***/
  575. void CPitchProsody::PitchTrack()
  576. {
  577. SPDBG_FUNC( "CPitchProsody::PitchTrack" );
  578. long i;
  579. CAlloCell *pCurCell, *pNextCell;
  580. bool initialWord; // 1st word in phrase
  581. long wordCntDwn;
  582. float curProm; // Current accent prominence
  583. long cNumOfPoints;
  584. float *pRefBuf, *pCeilBuf, *pFloorBuf;
  585. float lastProm;
  586. long loc;
  587. float value;
  588. pRefBuf = pCeilBuf = pFloorBuf = m_pContBuf = NULL;
  589. cNumOfPoints = (long)(m_TotalDur / PITCH_BUF_RES);
  590. pRefBuf = new float[cNumOfPoints];
  591. pCeilBuf = new float[cNumOfPoints];
  592. pFloorBuf = new float[cNumOfPoints];
  593. m_pContBuf = new float[cNumOfPoints];
  594. if( pRefBuf && pCeilBuf && pFloorBuf && m_pContBuf)
  595. {
  596. //--------------------------------------------
  597. // Initialize buffers to zero
  598. //--------------------------------------------
  599. for (i = 0; i < cNumOfPoints; i++)
  600. {
  601. pCeilBuf[i] = 0;
  602. pFloorBuf[i] = 0.00001f;
  603. pRefBuf[i] = 0;
  604. m_pContBuf[i] = 0;
  605. }
  606. //--------------------------------------------
  607. // Linear CEILING slope
  608. //--------------------------------------------
  609. if( m_Tune_Style == DESCEND_TUNE )
  610. {
  611. pCeilBuf[0] = 1.0;
  612. pCeilBuf[cNumOfPoints-1] = 0.70f;
  613. ::LineInterpContour( cNumOfPoints, pCeilBuf );
  614. }
  615. else if (m_Tune_Style == ASCEND_TUNE)
  616. {
  617. pCeilBuf[0] = 0.9f;
  618. pCeilBuf[cNumOfPoints-1] = 1.0f;
  619. ::LineInterpContour( cNumOfPoints, pCeilBuf );
  620. }
  621. else if (m_Tune_Style == FLAT_TUNE)
  622. {
  623. pCeilBuf[0] = 1.0f;
  624. pCeilBuf[cNumOfPoints-1] = 1.0f;
  625. ::LineInterpContour( cNumOfPoints, pCeilBuf );
  626. }
  627. //--------------------------------------------
  628. // Linear REFERENCE slope
  629. //--------------------------------------------
  630. pRefBuf[0] = (float) (pFloorBuf[0] + (pCeilBuf[0] - pFloorBuf[0]) * 0.33f);
  631. pRefBuf[cNumOfPoints-1] = (float) (pFloorBuf[0] + (pCeilBuf[cNumOfPoints-1] - pFloorBuf[cNumOfPoints-1]) * 0.33f);
  632. ::LineInterpContour( cNumOfPoints,pRefBuf );
  633. //--------------------------------------------
  634. // Final contour buffer
  635. //--------------------------------------------
  636. m_pContBuf[0] = pRefBuf[0];
  637. m_pContBuf[cNumOfPoints-1] = 0.0001f; // Something very small
  638. long iPrevBegin, iPrevEnd, iCurBegin;
  639. long iCurEnd, iNextBegin, iNextEnd;
  640. float cCurLen;
  641. long iCellindex;
  642. initialWord = true;
  643. iCellindex = 0;
  644. pCurCell = m_pAllos->GetHeadCell();
  645. while( pCurCell->m_allo == _SIL_ )
  646. {
  647. //---------------------------------
  648. // Skip leading silence
  649. //---------------------------------
  650. pCurCell = m_pAllos->GetNextCell();
  651. iCellindex++;
  652. }
  653. wordCntDwn = 1; // Skip 1st word
  654. lastProm = 0;
  655. iPrevBegin = iPrevEnd = 0;
  656. pNextCell = m_pAllos->GetNextCell();
  657. while( pCurCell )
  658. {
  659. if( iCellindex >= m_numOfCells-1 )
  660. {
  661. //-----------------------
  662. // Skip last allo
  663. //-----------------------
  664. break;
  665. }
  666. //-----------------------------------
  667. // Get CURRENT allo
  668. //-----------------------------------
  669. iCurBegin = pCurCell->m_PitchBufStart;
  670. iCurEnd = pCurCell->m_PitchBufEnd;
  671. cCurLen = (float)(iCurEnd - iCurBegin);
  672. curProm = pCurCell->m_Accent_Prom * (float)0.1;
  673. //-----------------------------------
  674. // Get NEXT allo
  675. //-----------------------------------
  676. iNextBegin = pNextCell->m_PitchBufStart;
  677. iNextEnd = pNextCell->m_PitchBufEnd;
  678. m_CurAccent = pCurCell->m_ToBI_Accent;
  679. //---------------------
  680. // Diagnostic
  681. //---------------------
  682. m_CurAccentSource = pCurCell->m_AccentSource;
  683. m_CurBoundarySource = pCurCell->m_BoundarySource;
  684. m_pCurTextStr = pCurCell->m_pTextStr;
  685. switch( pCurCell->m_ToBI_Accent )
  686. {
  687. case K_RSTAR:
  688. break;
  689. case K_HSTAR:
  690. {
  691. if( !initialWord ) // We never add a 'leg' to a phrase-initial word
  692. {
  693. //----------------------------------------------
  694. // Add a L leg to start to previous allo
  695. //----------------------------------------------
  696. if( iPrevBegin )
  697. {
  698. loc = (long) ((iCurBegin + (cCurLen * 0.1f)));
  699. value = ((pCeilBuf[loc] - pRefBuf[loc]) * curProm); // H*
  700. value = pRefBuf[loc] + (value * 0.25f); // L+H*
  701. NewTarget( iPrevBegin, value );
  702. //NewTarget( loc, value );
  703. }
  704. }
  705. //----------------------------------------------
  706. // Now plug in the H target
  707. //
  708. // If we're at a boundary, insert H at
  709. // allo mid-point else insert at allo start
  710. //----------------------------------------------
  711. if( pCurCell->m_ToBI_Boundary != K_NOBND )
  712. {
  713. //---------------------------
  714. // Insert H* at allo start
  715. //---------------------------
  716. loc = (long) iCurBegin;
  717. }
  718. else
  719. {
  720. //---------------------------
  721. // Insert H* at allo mid-point
  722. //---------------------------
  723. loc = (long) (iCurBegin + (cCurLen * K_HSTAR_OFFSET));
  724. }
  725. value = pRefBuf[loc] + ((pCeilBuf[loc] - pRefBuf[loc]) * curProm); // H*
  726. NewTarget( loc, value );
  727. }
  728. break;
  729. case K_LSTAR:
  730. {
  731. //------------------------------------
  732. // Insert L* at mid-point
  733. //------------------------------------
  734. loc = (long) (iCurBegin + (cCurLen * 0.3f));
  735. value = pRefBuf[loc] - ((pRefBuf[loc] - pFloorBuf[loc]) * curProm); // L*
  736. NewTarget( loc, value );
  737. }
  738. break;
  739. case K_LSTARH:
  740. {
  741. //----------------------------------------------
  742. // Insert L* at current start
  743. //----------------------------------------------
  744. value = pRefBuf[iCurBegin] - ((pRefBuf[iCurBegin] - pFloorBuf[iCurBegin]) * curProm); // L*+H
  745. NewTarget( iCurBegin, value );
  746. if( iNextBegin )
  747. {
  748. //----------------------------------------------
  749. // Insert H at next end
  750. // set prom gain?
  751. //----------------------------------------------
  752. value = pRefBuf[iNextEnd] - ((pRefBuf[iNextEnd] - pFloorBuf[iNextEnd]) * (curProm /* * .3 */ ));
  753. NewTarget( iNextEnd, value );
  754. }
  755. lastProm = 0;
  756. }
  757. break;
  758. case K_LHSTAR:
  759. {
  760. loc = (long) (iCurBegin + (cCurLen * 0.3f));
  761. if( iPrevBegin )
  762. {
  763. //----------------------------------------------
  764. // Insert L at previous start
  765. //----------------------------------------------
  766. value = (pRefBuf[iPrevBegin] - ((pRefBuf[iPrevBegin] - pFloorBuf[iPrevBegin]) * (curProm * 0.3f))); // L+H*
  767. NewTarget( iPrevBegin, value );
  768. }
  769. //----------------------------------------------
  770. // Insert H* at current mid-point
  771. //----------------------------------------------
  772. value = pRefBuf[loc] + ((pCeilBuf[loc] - pRefBuf[loc]) * curProm); // H*
  773. NewTarget( loc, value );
  774. lastProm = curProm;
  775. }
  776. break;
  777. case K_HSTARLSTAR:
  778. {
  779. //value = pRefBuf[iCurBegin] + ((pCeilBuf[iCurBegin] - pRefBuf[iCurBegin]) * curProm); // H*
  780. value = pRefBuf[0] + ((pCeilBuf[0] - pRefBuf[0]) * curProm); // H*
  781. NewTarget( iCurBegin, value );
  782. loc = (long) (iCurBegin + (cCurLen * 0.75f));
  783. value = pRefBuf[loc] - ((pRefBuf[loc] - pFloorBuf[loc]) * curProm); // L*
  784. NewTarget( loc, value );
  785. lastProm = curProm;
  786. }
  787. break;
  788. case K_DHSTAR:
  789. {
  790. loc = (long) ( iCurBegin + (cCurLen * 0.0f) );
  791. if( lastProm )
  792. {
  793. lastProm *= K_HDOWNSTEP_COEFF;
  794. value = pRefBuf[loc] + ((pCeilBuf[loc] - pRefBuf[loc]) * lastProm); // !H*
  795. NewTarget( loc, value );
  796. }
  797. //-----------------------------------------
  798. // no previous H*, treat !H* like an H*
  799. //-----------------------------------------
  800. else
  801. {
  802. value = pRefBuf[loc] + ((pCeilBuf[loc] - pRefBuf[loc]) * curProm); // H*
  803. NewTarget( loc, value );
  804. lastProm = curProm;
  805. }
  806. }
  807. break;
  808. default: // Unknown accent specfied
  809. break;
  810. }
  811. //-------------------------------------------------------------
  812. // if there's a boundary, fill in pitch value(s)
  813. // assume the boundary is set to correct (voiced) final phone
  814. //-------------------------------------------------------------
  815. curProm = pCurCell->m_Boundary_Prom * (float)0.1;
  816. m_CurAccent =(TOBI_ACCENT) pCurCell->m_ToBI_Boundary;
  817. //---------------------
  818. // Diagnostic
  819. //---------------------
  820. m_CurAccentSource = pCurCell->m_AccentSource;
  821. m_CurBoundarySource = pCurCell->m_BoundarySource;
  822. m_pCurTextStr = pCurCell->m_pTextStr;
  823. switch( pCurCell->m_ToBI_Boundary )
  824. {
  825. case K_LMINUS:
  826. {
  827. value = pRefBuf[iCurEnd] - ((pRefBuf[iCurEnd] - pFloorBuf[iCurEnd]) * curProm); // L-
  828. NewTarget( iCurEnd, value );
  829. }
  830. break;
  831. case K_HMINUS:
  832. {
  833. value = pRefBuf[iCurEnd] + ((pCeilBuf[iCurEnd] - pRefBuf[iCurEnd]) * curProm); // H-
  834. NewTarget( iCurEnd, value );
  835. }
  836. break;
  837. //case K_LPERC:
  838. //case K_HPERC:
  839. case K_LMINUSLPERC:
  840. {
  841. value = pFloorBuf[iCurEnd];
  842. //NewTarget( iCurEnd, value );
  843. NewTarget( iCurBegin, value );
  844. }
  845. break;
  846. case K_HMINUSHPERC:
  847. {
  848. value = pCeilBuf[iCurEnd];
  849. NewTarget( iCurEnd, value );
  850. }
  851. break;
  852. case K_LMINUSHPERC: // L-H%
  853. {
  854. //---------------------------------------
  855. // comma continuation rise
  856. //---------------------------------------
  857. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  858. // L starts at middle of previous phon
  859. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  860. loc = iPrevBegin + (iPrevEnd - iPrevBegin) / 2;
  861. value = pRefBuf[loc] - ((pRefBuf[loc] - pFloorBuf[loc]) * curProm); // L-
  862. NewTarget( loc, value );
  863. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  864. // H at end of current phon
  865. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  866. value = pRefBuf[iCurEnd] + ((pCeilBuf[iCurEnd] - pRefBuf[iCurEnd]) * curProm); // H%
  867. NewTarget( iCurEnd, value );
  868. }
  869. break;
  870. case K_HMINUSLPERC:
  871. {
  872. //---------------------------------------
  873. // accent extension followed by sharp drop
  874. //---------------------------------------
  875. value = pRefBuf[iCurBegin] + ((pCeilBuf[iCurBegin] - pRefBuf[iCurBegin]) * curProm); // H-
  876. NewTarget( iCurBegin, value );
  877. value = pFloorBuf[iCurEnd]; // L%
  878. //loc = iCurBegin + ((iCurEnd - iCurBegin) * 0.1f);
  879. NewTarget( iCurEnd, value );
  880. }
  881. break;
  882. default:
  883. break;
  884. }
  885. //----------------------------
  886. // Unflag initial word
  887. //----------------------------
  888. if( (initialWord) && (pCurCell->m_ctrlFlags & WORD_START) )
  889. {
  890. wordCntDwn--;
  891. if( wordCntDwn < 0 )
  892. {
  893. initialWord = false;
  894. }
  895. }
  896. //----------------------------
  897. // Setup for next allo
  898. //----------------------------
  899. iPrevBegin = iCurBegin;
  900. iPrevEnd = iCurEnd;
  901. pCurCell = pNextCell;
  902. pNextCell = m_pAllos->GetNextCell();
  903. iCellindex++;
  904. }
  905. //--- Debug Macro - Log pitch data to stream
  906. TTSDBG_LOGTOBI;
  907. ::SecondOrderInterp( cNumOfPoints, m_pContBuf );
  908. GetKnots();
  909. }
  910. if( pRefBuf )
  911. {
  912. delete pRefBuf;
  913. }
  914. if( pCeilBuf )
  915. {
  916. delete pCeilBuf;
  917. }
  918. if( pFloorBuf )
  919. {
  920. delete pFloorBuf;
  921. }
  922. if( m_pContBuf )
  923. {
  924. delete m_pContBuf;
  925. }
  926. } /* CPitchProsody::PitchTrack */