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.

886 lines
24 KiB

  1. /******************************************************************************
  2. * slm.cpp *
  3. *---------*
  4. *
  5. *------------------------------------------------------------------------------
  6. * Copyright (c) 1997 Entropic Research Laboratory, Inc.
  7. * Copyright (C) 1998 Entropic, Inc
  8. * Copyright (C) 2000 Microsoft Corporation Date: 03/02/00
  9. * All Rights Reserved
  10. *
  11. ********************************************************************* PACOG ***/
  12. #include "backendInt.h"
  13. #include "SpeakerData.h"
  14. #include "UnitSearch.h"
  15. #include <float.h>
  16. #include <math.h>
  17. #include <assert.h>
  18. #define MAX_F0 500
  19. #define MIN_F0 40
  20. #define LOW_F0_RATIO 1.0
  21. #define HIGH_F0_RATIO 1.0
  22. #define F0_RATIO_INC 0.05
  23. #define F0_WEIGHT 0.8
  24. struct DPUnit
  25. {
  26. double f0;
  27. double f0Zs;
  28. double f0Ratio;
  29. double acumCost;
  30. double targCost;
  31. double modCost;
  32. int iPrevCand;
  33. };
  34. struct DPList
  35. {
  36. std::vector<DPUnit> cands;
  37. double targF0Zs;
  38. int iBestPath;
  39. };
  40. struct NewF0Struct
  41. {
  42. double f0;
  43. double time;
  44. };
  45. struct DurStruct
  46. {
  47. double ratio;
  48. double runTime;
  49. double chunkTime;
  50. };
  51. //-------------------------------------------------------------------------
  52. //
  53. // Implementation of virtual class CSlm
  54. //
  55. class CSlmImp : CSlm
  56. {
  57. public:
  58. CSlmImp (int iOptions);
  59. ~CSlmImp ();
  60. int Load (const char *pszFileName, bool fCheckVersion);
  61. void Unload ();
  62. int GetSampFreq ();
  63. int GetSampFormat ();
  64. bool GetSynthMethod() { return m_pSpeakerData->GetSynthMethod(); }
  65. bool GetPhoneSetFlag() {return m_pSpeakerData->GetPhoneSetFlag(); }
  66. void SetFrontEndFlag() { m_pSpeakerData->SetFrontEndFlag(); }
  67. void SetF0Weight (float fWeight);
  68. void SetDurWeight (float fWeight);
  69. void SetRmsWeight (float fWeight);
  70. void SetLklWeight (float fWeight);
  71. void SetContWeight (float fWeight);
  72. void SetSameSegWeight (float fWeight);
  73. void SetPhBdrWeight (float fWeight);
  74. void SetF0BdrWeight (float fWeight);
  75. void GetTtpParam (int* piBaseLine, int* piRefLine, int* piTopLine);
  76. int Process (Phone* phList, int nPh, double startTime);
  77. CSynth* GetUnit (int iUnitIndex);
  78. ChkDescript* GetChunk (int iChunkIndex); //For command line slm
  79. void PreComputeDist();
  80. void CalculateF0Ratio ();
  81. void GetNewF0 (float** ppfF0, int* piNumF0, int iF0SampFreq);
  82. private:
  83. void GetNeighborF0s ( double dTime,
  84. std::vector<NewF0Struct>* pvNewF0,
  85. double* pdLeftF0,
  86. double* pdLeftOffset,
  87. double* pdRightF0,
  88. double* pdRightOffset,
  89. int* piLastIdx );
  90. void GetCandicates ( int iIdx, DPList *pDpLink );
  91. void GetAvgF0();
  92. void ComputeDPInfo ( DPList* pPrevLink, DPList& rCurLink);
  93. void GetUnitF0Ratio();
  94. void FindBdrF0 (double* pdLeftF0, double* pdRightF0, int idx);
  95. double m_dAvgTargF0;
  96. double m_dAvgSrcF0;
  97. private:
  98. CSpeakerData* m_pSpeakerData;
  99. CUnitSearch* m_pUnitSearch;
  100. ChkDescript* m_pChunks;
  101. int m_iNumChunks;
  102. int m_iOptions;
  103. };
  104. /*****************************************************************************
  105. * CSlm::ClassFactory *
  106. *--------------------*
  107. * Description:
  108. *
  109. ******************************************************************* PACOG ***/
  110. CSlm* CSlm::ClassFactory (int iOptions)
  111. {
  112. return new CSlmImp( iOptions );
  113. }
  114. /*****************************************************************************
  115. * CSlmImp::CSlmImp *
  116. *------------------*
  117. * Description:
  118. *
  119. ******************************************************************* PACOG ***/
  120. CSlmImp::CSlmImp( int iOptions )
  121. {
  122. m_pSpeakerData = 0;
  123. m_iOptions = iOptions;
  124. m_pChunks = 0;
  125. m_iNumChunks = 0;
  126. }
  127. /*****************************************************************************
  128. * CSlmImp::~CSlmImp *
  129. *-------------------*
  130. * Description:
  131. *
  132. ******************************************************************* PACOG ***/
  133. CSlmImp::~CSlmImp ( )
  134. {
  135. if (m_pChunks)
  136. {
  137. free (m_pChunks);
  138. m_pChunks = 0;
  139. m_iNumChunks = 0;
  140. }
  141. Unload ();
  142. }
  143. /*****************************************************************************
  144. * CSlmImp::Load *
  145. *---------------*
  146. * Description:
  147. *
  148. ******************************************************************* PACOG ***/
  149. int CSlmImp::Load(const char *pszFileName, bool fCheckVersion)
  150. {
  151. assert (pszFileName);
  152. if ((m_pSpeakerData = CSpeakerData::ClassFactory( pszFileName, fCheckVersion )) != 0)
  153. {
  154. if ((m_pUnitSearch = new CUnitSearch(m_iOptions & CSlm::DynSearch,
  155. m_iOptions & CSlm::Blend,
  156. m_iOptions & CSlm::UseTargetF0,
  157. m_iOptions & CSlm::UseGain)) != 0)
  158. {
  159. // if (m_pSpeakerData->Load (m_pUnitSearch, checkVersion))
  160. {
  161. m_pUnitSearch->SetSpeakerData(m_pSpeakerData);
  162. return 1;
  163. }
  164. }
  165. }
  166. return 0;
  167. }
  168. /*****************************************************************************
  169. * CSlmImp::Unload *
  170. *-----------------*
  171. * Description:
  172. *
  173. ******************************************************************* PACOG ***/
  174. void CSlmImp::Unload ( )
  175. {
  176. if (m_pSpeakerData)
  177. {
  178. m_pSpeakerData->Release();
  179. m_pSpeakerData = 0;
  180. }
  181. if (m_pUnitSearch)
  182. {
  183. delete m_pUnitSearch;
  184. m_pUnitSearch = 0;
  185. }
  186. }
  187. /*****************************************************************************
  188. * CSlmImp::GetTtpParam *
  189. *----------------------*
  190. * Description:
  191. * Return Prosody Range Parameters
  192. ******************************************************************* PACOG ***/
  193. void CSlmImp::GetTtpParam (int* piBaseLine, int* piRefLine, int* piTopLine)
  194. {
  195. m_pSpeakerData->GetTtpParam(piBaseLine, piRefLine, piTopLine);
  196. }
  197. /*****************************************************************************
  198. * CSlmImp::GetSampFreq *
  199. *----------------------*
  200. * Description:
  201. *
  202. ******************************************************************* PACOG ***/
  203. int CSlmImp::GetSampFreq ()
  204. {
  205. return m_pSpeakerData->GetSampFreq();
  206. }
  207. /*****************************************************************************
  208. * CSlmImp::GetSampFormat *
  209. *------------------------*
  210. * Description:
  211. *
  212. ******************************************************************* PACOG ***/
  213. int CSlmImp::GetSampFormat ()
  214. {
  215. return m_pSpeakerData->GetSampFormat();
  216. }
  217. /*****************************************************************************
  218. * CSlmImp::SetF0Weight *
  219. *----------------------*
  220. * Description:
  221. *
  222. ******************************************************************* PACOG ***/
  223. void CSlmImp::SetF0Weight (float fWeight)
  224. {
  225. m_pSpeakerData->SetF0Weight( fWeight);
  226. }
  227. /*****************************************************************************
  228. * CSlmImp::SetDurWeight *
  229. *-----------------------*
  230. * Description:
  231. *
  232. ******************************************************************* PACOG ***/
  233. void CSlmImp::SetDurWeight (float fWeight)
  234. {
  235. m_pSpeakerData->SetDurWeight( fWeight);
  236. }
  237. /*****************************************************************************
  238. * CSlmImp::SetRmsWeight *
  239. *-----------------------*
  240. * Description:
  241. *
  242. ******************************************************************* PACOG ***/
  243. void CSlmImp::SetRmsWeight (float fWeight)
  244. {
  245. m_pSpeakerData->SetRmsWeight( fWeight);
  246. }
  247. /*****************************************************************************
  248. * CSlmImp::SetLklWeight *
  249. *-----------------------*
  250. * Description:
  251. *
  252. ******************************************************************* PACOG ***/
  253. void CSlmImp::SetLklWeight (float fWeight)
  254. {
  255. m_pSpeakerData->SetLklWeight( fWeight);
  256. }
  257. /*****************************************************************************
  258. * CSlmImp::SetContWeight *
  259. *------------------------*
  260. * Description:
  261. *
  262. ******************************************************************* PACOG ***/
  263. void CSlmImp::SetContWeight (float fWeight)
  264. {
  265. m_pSpeakerData->SetContWeight( fWeight);
  266. }
  267. /*****************************************************************************
  268. * CSlmImp::SetSameSegWeight *
  269. *---------------------------*
  270. * Description:
  271. *
  272. ******************************************************************* PACOG ***/
  273. void CSlmImp::SetSameSegWeight (float fWeight)
  274. {
  275. m_pSpeakerData->SetSameWeight( fWeight);
  276. }
  277. /*****************************************************************************
  278. * CSlmImp::SetPhBdrWeight *
  279. *-------------------------*
  280. * Description:
  281. *
  282. ******************************************************************* WD ******/
  283. void CSlmImp::SetPhBdrWeight (float fWeight)
  284. {
  285. m_pSpeakerData->SetPhBdrWeight( fWeight);
  286. }
  287. /*****************************************************************************
  288. * CSlmImp::SetF0BdrWeight *
  289. *-------------------------*
  290. * Description:
  291. *
  292. ******************************************************************* WD ******/
  293. void CSlmImp::SetF0BdrWeight (float fWeight)
  294. {
  295. m_pSpeakerData->SetF0BdrWeight( fWeight);
  296. }
  297. /*****************************************************************************
  298. * CSlmImp::PreComputeDist *
  299. *-------------------------*
  300. * Description:
  301. *
  302. ******************************************************************* PACOG ***/
  303. void CSlmImp::PreComputeDist ()
  304. {
  305. if (m_pUnitSearch && m_pSpeakerData)
  306. {
  307. m_pUnitSearch->SetSpeakerData(m_pSpeakerData);
  308. }
  309. }
  310. /*****************************************************************************
  311. * CSlmImp::Process *
  312. *------------------*
  313. * Description:
  314. *
  315. ******************************************************************* PACOG ***/
  316. int CSlmImp::Process (Phone* pPhList, int iNumPh, double dStartTime)
  317. {
  318. if (m_pChunks)
  319. {
  320. free (m_pChunks);
  321. m_pChunks = 0;
  322. m_iNumChunks = 0;
  323. }
  324. if (!m_pUnitSearch->Search (pPhList, iNumPh, &m_pChunks, &m_iNumChunks, dStartTime))
  325. {
  326. return 0;
  327. }
  328. return m_iNumChunks;
  329. }
  330. /*****************************************************************************
  331. * CSlmImp::GetChunk *
  332. *-------------------*
  333. * Description:
  334. *
  335. ******************************************************************* PACOG ***/
  336. ChkDescript* CSlmImp::GetChunk(int iChunkIndex)
  337. {
  338. return &m_pChunks[iChunkIndex];
  339. }
  340. /*****************************************************************************
  341. * CSlmImp::GetUnit *
  342. *------------------*
  343. * Description:
  344. *
  345. ******************************************************************* PACOG ***/
  346. CSynth* CSlmImp::GetUnit (int iUnitIndex)
  347. {
  348. CSynth* pSynth = 0;
  349. return m_pSpeakerData->GetUnit(&m_pChunks[iUnitIndex]);
  350. }
  351. /*****************************************************************************
  352. * CSlmImp::GetNewF0 *
  353. *-------------------*
  354. *
  355. *
  356. *********************************************************************** WD ***/
  357. void CSlmImp::GetNewF0 (float** ppfF0, int* piNumF0, int iF0SampFreq)
  358. {
  359. assert ( iF0SampFreq > 0 );
  360. std::vector<NewF0Struct> vF0;
  361. std::vector<NewF0Struct> vNewF0;
  362. std::vector<DurStruct> vDurRatio;
  363. DurStruct durRatio;
  364. NewF0Struct f0Struct;
  365. int i;
  366. int iLastIdx = 0;
  367. double dTime = 0.0;
  368. double dF0Step = 1.0 / (double) iF0SampFreq; // in second
  369. double dLeftF0;
  370. double dLeftOffset;
  371. double dRightF0;
  372. double dRightOffset;
  373. CSynth* pSynth = 0;
  374. //--- clean old f0
  375. if ( *ppfF0 )
  376. {
  377. delete[] *ppfF0;
  378. *ppfF0 = NULL;
  379. }
  380. //--- get unit f0 ratio, using 3-point averaging tech
  381. for ( i = 0; i < m_iNumChunks; i++ )
  382. {
  383. m_pChunks[ i ].f0Ratio = 1.0;
  384. }
  385. GetUnitF0Ratio();
  386. //--- use original target duration
  387. double dRunTime = 0;
  388. double dPrevTime = 0;
  389. memset ( &durRatio, 0, sizeof( durRatio ) );
  390. //--- first, resample the f0 values of units
  391. for ( i = 0; i < m_iNumChunks; i++ )
  392. {
  393. pSynth = m_pSpeakerData->GetUnit(&m_pChunks[ i ]);
  394. pSynth->GetNewF0( &vNewF0, &dTime, &dRunTime );
  395. if ( dTime - dPrevTime > 0 && dRunTime - durRatio.runTime > 0 )
  396. {
  397. durRatio.ratio = ( dTime - dPrevTime ) / ( dRunTime - durRatio.runTime );
  398. }
  399. else
  400. {
  401. durRatio.ratio = 1;
  402. }
  403. dPrevTime = dTime;
  404. durRatio.runTime = dRunTime;
  405. durRatio.chunkTime = dTime;
  406. vDurRatio.push_back ( durRatio );
  407. delete pSynth;
  408. pSynth = 0;
  409. }
  410. iLastIdx = 0;
  411. for ( i = 0; i < int (dTime / dF0Step ); i++ )
  412. {
  413. GetNeighborF0s ( (i + 1) * dF0Step, &vNewF0, &dLeftF0, &dLeftOffset, &dRightF0, &dRightOffset, &iLastIdx );
  414. if ( dRightOffset + dLeftOffset > 0 )
  415. {
  416. f0Struct.f0 = (float) ( (dLeftF0 * dRightOffset + dRightF0 * dLeftOffset ) / ( dRightOffset + dLeftOffset ) );
  417. }
  418. else
  419. {
  420. f0Struct.f0 = 100.0;
  421. }
  422. f0Struct.time = (i + 1) * dF0Step;
  423. vF0.push_back ( f0Struct );
  424. }
  425. vNewF0.resize( 0 );
  426. //--- next, get new f0 values
  427. *piNumF0 = int ( vDurRatio[ vDurRatio.size() - 1 ].runTime / dF0Step );
  428. *ppfF0 = new float[ *piNumF0 ];
  429. if (*ppfF0 )
  430. {
  431. int idx = 0;
  432. double dChunkSt = 0;
  433. double dTargSt = 0;
  434. double dChunkTime = 0;
  435. dTime = 0;
  436. while ( dF0Step > vDurRatio[ idx ].runTime )
  437. {
  438. idx++;
  439. if ( idx >= vDurRatio.size() )
  440. {
  441. idx--;
  442. break;
  443. }
  444. }
  445. iLastIdx = 0;
  446. for ( i = 0; i < *piNumF0; i++ )
  447. {
  448. dTime += dF0Step;
  449. if ( idx > 0 )
  450. {
  451. dChunkSt = vDurRatio[ idx - 1 ].chunkTime;
  452. dTargSt = vDurRatio[ idx - 1 ].runTime;
  453. }
  454. dChunkTime = dChunkSt + ( dTime - dTargSt ) * vDurRatio[ idx ].ratio;
  455. GetNeighborF0s ( dChunkTime, &vF0, &dLeftF0, &dLeftOffset, &dRightF0, &dRightOffset, &iLastIdx );
  456. if ( dRightOffset + dLeftOffset > 0 )
  457. {
  458. (*ppfF0)[ i ] = (short) ( (dLeftF0 * dRightOffset + dRightF0 * dLeftOffset ) / ( dRightOffset + dLeftOffset ) );
  459. }
  460. else
  461. {
  462. (*ppfF0)[ i ] = 100.0;
  463. }
  464. while ( (i + 1) * dF0Step > vDurRatio[ idx ].runTime )
  465. {
  466. idx++;
  467. if ( idx >= vDurRatio.size() )
  468. {
  469. idx--;
  470. break;
  471. }
  472. }
  473. }
  474. }
  475. vDurRatio.resize( 0 );
  476. vF0.resize( 0 );
  477. m_pSpeakerData->ResetRunTime();
  478. }
  479. /*****************************************************************************
  480. * CSlmImp::GetNeighborF0s *
  481. *--------------------------*
  482. *
  483. *
  484. *********************************************************************** WD ***/
  485. void CSlmImp::GetNeighborF0s ( double dTime,
  486. std::vector<NewF0Struct>* pvNewF0,
  487. double* pdLeftF0,
  488. double* pdLeftOffset,
  489. double* pdRightF0,
  490. double* pdRightOffset,
  491. int* piLastIdx )
  492. {
  493. for ( int i = *piLastIdx; i < pvNewF0->size(); i++ )
  494. {
  495. if ( (*pvNewF0)[ i ].time >= dTime )
  496. {
  497. if ( i - 1 < 0 )
  498. {
  499. *pdLeftF0 = 0;
  500. *pdRightF0 = (*pvNewF0)[ i ].f0;
  501. *pdLeftOffset = (*pvNewF0)[ i ].time;
  502. *pdRightOffset = 0;
  503. }
  504. else
  505. {
  506. *pdLeftF0 = (*pvNewF0)[ i - 1 ].f0;
  507. *pdRightF0 = (*pvNewF0)[ i ].f0;
  508. *pdLeftOffset = dTime - (*pvNewF0)[ i - 1 ].time;
  509. *pdRightOffset = (*pvNewF0)[ i ].time - dTime;
  510. }
  511. break;
  512. }
  513. }
  514. *piLastIdx = i;
  515. }
  516. /*****************************************************************************
  517. * CSlmImp::CalculateF0Ratio *
  518. *---------------------------*
  519. * Description: skip unit with srcF0 = 0
  520. *
  521. *********************************************************************** WD ***/
  522. void CSlmImp::CalculateF0Ratio ()
  523. {
  524. std::vector<DPList> dpList;
  525. DPList dpLink;
  526. int iPrevIdx = -1; // the last cand with non-zero f0
  527. int i;
  528. GetAvgF0 ();
  529. for ( i = 0; i < m_iNumChunks; i++ )
  530. {
  531. dpLink.cands.resize ( 0 );
  532. GetCandicates ( i, &dpLink );
  533. if ( i > 0 )
  534. {
  535. if ( dpLink.cands.size() > 1 )
  536. {
  537. if ( iPrevIdx < 0 )
  538. {
  539. ComputeDPInfo ( NULL, dpLink );
  540. }
  541. else
  542. {
  543. ComputeDPInfo ( &dpList[ iPrevIdx ], dpLink );
  544. }
  545. iPrevIdx = i;
  546. }
  547. }
  548. else
  549. {
  550. if ( dpLink.cands.size() > 1 )
  551. {
  552. ComputeDPInfo ( NULL, dpLink );
  553. iPrevIdx = i;
  554. }
  555. }
  556. dpList.push_back ( dpLink );
  557. }
  558. //--- find optimal path
  559. i = m_iNumChunks - 1;
  560. iPrevIdx = -1;
  561. int iCurIdx;
  562. iCurIdx = dpList[ i ].iBestPath;
  563. if ( dpList[ i ].cands.size() > 1 )
  564. {
  565. iPrevIdx = dpList[ i ].cands[ iCurIdx ].iPrevCand;
  566. }
  567. m_pChunks[ i ].f0Ratio = dpList[ i ].cands[ iCurIdx ].f0Ratio;
  568. i--;
  569. for ( ; i >= 0; i-- )
  570. {
  571. iCurIdx = dpList[ i ].iBestPath;
  572. if ( dpList[ i ].cands.size() > 1 )
  573. {
  574. if ( iPrevIdx >= 0 )
  575. {
  576. iCurIdx = iPrevIdx;
  577. }
  578. iPrevIdx = dpList[ i ].cands[ iCurIdx ].iPrevCand;
  579. }
  580. m_pChunks[ i ].f0Ratio = dpList[ i ].cands[ iCurIdx ].f0Ratio;
  581. }
  582. //--- free memory
  583. for ( i = 0; i < dpList.size(); i++ )
  584. {
  585. dpList[ i ].cands.resize ( 0 );
  586. }
  587. dpList.resize( 0 );
  588. }
  589. /*****************************************************************************
  590. * CSlmImp::ComputeDPInfo *
  591. *------------------------*
  592. * Description:
  593. *
  594. *********************************************************************** WD ***/
  595. void CSlmImp::ComputeDPInfo ( DPList* pPrevLink, DPList& rCurLink)
  596. {
  597. DPUnit candIseg;
  598. DPUnit candJseg;
  599. int nCandI;
  600. int nCandJ;
  601. double dMinCost;
  602. double dTotalMinCost;
  603. double dAcumCost;
  604. double dJointCost;
  605. nCandI = rCurLink.cands.size();
  606. if ( pPrevLink )
  607. {
  608. nCandJ = pPrevLink->cands.size();
  609. }
  610. rCurLink.iBestPath = -1;
  611. dTotalMinCost = DBL_MAX;
  612. for ( int i = 0; i < nCandI; i++ )
  613. {
  614. candIseg = rCurLink.cands[ i ];
  615. if ( pPrevLink )
  616. {
  617. dMinCost = DBL_MAX;
  618. for ( int j = 0; j < nCandJ; j++ )
  619. {
  620. candJseg = pPrevLink->cands[ j ];
  621. dJointCost = fabs ( ( candIseg.f0Zs - candJseg.f0Zs ) - ( rCurLink.targF0Zs - pPrevLink->targF0Zs ) );
  622. //--- acum cost
  623. dAcumCost = dJointCost + pPrevLink->cands[ j ].acumCost + rCurLink.cands[ i ].targCost;
  624. dAcumCost += F0_WEIGHT * ( rCurLink.cands[ i ].modCost + pPrevLink->cands[ j ].modCost );
  625. if ( dAcumCost < dMinCost )
  626. {
  627. dMinCost = dAcumCost;
  628. rCurLink.cands[ i ].iPrevCand = j;
  629. }
  630. }
  631. rCurLink.cands[ i ].acumCost = dMinCost;
  632. }
  633. else
  634. {
  635. rCurLink.cands[ i ].iPrevCand = 0;
  636. rCurLink.cands[ i ].acumCost = rCurLink.cands[ i ].targCost;
  637. }
  638. if ( dTotalMinCost > rCurLink.cands[ i ].acumCost )
  639. {
  640. dTotalMinCost = rCurLink.cands[ i ].acumCost;
  641. rCurLink.iBestPath = i;
  642. }
  643. }
  644. }
  645. /*****************************************************************************
  646. * CSlmImp::GetAvgF0 *
  647. *-------------------*
  648. * Description:
  649. *
  650. *********************************************************************** WD ***/
  651. void CSlmImp::GetAvgF0()
  652. {
  653. int iNumTargF0 = 0;
  654. int iNumSrcF0 = 0;
  655. m_dAvgTargF0 = 0.0;
  656. m_dAvgSrcF0 = 0.0;
  657. for ( int i = 0; i < m_iNumChunks; i++ )
  658. {
  659. if ( m_pChunks[ i ].srcF0 > 0 )
  660. {
  661. m_dAvgSrcF0 += m_pChunks[ i ].srcF0;
  662. iNumSrcF0++;
  663. }
  664. if ( m_pChunks[ i ].targF0 > 0 )
  665. {
  666. m_dAvgTargF0 += m_pChunks[ i ].targF0;
  667. iNumTargF0++;
  668. }
  669. }
  670. if ( iNumSrcF0 > 0 )
  671. {
  672. m_dAvgSrcF0 /= iNumSrcF0;
  673. }
  674. if ( iNumTargF0 > 0 )
  675. {
  676. m_dAvgTargF0 /= iNumTargF0;
  677. }
  678. }
  679. /*****************************************************************************
  680. * CSlmImp::GetCandicates *
  681. *------------------------*
  682. * Description:
  683. *
  684. *********************************************************************** WD ***/
  685. void CSlmImp::GetCandicates ( int idx, DPList *pDpLink )
  686. {
  687. DPUnit dpCand;
  688. double dF0;
  689. pDpLink->targF0Zs = ( m_pChunks[ idx ].targF0 - m_dAvgTargF0 ) / m_dAvgTargF0;
  690. pDpLink->iBestPath = 0;
  691. for ( double d = LOW_F0_RATIO; d <= HIGH_F0_RATIO; d += F0_RATIO_INC )
  692. {
  693. memset ( &dpCand, 0, sizeof ( DPUnit ) );
  694. if ( m_pChunks[ idx ].srcF0 == 0.0 || m_dAvgSrcF0 == 0.0 )
  695. {
  696. dpCand.f0Ratio = 1.0;
  697. pDpLink->cands.push_back ( dpCand );
  698. break;
  699. }
  700. dF0 = m_pChunks[ idx ].srcF0 * d;
  701. if ( dF0 <= MAX_F0 && dF0 >= MIN_F0 )
  702. {
  703. dpCand.f0 = dF0;
  704. dpCand.f0Zs = ( dF0 - m_dAvgSrcF0 ) / m_dAvgSrcF0;
  705. dpCand.f0Ratio = d;
  706. dpCand.modCost = fabs ( 1.0 - d );
  707. pDpLink->cands.push_back ( dpCand );
  708. }
  709. }
  710. }
  711. /*****************************************************************************
  712. * CSlmImp::GetUnitF0Ratio *
  713. *-------------------------*
  714. * Description:
  715. *
  716. *********************************************************************** WD ***/
  717. void CSlmImp::GetUnitF0Ratio ()
  718. {
  719. double dLeftF0;
  720. double dRightF0;
  721. double dCurF0;
  722. double dCenterF0 = 0;
  723. for ( int i = 0; i < m_iNumChunks; i++ )
  724. {
  725. if ( m_pChunks[ i ].srcF0 == 0 )
  726. {
  727. continue;
  728. }
  729. FindBdrF0 ( &dLeftF0, &dRightF0, i );
  730. dCurF0 = m_pChunks[ i ].srcF0 * m_pChunks[ i ].f0Ratio;
  731. if ( dCurF0 > 0 )
  732. {
  733. if ( dLeftF0 > 0 && dRightF0 > 0 )
  734. {
  735. dCenterF0 = ( dCurF0 + dLeftF0 + dRightF0 ) / 3;
  736. }
  737. else if ( dRightF0 > 0 )
  738. {
  739. dCenterF0 = ( dCurF0 + dRightF0 ) / 2;
  740. }
  741. else if ( dLeftF0 > 0 )
  742. {
  743. dCenterF0 = ( dCurF0 + dLeftF0 ) / 2;
  744. }
  745. if ( dCenterF0 > 0 )
  746. {
  747. m_pChunks[ i ].f0Ratio = dCenterF0 / dCurF0;
  748. }
  749. }
  750. }
  751. }
  752. /*****************************************************************************
  753. * CSlmImp::FindBdrF0 *
  754. *------------------------*
  755. * Description:
  756. *
  757. *********************************************************************** WD ***/
  758. void CSlmImp::FindBdrF0 (double* pdLeftF0, double* pdRightF0, int idx)
  759. {
  760. int i = idx - 1;
  761. while ( i >= 0 && m_pChunks[ i ].srcF0 == 0 )
  762. {
  763. i--;
  764. }
  765. if ( i < 0 )
  766. {
  767. *pdLeftF0 = -1;
  768. }
  769. else
  770. {
  771. *pdLeftF0 = m_pChunks[ i ].srcF0 * m_pChunks[ i ].f0Ratio;
  772. }
  773. i = idx + 1;
  774. while ( i < m_iNumChunks && m_pChunks[ i ].srcF0 == 0 )
  775. {
  776. i++;
  777. }
  778. if ( i >= m_iNumChunks )
  779. {
  780. *pdRightF0 = -1;
  781. }
  782. else
  783. {
  784. *pdRightF0 = m_pChunks[ i ].srcF0 * m_pChunks[ i ].f0Ratio;
  785. }
  786. }