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.

733 lines
17 KiB

  1. /******************************************************************************
  2. * clusters.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 "clusters.h"
  13. #include "backendInt.h"
  14. #include <assert.h>
  15. #include <math.h>
  16. const int CClusters::m_iHistMax = 4;
  17. const double CClusters::m_dVerySmallProb = -100000.0;
  18. /*****************************************************************************
  19. * CClusters::CClusters *
  20. *-----------------------*
  21. * Description:
  22. *
  23. ******************************************************************* PACOG ***/
  24. CClusters::CClusters ()
  25. {
  26. m_pSegments = 0;
  27. }
  28. /*****************************************************************************
  29. * CClusters::~CClusters *
  30. *-----------------------*
  31. * Description:
  32. *
  33. ******************************************************************* PACOG ***/
  34. CClusters::~CClusters ()
  35. {
  36. if (m_pSegments)
  37. {
  38. delete[] m_pSegments;
  39. }
  40. }
  41. /*****************************************************************************
  42. * CClusters::LoadFromFile *
  43. *-------------------------*
  44. * Description:
  45. *
  46. ******************************************************************* PACOG ***/
  47. int CClusters::LoadFromFile (FILE* fp)
  48. {
  49. SegInfo segment;
  50. int iNumSegments;
  51. int iUseVq;
  52. int iReadSize;
  53. int i;
  54. assert (fp);
  55. // Number of segments in the file
  56. if (! fread (&iNumSegments, sizeof(iNumSegments), 1, fp))
  57. {
  58. return 0;
  59. }
  60. if (!Init (iNumSegments))
  61. {
  62. return 0;
  63. }
  64. // VQ info in file or not?
  65. if (! fread (&iUseVq, sizeof(iUseVq), 1, fp))
  66. {
  67. return 0;
  68. }
  69. iReadSize = iUseVq ? sizeof(StateInfoVQ) : sizeof(StateInfo);
  70. // Read segments
  71. memset (&segment, 0, sizeof(segment));
  72. for ( i=0; i<iNumSegments; i++)
  73. {
  74. if (!fread (&segment, iReadSize, 1, fp) )
  75. {
  76. return 0;
  77. }
  78. SetClusterEquivalent (i, &segment);
  79. }
  80. #ifdef _DEBUG_
  81. Debug();
  82. #endif
  83. return 1;
  84. }
  85. /*****************************************************************************
  86. * CClusters::Init *
  87. *-----------------*
  88. * Description:
  89. *
  90. ******************************************************************* PACOG ***/
  91. bool CClusters::Init(int iNumSegments)
  92. {
  93. if ((m_pSegments = new SegInfo[iNumSegments]) != 0)
  94. {
  95. m_iNumSegments = iNumSegments;
  96. return m_hash.Init();
  97. }
  98. return false;
  99. }
  100. /*****************************************************************************
  101. * CClusters::SetClusterEquivalent *
  102. *---------------------------------*
  103. * Description:
  104. *
  105. ******************************************************************* PACOG ***/
  106. int CClusters::SetClusterEquivalent (int iIndex, SegInfo* pSeginfo)
  107. {
  108. hashNode* node;
  109. m_pSegments[iIndex] = *pSeginfo;
  110. if ((node = m_hash.BuildEntry(m_pSegments[iIndex].clusterName)) == 0)
  111. {
  112. return 0;
  113. }
  114. node->m_equiv.push_back(&m_pSegments[iIndex]);
  115. return 1;
  116. }
  117. /*****************************************************************************
  118. * CClusters::GetEquivalentCount *
  119. *-------------------------------*
  120. * Description:
  121. *
  122. ******************************************************************* PACOG ***/
  123. int CClusters::GetEquivalentCount (const char* cluster)
  124. {
  125. if ((m_pFound = m_hash.Find(cluster)) != 0)
  126. {
  127. if (m_pFound->m_sRmsaver == 0.0)
  128. {
  129. if (!ComputeStats (m_pFound))
  130. {
  131. return 0;
  132. }
  133. }
  134. return m_pFound->m_equiv.size();
  135. }
  136. return 0;
  137. }
  138. /*****************************************************************************
  139. * CClusters::GetEquivalent *
  140. *--------------------------*
  141. * Description:
  142. *
  143. ******************************************************************* PACOG ***/
  144. SegInfo* CClusters::GetEquivalent(int index)
  145. {
  146. assert (m_pFound!=0);
  147. assert (index < m_pFound->m_equiv.size() );
  148. return m_pFound->m_equiv[index];
  149. }
  150. /*****************************************************************************
  151. * CClusters::GetBestExample *
  152. *---------------------------*
  153. * Description:
  154. *
  155. ******************************************************************* PACOG ***/
  156. SegInfo* CClusters::GetBestExample (const char* cluster)
  157. {
  158. int iNumEquiv;
  159. SegInfo* equiv;
  160. SegInfo* best = 0;
  161. double lklhood = m_dVerySmallProb;
  162. double f0dev;
  163. double rmsdev;
  164. double durdev;
  165. int i;
  166. assert (cluster);
  167. if ((iNumEquiv = GetEquivalentCount (cluster)) <=0)
  168. {
  169. return 0;
  170. }
  171. for (i=0; i<iNumEquiv; i++)
  172. {
  173. equiv = GetEquivalent (i);
  174. if (equiv->f0flag == 1 && m_pFound->m_sF0aver)
  175. {
  176. f0dev = fabs(equiv->f0 - m_pFound->m_sF0aver) / m_pFound->m_sF0aver;
  177. }
  178. else
  179. {
  180. f0dev = 0.0;
  181. }
  182. durdev = fabs(equiv->dur - m_pFound->m_fDuraver) / m_pFound->m_fDuraver;
  183. rmsdev = fabs(equiv->rms - m_pFound->m_sRmsaver) / m_pFound->m_sRmsaver;
  184. if ((durdev < 0.2) && (equiv->f0flag == m_pFound->m_sF0flag) && (f0dev < 0.2) && (rmsdev < 0.2))
  185. {
  186. if (equiv->lklhood > lklhood)
  187. {
  188. lklhood = equiv->lklhood;
  189. best = equiv;
  190. }
  191. }
  192. }
  193. if (best==NULL)
  194. {
  195. // Need to relax constraints and look some more?
  196. float durcon;
  197. float rmscon;
  198. for (rmscon = 0.1F ; best==NULL && rmscon < 2.0F; rmscon *= 2.0F)
  199. {
  200. for (durcon = 0.1F; best==NULL && durcon < 100.0F; durcon *= 2.0F)
  201. {
  202. lklhood = m_dVerySmallProb;
  203. for (i=0; i<iNumEquiv; i++)
  204. {
  205. durdev = (equiv->dur - m_pFound->m_fDuraver)/m_pFound->m_fDuraver;
  206. rmsdev = fabs(equiv->rms - m_pFound->m_sRmsaver)/m_pFound->m_sRmsaver;
  207. if ( (durdev >= 0.0) && (durdev < durcon) && (rmsdev < rmscon) )
  208. {
  209. if (equiv->lklhood > lklhood)
  210. {
  211. lklhood = equiv->lklhood;
  212. best = equiv;
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }
  219. return best;
  220. }
  221. /*****************************************************************************
  222. * CClusters::GetStats *
  223. *---------------------*
  224. * Description:
  225. *
  226. ******************************************************************* PACOG ***/
  227. int CClusters::GetStats (const char* cluster, int* f0Flag, double* f0Aver, double* rmsAver, double* durAver)
  228. {
  229. hashNode* clustFound;
  230. assert (cluster);
  231. if ((clustFound = m_hash.Find (cluster)) == 0)
  232. {
  233. return 0;
  234. }
  235. if (clustFound->m_sRmsaver == 0)
  236. {
  237. if (!ComputeStats (clustFound))
  238. {
  239. return 0;
  240. }
  241. }
  242. if (f0Flag)
  243. {
  244. *f0Flag = clustFound->m_sF0flag;
  245. }
  246. if (f0Aver)
  247. {
  248. *f0Aver = clustFound->m_sF0aver;
  249. }
  250. if (rmsAver)
  251. {
  252. *rmsAver = clustFound->m_sRmsaver;
  253. }
  254. if (durAver)
  255. {
  256. *durAver = clustFound->m_fDuraver;
  257. }
  258. return 1;
  259. }
  260. /*****************************************************************************
  261. * CClusters::LoadGainTable *
  262. *--------------------------*
  263. * Description:
  264. *
  265. ******************************************************************* PACOG ***/
  266. int CClusters::LoadGainTable (FILE* fin)
  267. {
  268. hashNode* clustFound;
  269. char cluster[MAX_CLUSTER_LEN];
  270. float dur;
  271. short rms;
  272. short f0flag;
  273. short f0;
  274. float likl;
  275. int nRec;
  276. int i;
  277. assert (fin);
  278. if (!fscanf (fin, "%d\n", &nRec))
  279. {
  280. return 0;
  281. }
  282. for (i = 0; i < nRec; i++)
  283. {
  284. fscanf(fin, "%s %f %hd %hd %hd %f\n", cluster, &dur, &f0flag, &f0, &rms, &likl);
  285. if ((clustFound = m_hash.Find(cluster)) == 0)
  286. {
  287. return 0;
  288. }
  289. clustFound->m_fDuraver = dur;
  290. clustFound->m_sRmsaver = rms;
  291. clustFound->m_sF0flag = f0flag;
  292. clustFound->m_sF0aver = f0;
  293. clustFound->m_fLikaver = likl;
  294. }
  295. return 1;
  296. }
  297. /*****************************************************************************
  298. * CClusters::ComputeStats *
  299. *-------------------------*
  300. * Description:
  301. *
  302. ******************************************************************* PACOG ***/
  303. int CClusters::ComputeStats (hashNode* cluster)
  304. {
  305. int hist[m_iHistMax];
  306. short *f0val;
  307. float *durval;
  308. float *likval;
  309. long rmsacum = 0;
  310. int iNumEquiv;
  311. int max;
  312. assert (cluster);
  313. memset (hist, 0, sizeof(hist));
  314. if ( (iNumEquiv = cluster->m_equiv.size()) > 0)
  315. {
  316. if ( (f0val = new short[iNumEquiv]) == 0 )
  317. {
  318. return 0;
  319. }
  320. if ( (durval = new float[iNumEquiv]) == 0 )
  321. {
  322. return 0;
  323. }
  324. if ( (likval = new float[iNumEquiv]) == 0 )
  325. {
  326. return 0;
  327. }
  328. for (int i=0; i<iNumEquiv; i++ )
  329. {
  330. f0val[i] = cluster->m_equiv[i]->f0;
  331. durval[i] = cluster->m_equiv[i]->dur;
  332. likval[i] = cluster->m_equiv[i]->lklhood;
  333. }
  334. qsort(f0val, iNumEquiv, sizeof(*f0val), ShortCmp);
  335. qsort(durval, iNumEquiv, sizeof(*durval), FloatCmp);
  336. qsort(likval, iNumEquiv, sizeof(*likval), FloatCmp);
  337. cluster->m_sF0aver = f0val[iNumEquiv/2];
  338. cluster->m_fDuraver = durval[iNumEquiv/2];
  339. cluster->m_fLikaver = likval[iNumEquiv/2];
  340. delete[] f0val;
  341. delete[] durval;
  342. delete[] likval;
  343. for (i=0; i<iNumEquiv; i++)
  344. {
  345. rmsacum += cluster->m_equiv[i]->rms;
  346. hist[cluster->m_equiv[i]->f0flag + 2]++;
  347. }
  348. cluster->m_sRmsaver = rmsacum/iNumEquiv;
  349. cluster->m_sF0flag = 0;
  350. max = 0;
  351. for (i=0; i<m_iHistMax; i++)
  352. {
  353. if (hist[i]>max)
  354. {
  355. max = hist[i];
  356. cluster->m_sF0flag = i-2;
  357. }
  358. }
  359. }
  360. return 1;
  361. }
  362. /*****************************************************************************
  363. * hashNode::hashNode *
  364. *--------------------*
  365. * Description:
  366. *
  367. ******************************************************************* PACOG ***/
  368. hashNode::hashNode()
  369. {
  370. m_pszKey = 0;
  371. m_sF0flag = 0;
  372. m_sF0aver = 0;
  373. m_sRmsaver = 0;
  374. m_fDuraver = 0.0;
  375. m_fLikaver = 0.0;
  376. m_pNext = 0;
  377. }
  378. /*****************************************************************************
  379. * CHash::HashValue *
  380. *------------------*
  381. * Description:
  382. *
  383. ******************************************************************* PACOG ***/
  384. unsigned int CHash::HashValue (unsigned char *name)
  385. {
  386. assert (name);
  387. for (unsigned int h=0; *name ; name++)
  388. {
  389. h = (64*h + *name) % HASHSIZE;
  390. }
  391. return h;
  392. }
  393. /*****************************************************************************
  394. * CHash::CHash *
  395. *--------------*
  396. * Description:
  397. *
  398. ******************************************************************* PACOG ***/
  399. CHash::CHash()
  400. {
  401. memset (m_ppHeads, 0, sizeof(m_ppHeads));
  402. }
  403. /*****************************************************************************
  404. * CHash::~CHash *
  405. *---------------*
  406. * Description:
  407. *
  408. ******************************************************************* PACOG ***/
  409. CHash::~CHash ()
  410. {
  411. hashNode* busy;
  412. hashNode* empty;
  413. for (int i=0; i<HASHSIZE; i++)
  414. {
  415. busy = m_ppHeads[i];
  416. while (busy->m_pNext)
  417. {
  418. empty = busy;
  419. busy = busy->m_pNext;
  420. delete empty;
  421. }
  422. delete busy;
  423. }
  424. }
  425. /*****************************************************************************
  426. * CHash::Init *
  427. *-------------*
  428. * Description:
  429. *
  430. ******************************************************************* PACOG ***/
  431. bool CHash::Init ()
  432. {
  433. for (int i=0; i < HASHSIZE; i++)
  434. {
  435. if ( (m_ppHeads[i] = new hashNode) == 0)
  436. {
  437. return false;
  438. }
  439. }
  440. return true;
  441. }
  442. /*****************************************************************************
  443. * CHash::BuildEntry *
  444. *-------------------*
  445. * Description:
  446. *
  447. ******************************************************************* PACOG ***/
  448. struct hashNode* CHash::BuildEntry (const char *name)
  449. {
  450. hashNode* x;
  451. hashNode* t;
  452. assert (name);
  453. if (name && *name)
  454. {
  455. t = m_ppHeads[ HashValue((unsigned char*)name)];
  456. while (t->m_pNext)
  457. {
  458. if (strcmp (t->m_pNext->m_pszKey, name) == 0)
  459. {
  460. break;
  461. }
  462. t = t->m_pNext;
  463. }
  464. if (t->m_pNext)
  465. {
  466. return t->m_pNext;
  467. }
  468. if ((x = new hashNode) != 0)
  469. {
  470. x->m_pNext = t->m_pNext;
  471. t->m_pNext = x;
  472. x->m_pszKey = name;
  473. return x;
  474. }
  475. }
  476. return 0;
  477. }
  478. /*****************************************************************************
  479. * CHash::Find *
  480. *-------------*
  481. * Description:
  482. *
  483. ******************************************************************* PACOG ***/
  484. hashNode* CHash::Find (const char *name)
  485. {
  486. hashNode* t;
  487. assert (name);
  488. t = m_ppHeads[HashValue((unsigned char*)name)];
  489. while (t->m_pNext)
  490. {
  491. if ( strcmp(t->m_pNext->m_pszKey, name) == 0 )
  492. {
  493. return t->m_pNext;
  494. }
  495. t = t->m_pNext;
  496. }
  497. return 0;
  498. }
  499. /*****************************************************************************
  500. * CHash::NextEntry *
  501. *------------------*
  502. * Description:
  503. *
  504. ******************************************************************* PACOG ***/
  505. hashNode* CHash::NextEntry(int* idx1, int* idx2)
  506. {
  507. hashNode* node;
  508. int i;
  509. assert (idx1);
  510. assert (idx2);
  511. while (*idx1 < HASHSIZE )
  512. {
  513. if ((node = m_ppHeads[*idx1]->m_pNext) != 0)
  514. {
  515. for ( i=0; i<*idx2 && node->m_pNext; i++)
  516. {
  517. node = node->m_pNext;
  518. }
  519. if (i==*idx2)
  520. {
  521. (*idx2)++;
  522. return node;
  523. }
  524. }
  525. (*idx1)++;
  526. *idx2 = 0;
  527. }
  528. return 0;
  529. }
  530. /*****************************************************************************
  531. * CClusters::Debug *
  532. *------------------*
  533. * Description:
  534. *
  535. ******************************************************************* PACOG ***/
  536. void CClusters::Debug()
  537. {
  538. for (int i=0; i<m_iNumSegments; i++)
  539. {
  540. printf ("%s %d %d %f %f %d %d %d %f %d %d\n",
  541. m_pSegments[i].clusterName,
  542. m_pSegments[i].chunkIdx,
  543. m_pSegments[i].f0flag,
  544. m_pSegments[i].start,
  545. m_pSegments[i].dur,
  546. m_pSegments[i].f0,
  547. m_pSegments[i].rms,
  548. m_pSegments[i].lklhood,
  549. m_pSegments[i].leftVqIdx,
  550. m_pSegments[i].rightVqIdx);
  551. }
  552. }
  553. /*****************************************************************************
  554. * CClusters::PreComputeDist *
  555. *---------------------------*
  556. * Description:
  557. * Pre-compute some of the distances used in the dynamic search of units
  558. ******************************************************************* PACOG ***/
  559. int CClusters::PreComputeDist(double dDurWeight, double dRmsWeight, double dLklhoodWeight)
  560. {
  561. hashNode* cluster;
  562. double durDev;
  563. double rmsDev;
  564. double lklhood;
  565. for (int i=0; i<m_iNumSegments; i++)
  566. {
  567. if ((cluster = m_hash.Find (m_pSegments[i].clusterName)) == 0)
  568. {
  569. return 0;
  570. }
  571. if (cluster->m_fDuraver == 0)
  572. {
  573. ComputeStats (cluster);
  574. }
  575. durDev = fabs(m_pSegments[i].dur - cluster->m_fDuraver)/cluster->m_fDuraver;
  576. rmsDev = fabs(m_pSegments[i].rms - cluster->m_sRmsaver)/cluster->m_sRmsaver;
  577. lklhood = -(m_pSegments[i].lklhood - cluster->m_fLikaver) * sqrt(m_pSegments[i].dur);
  578. m_pSegments[i].repDist = dDurWeight * durDev + dRmsWeight * rmsDev + dLklhoodWeight * lklhood;
  579. }
  580. return 1;
  581. }
  582. /*****************************************************************************
  583. * CClusters::FloatCmp *
  584. *---------------------*
  585. * Description:
  586. *
  587. ******************************************************************* PACOG ***/
  588. int CClusters::FloatCmp ( const void *a, const void *b )
  589. {
  590. float acum;
  591. assert (a);
  592. assert (b);
  593. acum = *((float*)a) - *((float*)b);
  594. if ( acum>0.0)
  595. {
  596. return 1;
  597. }
  598. if ( acum<0.0)
  599. {
  600. return -1;
  601. }
  602. return 0;
  603. }
  604. /*****************************************************************************
  605. * CClusters::ShortCmp *
  606. *---------------------*
  607. * Description:
  608. *
  609. ******************************************************************* PACOG ***/
  610. int CClusters::ShortCmp ( const void *a, const void *b )
  611. {
  612. assert (a);
  613. assert (b);
  614. return *((short*)a) - *((short*)b);
  615. }