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.

1814 lines
57 KiB

  1. /*******************************************************************************
  2. * VoiceDataObj.cpp *
  3. *------------------*
  4. * Description:
  5. * This module is the main implementation file for the CVoiceData class.
  6. *-------------------------------------------------------------------------------
  7. * Created By: EDC Date: 05/06/99
  8. * Copyright (C) 1999 Microsoft Corporation
  9. * All Rights Reserved
  10. *
  11. *******************************************************************************/
  12. //--- Additional includes
  13. #include "stdafx.h"
  14. #include "VoiceDataObj.h"
  15. /*****************************************************************************
  16. * CVoiceData::FinalConstruct *
  17. *-------------------------------*
  18. * Description:
  19. * Constructor
  20. ********************************************************************* EDC ***/
  21. CVoiceData::CVoiceData()
  22. {
  23. //--- Init vars
  24. m_hVoiceDef = NULL;
  25. m_hVoiceData = NULL;
  26. m_pVoiceData = NULL;
  27. m_pVoiceDef = NULL;
  28. } /* CVoiceData::FinalConstruct */
  29. /*****************************************************************************
  30. * CVoiceData::FinalRelease *
  31. *-----------------------------*
  32. * Description:
  33. * destructor
  34. ********************************************************************* EDC ***/
  35. CVoiceData::~CVoiceData()
  36. {
  37. SPDBG_FUNC( "CVoiceData::FinalRelease" );
  38. if( m_pVoiceDef )
  39. {
  40. ::UnmapViewOfFile( (void*)m_pVoiceDef );
  41. }
  42. if( m_pVoiceData )
  43. {
  44. ::UnmapViewOfFile( (void*)m_pVoiceData );
  45. }
  46. if( m_hVoiceDef ) ::CloseHandle( m_hVoiceDef );
  47. if( m_hVoiceData ) ::CloseHandle( m_hVoiceData );
  48. } /* CVoiceData::FinalRelease */
  49. /*****************************************************************************
  50. * CVoiceData::MapFile *
  51. *------------------------*
  52. * Description:
  53. * Helper function used by SetObjectToken to map file. This function
  54. * assumes that m_cpToken has been initialized.+++
  55. ********************************************************************* RAL ***/
  56. HRESULT CVoiceData::MapFile( const WCHAR * pszTokenVal, // Value that contains file path
  57. HANDLE * phMapping, // Pointer to file mapping handle
  58. void ** ppvData ) // Pointer to the data
  59. {
  60. HRESULT hr = S_OK;
  61. bool fWorked;
  62. CSpDynamicString dstrFilePath;
  63. hr = m_cpToken->GetStringValue( pszTokenVal, &dstrFilePath );
  64. if ( SUCCEEDED( hr ) )
  65. {
  66. fWorked = false;
  67. *phMapping = NULL;
  68. *ppvData = NULL;
  69. HANDLE hFile;
  70. #ifndef _WIN32_WCE
  71. hFile = g_Unicode.CreateFile(
  72. dstrFilePath,
  73. GENERIC_READ,
  74. FILE_SHARE_READ,
  75. NULL,
  76. OPEN_EXISTING,
  77. FILE_ATTRIBUTE_NORMAL,
  78. NULL );
  79. #else //_WIN32_WCE
  80. hFile = g_Unicode.CreateFileForMapping(
  81. dstrFilePath,
  82. GENERIC_READ,
  83. FILE_SHARE_READ,
  84. NULL,
  85. OPEN_EXISTING,
  86. FILE_ATTRIBUTE_NORMAL,
  87. NULL );
  88. #endif //_WIN32_WCE
  89. if (hFile != INVALID_HANDLE_VALUE)
  90. {
  91. //-------------------------------------
  92. // Make a unique map name from path
  93. //-------------------------------------
  94. long i;
  95. for( i = 0; i < _MAX_PATH-1; i++ )
  96. {
  97. if( dstrFilePath[i] == 0 )
  98. {
  99. // End of string
  100. break;
  101. }
  102. if( dstrFilePath[i] == '\\' )
  103. {
  104. //-------------------------------------
  105. // Change backslash to underscore
  106. //-------------------------------------
  107. dstrFilePath[i] = '_';
  108. }
  109. }
  110. *phMapping = g_Unicode.CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, dstrFilePath );
  111. ::CloseHandle( hFile );
  112. }
  113. if (*phMapping)
  114. {
  115. *ppvData = ::MapViewOfFile( *phMapping, FILE_MAP_READ, 0, 0, 0 );
  116. if (*ppvData)
  117. {
  118. fWorked = true;
  119. }
  120. }
  121. if (!fWorked)
  122. {
  123. hr = HRESULT_FROM_WIN32(::GetLastError());
  124. if (hr == E_HANDLE)
  125. {
  126. hr &= 0xFFFFF000;
  127. hr |= ERROR_FILE_NOT_FOUND;
  128. }
  129. if (*phMapping)
  130. {
  131. ::CloseHandle(*phMapping);
  132. *phMapping = NULL;
  133. }
  134. }
  135. }
  136. return hr;
  137. } /* CVoiceData::MapFile */
  138. /*****************************************************************************
  139. * CVoiceData::SetObjectToken *
  140. *-------------------------------*
  141. * Description:
  142. * This function performs the majority of the initialization of the voice.
  143. * Once the object token has been provided, the filenames are read from the
  144. * token key and the files are mapped.+++
  145. ********************************************************************* RAL ***/
  146. STDMETHODIMP CVoiceData::SetObjectToken(ISpObjectToken * pToken)
  147. {
  148. SPDBG_FUNC( "CVoiceData::SetObjectToken" );
  149. HRESULT hr = S_OK;
  150. m_cpToken = pToken;
  151. if ( SUCCEEDED( hr ) )
  152. {
  153. hr = MapFile( L"VoiceDef", &m_hVoiceDef, (void **)&m_pVoiceDef );
  154. }
  155. if ( SUCCEEDED( hr ) )
  156. {
  157. hr = MapFile( L"VoiceData", &m_hVoiceData, (void **)&m_pVoiceData );
  158. }
  159. //--- Init voice data pointers
  160. if (SUCCEEDED(hr))
  161. {
  162. hr = InitVoiceData();
  163. }
  164. return hr;
  165. } /* CVoiceData::SetObjectToken */
  166. /*****************************************************************************
  167. * CVoiceData::GetVoiceInfo *
  168. *-----------------------------*
  169. * Description:
  170. * This method is used to retrieve the voice file data description.+++
  171. ********************************************************************* EDC ***/
  172. STDMETHODIMP CVoiceData::GetVoiceInfo( MSVOICEINFO* pVoiceInfo )
  173. {
  174. SPDBG_FUNC( "CVoiceData::GetVoiceInfo" );
  175. HRESULT hr = S_OK;
  176. long i;
  177. //--- Check args
  178. if( ( SP_IS_BAD_WRITE_PTR( pVoiceInfo ) ) || ( m_pVoiceDef == NULL ) )
  179. {
  180. hr = E_INVALIDARG;
  181. }
  182. else
  183. {
  184. if (!m_cpToken)
  185. {
  186. hr = SPERR_UNINITIALIZED;
  187. }
  188. else
  189. {
  190. pVoiceInfo->pWindow = m_pWindow;
  191. pVoiceInfo->FFTSize = m_FFTSize;
  192. pVoiceInfo->LPCOrder = m_cOrder;
  193. pVoiceInfo->ProsodyGain = m_pVoiceDef->ProsodyGain;
  194. pVoiceInfo->eReverbType = m_pVoiceDef->ReverbType;
  195. pVoiceInfo->Pitch = m_pVoiceDef->Pitch;
  196. pVoiceInfo->Rate = m_pVoiceDef->Rate;
  197. pVoiceInfo->LangID = m_pVoiceDef->LangID;
  198. pVoiceInfo->SampleRate = m_pVoiceDef->SampleRate;
  199. pVoiceInfo->VibratoFreq = m_pVoiceDef->VibratoFreq;
  200. pVoiceInfo->VibratoDepth = m_pVoiceDef->VibratoDepth;
  201. pVoiceInfo->NumOfTaps = m_pVoiceDef->NumOfTaps;
  202. // Assumes voices are ALWAYS 16-bit mono (probably valid for now)***
  203. pVoiceInfo->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
  204. pVoiceInfo->WaveFormatEx.nSamplesPerSec = pVoiceInfo->SampleRate;
  205. pVoiceInfo->WaveFormatEx.wBitsPerSample = 16; // ***
  206. pVoiceInfo->WaveFormatEx.nChannels = 1; // ***
  207. pVoiceInfo->WaveFormatEx.nBlockAlign = (unsigned short)(pVoiceInfo->WaveFormatEx.nChannels * sizeof(short)); // ***
  208. pVoiceInfo->WaveFormatEx.nAvgBytesPerSec = pVoiceInfo->WaveFormatEx.nSamplesPerSec * pVoiceInfo->WaveFormatEx.nBlockAlign;
  209. pVoiceInfo->WaveFormatEx.cbSize = 0;
  210. for (i = 0; i < MAXTAPS; i++)
  211. {
  212. pVoiceInfo->TapCoefficients[i] = m_pVoiceDef->TapCoefficients[i];
  213. }
  214. }
  215. }
  216. return hr;
  217. } /* CVoiceData::GetVoiceInfo */
  218. /*****************************************************************************
  219. * CVoiceData::GetUnit *
  220. *------------------------*
  221. * Description:
  222. * Retrieves and uncompresses audio data from the unit inventory. +++
  223. *
  224. ********************************************************************* EDC ***/
  225. STDMETHODIMP CVoiceData::GetUnitData( ULONG unitID, MSUNITDATA* pUnitData )
  226. {
  227. SPDBG_FUNC( "CVoiceData::GetUnit" );
  228. HRESULT hr = S_OK;
  229. //--- Check args
  230. if( SP_IS_BAD_WRITE_PTR( pUnitData ) )
  231. {
  232. hr = E_INVALIDARG;
  233. }
  234. else if( unitID > m_NumOfUnits )
  235. {
  236. //--------------------------
  237. // ID is out of range!
  238. //--------------------------
  239. hr = E_INVALIDARG;
  240. }
  241. else
  242. {
  243. if (!m_cpToken)
  244. {
  245. hr = SPERR_UNINITIALIZED;
  246. }
  247. else
  248. {
  249. if( m_CompressionType != COMPRESS_LPC )
  250. {
  251. //--------------------------------------
  252. // Unsupported compression type
  253. //--------------------------------------
  254. hr = E_FAIL;
  255. }
  256. else
  257. {
  258. //-------------------------------------------------------------------
  259. // Retrieve data from compressed inventory
  260. //-------------------------------------------------------------------
  261. hr = DecompressUnit( unitID, pUnitData );
  262. }
  263. }
  264. }
  265. return hr;
  266. } /* CVoiceData::GetUnit */
  267. /*****************************************************************************
  268. * CVoiceData::AlloToUnit *
  269. *---------------------------*
  270. * Description:
  271. * Converts FE allo code to BE unit phon code.+++
  272. *
  273. ********************************************************************* EDC ***/
  274. STDMETHODIMP CVoiceData::AlloToUnit( short allo, long attributes, long* pUnitID )
  275. {
  276. SPDBG_FUNC( "CVoiceData::AlloToUnit" );
  277. HRESULT hr = S_OK;
  278. long index;
  279. union {
  280. char c[2];
  281. short s;
  282. } temp;
  283. char* pb;
  284. //--- Check args
  285. if( (SP_IS_BAD_READ_PTR( pUnitID )) || (allo >= m_NumOfAllos) )
  286. {
  287. hr = E_INVALIDARG;
  288. }
  289. else
  290. {
  291. index = (long)allo << 1; // 2 entries per phon
  292. if( attributes & ALLO_IS_STRESSED )
  293. {
  294. //--- 2nd half
  295. pb = (char*) &m_AlloToUnitTbl[index + (m_NumOfAllos << 1)];
  296. }
  297. else
  298. {
  299. pb = (char*) &m_AlloToUnitTbl[index];
  300. }
  301. // We read this way to avoid missaligned data accesses in 64bit.
  302. temp.c[0] = *pb++;
  303. temp.c[1] = *pb;
  304. *pUnitID = (long) temp.s;
  305. }
  306. return hr;
  307. } /* CVoiceData::AlloToUnit */
  308. /*****************************************************************************
  309. * CVoiceData::GetUnitIDs *
  310. *---------------------------*
  311. * Description:
  312. * Gets the inventory triphone (in context) unit code.+++
  313. *
  314. ********************************************************************* EDC ***/
  315. STDMETHODIMP CVoiceData::GetUnitIDs( UNIT_CVT* pUnits, ULONG cUnits )
  316. {
  317. SPDBG_FUNC( "CVoiceData::GetUnitIDs" );
  318. ULONG i;
  319. ULONG curID, prevID, nextID;
  320. ULONG curF, prevF, nextF;
  321. char cPos;
  322. ULONG senoneID;
  323. UNALIGNED UNIT_STATS *pStats;
  324. HRESULT hr = S_OK;
  325. //--- Check args
  326. if( (SP_IS_BAD_READ_PTR( pUnits)) ||
  327. (SP_IS_BAD_WRITE_PTR( pUnits)) )
  328. {
  329. hr = E_INVALIDARG;
  330. }
  331. else
  332. {
  333. if (!m_cpToken)
  334. {
  335. hr = SPERR_UNINITIALIZED;
  336. }
  337. else
  338. {
  339. for( i = 0; i < cUnits; i++ )
  340. {
  341. //---------------------------
  342. // CURRENT phon
  343. //---------------------------
  344. curID = pUnits[i].PhonID;
  345. curF = pUnits[i].flags;
  346. //---------------------------
  347. // PREVIOUS phon
  348. //---------------------------
  349. if( i == 0 )
  350. {
  351. prevID = m_Sil_Index;
  352. prevF = 0;
  353. }
  354. else
  355. {
  356. prevID = pUnits[i-1].PhonID;
  357. prevF = pUnits[i-1].flags;
  358. }
  359. //---------------------------
  360. // NEXT phon
  361. //---------------------------
  362. if( i >= cUnits -1 )
  363. {
  364. nextID = m_Sil_Index;
  365. nextF = 0;
  366. }
  367. else
  368. {
  369. nextID = pUnits[i+1].PhonID;
  370. nextF = pUnits[i+1].flags;
  371. }
  372. if( curID == m_Sil_Index )
  373. {
  374. //----------------------
  375. // SILENCE phon
  376. //----------------------
  377. pUnits[i].UnitID = 0;
  378. pUnits[i].SenoneID = 0;
  379. pUnits[i].szUnitName[0] = 0;
  380. pUnits[i].Dur = SIL_DURATION;
  381. pUnits[i].Amp = 0;
  382. pUnits[i].AmpRatio = 1.0f;
  383. }
  384. else
  385. {
  386. cPos = '\0';
  387. if( curF & WORD_START_FLAG )
  388. {
  389. if( nextF & WORD_START_FLAG )
  390. //---------------------------------------
  391. // Both Cur and Next are word start
  392. //---------------------------------------
  393. cPos = 's';
  394. else
  395. //---------------------------------------
  396. // Cur is word start
  397. // Next is not
  398. //---------------------------------------
  399. cPos = 'b';
  400. }
  401. else if( nextF & WORD_START_FLAG )
  402. {
  403. //---------------------------------------
  404. // Next is word start
  405. // Cur is not
  406. //---------------------------------------
  407. cPos = 'e';
  408. }
  409. HRESULT hrt;
  410. hrt = GetTriphoneID( m_pForest,
  411. curID,
  412. prevID,
  413. nextID,
  414. cPos,
  415. m_pd,
  416. &senoneID);
  417. if( FAILED(hrt) )
  418. {
  419. //------------------------------------------------
  420. // Instead of failing, I'll be robust and ignore
  421. // the error. Force triphone to something that's
  422. // valid.
  423. //------------------------------------------------
  424. senoneID = 0;
  425. }
  426. pUnits[i].UnitID = (m_pForest->gsOffset[curID] -
  427. m_First_Context_Phone) + (senoneID + 1);
  428. pUnits[i].SenoneID = senoneID;
  429. //-----------------------------
  430. // Get phon name strings
  431. //-----------------------------
  432. char *pName;
  433. pName = PhonFromID( m_pd, pUnits[i].PhonID );
  434. strcpy( &pUnits[i].szUnitName[0], pName );
  435. //-----------------------------
  436. // Get unit stats
  437. //-----------------------------
  438. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  439. pStats = &pStats[senoneID+1];
  440. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  441. pStats = &pStats[senoneID-1];
  442. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  443. pStats = &pStats[senoneID];
  444. pUnits[i].Dur = pStats->dur / 1000.0f; // ms -> sec
  445. pUnits[i].Amp = pStats->amp;
  446. pUnits[i].AmpRatio = (float)sqrt(pStats->ampRatio);
  447. //----------------------------------------------------------
  448. // Looks like the "SENONE" table durations are
  449. // incorrect (not even close!).
  450. // Calc the real duration from inv epochs
  451. // TODO: Make new table in voice data block
  452. //----------------------------------------------------------
  453. //hr = GetUnitDur( pUnits[i].UnitID, &pUnits[i].Dur );
  454. if( FAILED(hr) )
  455. {
  456. break;
  457. }
  458. }
  459. }
  460. }
  461. }
  462. return hr;
  463. } /* CVoiceData::GetUnitIDs */
  464. /*****************************************************************************
  465. * GetDataBlock *
  466. *--------------*
  467. * Description:
  468. * Return ptr and length of specified voice data block. +++
  469. *
  470. ********************************************************************** MC ***/
  471. HRESULT CVoiceData::GetDataBlock( VOICEDATATYPE type, char **ppvOut, ULONG *pdwSize )
  472. {
  473. SPDBG_FUNC( "CVoiceData::GetDataBlock" );
  474. long *offs;
  475. HRESULT hr = S_OK;
  476. long dataType;
  477. if( !m_pVoiceData )
  478. {
  479. hr = E_INVALIDARG;
  480. }
  481. else
  482. {
  483. dataType = (long)type * 2; // x2 since each entry is an offset/length pair
  484. offs = (long*)&m_pVoiceData->PhonOffset; // Table start
  485. *ppvOut = offs[dataType] + ((char*)m_pVoiceData); // Offset -> abs address
  486. *pdwSize = offs[dataType + 1];
  487. }
  488. return hr;
  489. } /* CVoiceData::GetDataBlock */
  490. /*****************************************************************************
  491. * InitVoiceData *
  492. *---------------*
  493. * Description:
  494. * Create pointers to voice data blocks from m_pVoiceData offsets.+++
  495. *
  496. ********************************************************************** MC ***/
  497. HRESULT CVoiceData::InitVoiceData()
  498. {
  499. SPDBG_FUNC( "CVoiceData::InitVoiceData" );
  500. char *pRawData;
  501. ULONG dataSize;
  502. HRESULT hr = S_OK;
  503. //------------------------------------------
  504. // Check data type and version
  505. //------------------------------------------
  506. if( (m_pVoiceData != NULL)
  507. && (m_pVoiceData->Type == MS_DATA_TYPE)
  508. && (m_pVoiceData->Version == HEADER_VERSION) )
  509. {
  510. //-------------------------------
  511. // Get ptr to PHONs
  512. //-------------------------------
  513. hr = GetDataBlock( MSVD_PHONE, &pRawData, &dataSize );
  514. m_pd = (PHON_DICT*)pRawData;
  515. //-------------------------------
  516. // Get ptr to TREE
  517. //-------------------------------
  518. if( SUCCEEDED(hr) )
  519. {
  520. hr = GetDataBlock( MSVD_TREEIMAGE, &pRawData, &dataSize );
  521. m_pForest = (TRIPHONE_TREE*)pRawData;
  522. }
  523. //-------------------------------
  524. // Get ptr to SENONE
  525. //-------------------------------
  526. if( SUCCEEDED(hr) )
  527. {
  528. hr = GetDataBlock( MSVD_SENONE, &pRawData, &dataSize );
  529. m_SenoneBlock = (long*)pRawData;
  530. }
  531. //-------------------------------
  532. // Get ptr to ALLOID
  533. //-------------------------------
  534. if( SUCCEEDED(hr) )
  535. {
  536. hr = GetDataBlock( MSVD_ALLOID, &pRawData, &dataSize );
  537. m_AlloToUnitTbl = (short*)pRawData;
  538. m_NumOfAllos = dataSize / 8;
  539. }
  540. if( SUCCEEDED(hr) )
  541. {
  542. m_First_Context_Phone = m_pd->numCiPhones;
  543. m_Sil_Index = PhonToID( m_pd, "SIL" );
  544. }
  545. //-----------------------------------------------------
  546. // Init voice data INVENTORY parameters
  547. //-----------------------------------------------------
  548. if( SUCCEEDED(hr) )
  549. {
  550. hr = GetDataBlock( MSVD_INVENTORY, &pRawData, &dataSize );
  551. if( SUCCEEDED(hr) )
  552. {
  553. m_pInv = (INVENTORY*)pRawData;
  554. m_CompressionType = m_pVoiceDef->CompressionType;
  555. //---------------------------------------------
  556. // Convert REL to ABS
  557. //---------------------------------------------
  558. m_pUnit = (long*)((char*)m_pInv + m_pInv->UnitsOffset);
  559. m_pTrig = (float*)((char*)m_pInv + m_pInv->TrigOffset);
  560. m_pWindow = (float*)((char*)m_pInv + m_pInv->WindowOffset);
  561. m_pGauss = (float*)((char*)m_pInv + m_pInv->pGaussOffset);
  562. m_SampleRate = (float)m_pInv->SampleRate;
  563. m_FFTSize = m_pInv->FFTSize;
  564. m_cOrder = m_pInv->cOrder;
  565. m_GaussID = 0;
  566. m_NumOfUnits = m_pInv->cNumUnits;
  567. }
  568. }
  569. }
  570. else
  571. {
  572. //-------------------------
  573. // Not a voice file!
  574. //-------------------------
  575. hr = E_FAIL;
  576. }
  577. return hr;
  578. } /* CVoiceData::InitVoiceData */
  579. /*****************************************************************************
  580. * CVoiceData::DecompressUnit *
  581. *-------------------------------*
  582. * Description:
  583. * Decompress acoustic unit.+++
  584. *
  585. * INPUT:
  586. * UnitID - unit number (1 - 3333 typ)
  587. *
  588. * OUTPUT:
  589. * Fills pSynth if success
  590. *
  591. ********************************************************************** MC ***/
  592. HRESULT CVoiceData::DecompressUnit( ULONG UnitID, MSUNITDATA* pSynth )
  593. {
  594. SPDBG_FUNC( "CVoiceData::DecompressUnit" );
  595. long i, j, k, cNumEpochs, cBytes, cOrder = 0, VectDim;
  596. long frameSize, cNumBins, startBin;
  597. char *pCurStor;
  598. unsigned char index;
  599. float pLSP[MAX_LPCORDER], pFFT[MAX_FFTSIZE], pRes[MAX_FFTSIZE], Gain;
  600. float *pCurLSP, *pCurLPC, *pMean, *pCurRes;
  601. HRESULT hr = S_OK;
  602. memset( pSynth, 0, sizeof(MSUNITDATA) );
  603. //-----------------------------------------
  604. // Pointer to unit data from inventory
  605. //-----------------------------------------
  606. pCurStor = (char*)((char*)m_pInv + m_pUnit[UnitID] ); // Rel to abs
  607. //---------------------------------
  608. // Get epoch count - 'cNumEpochs'
  609. //---------------------------------
  610. cBytes = sizeof(long);
  611. memcpy( &cNumEpochs, pCurStor, cBytes );
  612. pSynth->cNumEpochs = cNumEpochs;
  613. pCurStor += cBytes;
  614. //---------------------------------
  615. // Get epoch lengths - 'pEpoch'
  616. //---------------------------------
  617. pSynth->pEpoch = new float[cNumEpochs];
  618. if( pSynth->pEpoch == NULL )
  619. {
  620. hr = E_OUTOFMEMORY;
  621. }
  622. if( SUCCEEDED(hr) )
  623. {
  624. cBytes = DecompressEpoch( (signed char *) pCurStor, cNumEpochs, pSynth->pEpoch );
  625. pCurStor += cBytes;
  626. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  627. //
  628. // Uncompress LPC coefficients...
  629. //
  630. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  631. cOrder = m_pInv->cOrder;
  632. pSynth->cOrder = cOrder;
  633. pSynth->pLPC = new float[cNumEpochs * (1 + cOrder)];
  634. if( pSynth->pLPC == NULL )
  635. {
  636. hr = E_OUTOFMEMORY;
  637. }
  638. }
  639. if( SUCCEEDED(hr) )
  640. {
  641. pCurLPC = pSynth->pLPC;
  642. //---------------------------------
  643. // ... for each epoch
  644. //---------------------------------
  645. for( i = 0; i < cNumEpochs; i++, pCurLPC += (1 + cOrder) )
  646. {
  647. //-------------------------------------
  648. // Decode quantized LSP's...
  649. //-------------------------------------
  650. pCurLSP = pLSP;
  651. for( k = 0; k < m_pInv->cNumLPCBooks; k++ )
  652. {
  653. VectDim = m_pInv->LPCBook[k].cCodeDim;
  654. memcpy( &index, pCurStor, sizeof(char));
  655. pCurStor += sizeof(char);
  656. pMean = ((float*)((char*)m_pInv + m_pInv->LPCBook[k].pData)) + (index * VectDim);
  657. for( j = 0; j < VectDim; j++ )
  658. pCurLSP[j] = pMean[j];
  659. pCurLSP += VectDim;
  660. }
  661. //--------------------------------------------------
  662. // ...then convert to predictor coefficients
  663. // (LSP's quantize better than PC's)
  664. //--------------------------------------------------
  665. LSPtoPC( pLSP, pCurLPC, cOrder, i );
  666. }
  667. //---------------------------------------
  668. // Get pointer to residual gains
  669. //---------------------------------------
  670. cBytes = cNumEpochs * sizeof(float);
  671. pSynth->pGain = (float*) pCurStor;
  672. pCurStor += cBytes;
  673. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  674. //
  675. // Uncompress residual waveform
  676. //
  677. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  678. //--------------------------------------------
  679. // First, figure out the buffer length...
  680. //--------------------------------------------
  681. pSynth->cNumSamples = 0;
  682. for( j = 0; j < cNumEpochs; j++ )
  683. {
  684. pSynth->cNumSamples += (long) ABS(pSynth->pEpoch[j]);
  685. }
  686. //--------------------------------------------
  687. // ...get buffer memory...
  688. //--------------------------------------------
  689. pSynth->pRes = new float[pSynth->cNumSamples];
  690. if( pSynth->pRes == NULL )
  691. {
  692. hr = E_OUTOFMEMORY;
  693. }
  694. }
  695. if( SUCCEEDED(hr) )
  696. {
  697. //--------------------------------------------
  698. // ...and fill with uncompressed residual
  699. //--------------------------------------------
  700. pCurRes = pSynth->pRes;
  701. for( i = 0; i < (long)pSynth->cNumEpochs; i++ )
  702. {
  703. //-------------------------------------
  704. // Get epoch length
  705. //-------------------------------------
  706. frameSize = (long)(ABS(pSynth->pEpoch[i]));
  707. // restore whisper
  708. //if( (pSynth->pEpoch[i] > 0) && !(m_fModifiers & BACKEND_BITFLAG_WHISPER) )
  709. if( pSynth->pEpoch[i] > 0 )
  710. {
  711. //-----------------------------------------------
  712. // VOICED epoch
  713. //-----------------------------------------------
  714. if( (m_pInv->cNumDresBooks == 0) || (i == 0) || (pSynth->pEpoch[i - 1] < 0) )
  715. {
  716. //--------------------------------------
  717. // Do static quantization
  718. //--------------------------------------
  719. for( j = 0; j < m_pInv->FFTSize; j++ )
  720. {
  721. pFFT[j] = 0.0f;
  722. }
  723. startBin = 1;
  724. for( k = 0; k < m_pInv->cNumResBooks; k++ )
  725. {
  726. VectDim = m_pInv->ResBook[k].cCodeDim;
  727. cNumBins = VectDim / 2;
  728. memcpy( &index, pCurStor, sizeof(char) );
  729. pCurStor += sizeof(char);
  730. //------------------------------------------
  731. // Uncompress spectrum using 'pResBook'
  732. //------------------------------------------
  733. pMean = ((float*)((char*)m_pInv + m_pInv->ResBook[k].pData)) + (index * VectDim);
  734. PutSpectralBand( pFFT, pMean, startBin, cNumBins, m_pInv->FFTSize );
  735. startBin += cNumBins;
  736. }
  737. }
  738. else
  739. {
  740. //--------------------------------------
  741. // Do delta quantization
  742. //--------------------------------------
  743. startBin = 1;
  744. for( k = 0; k < m_pInv->cNumDresBooks; k++ )
  745. {
  746. VectDim = m_pInv->DresBook[k].cCodeDim;
  747. cNumBins = VectDim / 2;
  748. memcpy( &index, pCurStor, sizeof(char));
  749. pCurStor += sizeof(char);
  750. //------------------------------------------
  751. // Uncompress spectrum using 'pDresBook'
  752. //------------------------------------------
  753. pMean = ((float*)((char*)m_pInv + m_pInv->DresBook[k].pData)) + (index * VectDim);
  754. AddSpectralBand( pFFT, pMean, startBin, cNumBins, m_pInv->FFTSize );
  755. startBin += cNumBins;
  756. }
  757. }
  758. //--------------------------------------------------------
  759. // Convert quantized FFT back to time residual
  760. //--------------------------------------------------------
  761. memcpy( pRes, pFFT, m_pInv->FFTSize * sizeof(float) ); // preserve original for delta residual
  762. InverseFFT( pRes, m_pInv->FFTSize, m_pInv->FFTOrder, m_pTrig );
  763. GainDeNormalize( pRes, (long)m_pInv->FFTSize, ((UNALIGNED float*)pSynth->pGain)[i] );
  764. SetEpochLen( pCurRes, frameSize, pRes, m_pInv->FFTSize );
  765. }
  766. else
  767. {
  768. //-----------------------------------------------
  769. // UNVOICED epoch
  770. // NOTE: Assumes 'm_pGauss' is 1 sec
  771. //-----------------------------------------------
  772. Gain = 0.02f * ((UNALIGNED float*)pSynth->pGain)[i];
  773. if( m_GaussID + frameSize >= m_pInv->SampleRate)
  774. {
  775. m_GaussID = 0;
  776. }
  777. //----------------------------------------------------------
  778. // Generate gaussian random noise for unvoiced sounds
  779. //----------------------------------------------------------
  780. for( j = 0; j < frameSize; j++ )
  781. {
  782. pCurRes[j] = Gain * m_pGauss[j + m_GaussID];
  783. }
  784. m_GaussID += frameSize;
  785. }
  786. // restore whisper
  787. /*if( (pSynth->pEpoch[i] > 0) && m_fModifiers & BACKEND_BITFLAG_WHISPER)
  788. {
  789. pSynth->pEpoch[i] = - pSynth->pEpoch[i];
  790. }*/
  791. pCurRes += frameSize;
  792. }
  793. }
  794. if( FAILED(hr) )
  795. {
  796. //----------------------------------
  797. // Cleanup allocated memory
  798. //----------------------------------
  799. if( pSynth->pEpoch )
  800. {
  801. delete pSynth->pEpoch;
  802. pSynth->pEpoch = NULL;
  803. }
  804. if( pSynth->pRes )
  805. {
  806. delete pSynth->pRes;
  807. pSynth->pRes = NULL;
  808. }
  809. if( pSynth->pLPC )
  810. {
  811. delete pSynth->pLPC;
  812. pSynth->pLPC = NULL;
  813. }
  814. }
  815. return hr;
  816. } /* CVoiceData::DecompressUnit */
  817. /*****************************************************************************
  818. * CVoiceData::DecompressUnit *
  819. *-------------------------------*
  820. * Description:
  821. * Decompress acoustic unit. +++
  822. *
  823. * INPUT:
  824. * UnitID - unit number (1 - 3333 typ)
  825. *
  826. * OUTPUT:
  827. * Fills pSynth if success
  828. *
  829. ********************************************************************** MC ***/
  830. HRESULT CVoiceData::GetUnitDur( ULONG UnitID, float* pDur )
  831. {
  832. SPDBG_FUNC( "CVoiceData::GetUnitDur" );
  833. char *pCurStor;
  834. float *pEpoch = NULL;
  835. long cBytes, cNumEpochs, i;
  836. float totalDur;
  837. HRESULT hr = S_OK;
  838. totalDur = 0;
  839. if( UnitID > m_NumOfUnits )
  840. {
  841. //--------------------------
  842. // ID is out of range!
  843. //--------------------------
  844. hr = E_INVALIDARG;
  845. }
  846. if( SUCCEEDED(hr) )
  847. {
  848. //-----------------------------------------
  849. // Pointer to unit data from inventory
  850. //-----------------------------------------
  851. pCurStor = (char*)((char*)m_pInv + m_pUnit[UnitID] ); // Rel to abs
  852. //---------------------------------
  853. // Get epoch count - 'cNumEpochs'
  854. //---------------------------------
  855. cBytes = sizeof(long);
  856. memcpy( &cNumEpochs, pCurStor, cBytes );
  857. pCurStor += cBytes;
  858. //---------------------------------
  859. // Get epoch lengths - 'pEpoch'
  860. //---------------------------------
  861. pEpoch = new float[cNumEpochs];
  862. if( pEpoch == NULL )
  863. {
  864. hr = E_OUTOFMEMORY;
  865. }
  866. if( SUCCEEDED(hr) )
  867. {
  868. cBytes = DecompressEpoch( (signed char *) pCurStor, cNumEpochs, pEpoch );
  869. for( i = 0; i < cNumEpochs; i++)
  870. {
  871. totalDur += ABS(pEpoch[i]);
  872. }
  873. }
  874. }
  875. *pDur = totalDur / 22050;
  876. //----------------------------------
  877. // Cleanup allocated memory
  878. //----------------------------------
  879. if( pEpoch )
  880. {
  881. delete pEpoch;
  882. }
  883. return hr;
  884. } /* CVoiceData::GetUnitDur */
  885. /*****************************************************************************
  886. * CVoiceData::DecompressEpoch *
  887. *--------------------------------*
  888. * Description:
  889. * Decompress epoch len stream from RLE. Fills 'pEpoch' with lengths.
  890. * Returns number of 'rgbyte' src bytes consumed.
  891. *
  892. ********************************************************************** MC ***/
  893. long CVoiceData::DecompressEpoch( signed char *rgbyte, long cNumEpochs, float *pEpoch )
  894. {
  895. SPDBG_FUNC( "CVoiceData::DecompressEpoch" );
  896. long iDest, iSrc;
  897. for( iSrc = 0, iDest = 0; iDest < cNumEpochs; ++iDest, ++iSrc )
  898. {
  899. //--------------------------------------
  900. // Decode RLE for VOICED epochs
  901. //--------------------------------------
  902. if( rgbyte[iSrc] == 127 )
  903. {
  904. pEpoch[iDest] = 127.0f;
  905. while( rgbyte[iSrc] == 127 )
  906. {
  907. pEpoch[iDest] += rgbyte[++iSrc];
  908. }
  909. }
  910. //--------------------------------------
  911. // Decode RLE for UNVOICED epochs
  912. //--------------------------------------
  913. else if( rgbyte[iSrc] == - 128 )
  914. {
  915. pEpoch[iDest] = - 128.0f;
  916. while( rgbyte[iSrc] == - 128 )
  917. pEpoch[iDest] += rgbyte[++iSrc];
  918. }
  919. //--------------------------------------
  920. // No compression here
  921. //--------------------------------------
  922. else
  923. {
  924. pEpoch[iDest] = rgbyte[iSrc];
  925. }
  926. }
  927. return iSrc;
  928. } /* CVoiceData::DecompressEpoch */
  929. /*****************************************************************************
  930. * LSPCompare *
  931. *------------*
  932. * Description:
  933. * QSORT callback
  934. *
  935. ********************************************************************** MC ***/
  936. static int __cdecl LSPCompare( const void *a, const void *b )
  937. {
  938. SPDBG_FUNC( "LSPCompare" );
  939. if( *((PFLOAT) a) > *((PFLOAT) b) )
  940. {
  941. return 1;
  942. }
  943. else if( *((PFLOAT) a) == *((PFLOAT) b) )
  944. {
  945. return 0;
  946. }
  947. else
  948. {
  949. return -1;
  950. }
  951. } /* LSPCompare */
  952. /*****************************************************************************
  953. * CVoiceData::OrderLSP *
  954. *-------------------------*
  955. * Description:
  956. * This routine reorders the LSP frequencies so that they are monotonic
  957. *
  958. ********************************************************************** MC ***/
  959. long CVoiceData::OrderLSP( PFLOAT pLSPFrame, INT cOrder )
  960. {
  961. SPDBG_FUNC( "CVoiceData::OrderLSP" );
  962. long i, retCode = true;
  963. for( i = 1; i < cOrder; i++ )
  964. {
  965. if( pLSPFrame[i - 1] > pLSPFrame[i] )
  966. {
  967. retCode = false;
  968. }
  969. }
  970. qsort( (void *) pLSPFrame, (size_t) cOrder, (size_t) sizeof (float), LSPCompare );
  971. return retCode;
  972. } /* CVoiceData::OrderLSP */
  973. /*****************************************************************************
  974. * CVoiceData::LSPtoPC *
  975. *------------------------*
  976. * Description:
  977. * Converts line spectral frequencies to LPC predictor coefficients.
  978. *
  979. ********************************************************************** MC ***/
  980. void CVoiceData::LSPtoPC( float *pLSP, float *pLPC, long cOrder, long /*frame*/ )
  981. {
  982. SPDBG_FUNC( "CVoiceData::LSPtoPC" );
  983. long i, j, k, noh;
  984. double freq[MAXNO], p[MAXNO / 2], q[MAXNO / 2];
  985. double a[MAXNO / 2 + 1], a1[MAXNO / 2 + 1], a2[MAXNO / 2 + 1];
  986. double b[MAXNO / 2 + 1], b1[MAXNO / 2 + 1], b2[MAXNO / 2 + 1];
  987. double pi, xx, xf;
  988. //----------------------------------
  989. // Check for non-monotonic LSPs
  990. //----------------------------------
  991. for( i = 1; i < cOrder; i++ )
  992. {
  993. if( pLSP[i] <= pLSP[i - 1] )
  994. {
  995. //-----------------------------
  996. // Reorder LSPs
  997. //-----------------------------
  998. OrderLSP( pLSP, cOrder );
  999. break;
  1000. }
  1001. }
  1002. //--------------------------
  1003. // Initialization
  1004. //--------------------------
  1005. pi = KTWOPI;
  1006. noh = cOrder / 2;
  1007. for( j = 0; j < cOrder; j++ )
  1008. {
  1009. freq[j] = pLSP[j];
  1010. }
  1011. for( i = 0; i < noh + 1; i++ )
  1012. {
  1013. a[i] = 0.0f;
  1014. a1[i] = 0.0f;
  1015. a2[i] = 0.0f;
  1016. b[i] = 0.0f;
  1017. b1[i] = 0.0f;
  1018. b2[i] = 0.0f;
  1019. }
  1020. //-------------------------------------
  1021. // LSP filter parameters
  1022. //-------------------------------------
  1023. for( i = 0; i < noh; i++ )
  1024. {
  1025. p[i] = - 2.0 * cos( pi * freq[2 * i] );
  1026. q[i] = - 2.0 * cos( pi * freq[2 * i + 1] );
  1027. }
  1028. //-------------------------------------
  1029. // Impulse response of analysis filter
  1030. //-------------------------------------
  1031. xf = 0.0f;
  1032. for( k = 0; k < cOrder + 1; k++ )
  1033. {
  1034. xx = 0.0f;
  1035. if( k == 0 )
  1036. {
  1037. xx = 1.0f;
  1038. }
  1039. a[0] = xx + xf;
  1040. b[0] = xx - xf;
  1041. xf = xx;
  1042. for( i = 0; i < noh; i++ )
  1043. {
  1044. a[i + 1] = a[i] + p[i] * a1[i] + a2[i];
  1045. b[i + 1] = b[i] + q[i] * b1[i] + b2[i];
  1046. a2[i] = a1[i];
  1047. a1[i] = a[i];
  1048. b2[i] = b1[i];
  1049. b1[i] = b[i];
  1050. }
  1051. if( k != 0)
  1052. {
  1053. pLPC[k - 1] = (float) (- 0.5 * (a[noh] + b[noh]));
  1054. }
  1055. }
  1056. //-------------------------------------------------------
  1057. // Convert to predictor coefficient array configuration
  1058. //-------------------------------------------------------
  1059. for( i = cOrder - 1; i >= 0; i-- )
  1060. {
  1061. pLPC[i + 1] = - pLPC[i];
  1062. }
  1063. pLPC[0] = 1.0f;
  1064. } /* CVoiceData::LSPtoPC */
  1065. /*****************************************************************************
  1066. * CVoiceData::PutSpectralBand *
  1067. *--------------------------------*
  1068. * Description:
  1069. * This routine copies the frequency band specified by StartBin as
  1070. * is initial FFT bin, and containing cNumBins.
  1071. *
  1072. ********************************************************************** MC ***/
  1073. void CVoiceData::PutSpectralBand( float *pFFT, float *pBand, long StartBin,
  1074. long cNumBins, long FFTSize )
  1075. {
  1076. SPDBG_FUNC( "CVoiceData::PutSpectralBand" );
  1077. long j, k, VectDim;
  1078. VectDim = 2 * cNumBins;
  1079. for( j = 0, k = StartBin; j < cNumBins; j++, k++ )
  1080. {
  1081. pFFT[k] = pBand[j];
  1082. }
  1083. k = FFTSize - (StartBin - 1 + cNumBins);
  1084. for( j = cNumBins; j < 2 * cNumBins; j++, k++ )
  1085. {
  1086. pFFT[k] = pBand[j];
  1087. }
  1088. } /* CVoiceData::PutSpectralBand */
  1089. /*****************************************************************************
  1090. * CVoiceData::AddSpectralBand *
  1091. *--------------------------------*
  1092. * Description:
  1093. * This routine adds the frequency band specified by StartBin as
  1094. * is initial FFT bin, and containing cNumBins, to the existing band.
  1095. *
  1096. ********************************************************************** MC ***/
  1097. void CVoiceData::AddSpectralBand( float *pFFT, float *pBand, long StartBin,
  1098. long cNumBins, long FFTSize )
  1099. {
  1100. SPDBG_FUNC( "CVoiceData::AddSpectralBand" );
  1101. long j, k, VectDim;
  1102. VectDim = 2 * cNumBins;
  1103. for( j = 0, k = StartBin; j < cNumBins; j++, k++ )
  1104. {
  1105. pFFT[k] += pBand[j];
  1106. }
  1107. k = FFTSize - (StartBin - 1 + cNumBins);
  1108. for( j = cNumBins; j < 2 * cNumBins; j++, k++ )
  1109. {
  1110. pFFT[k] += pBand[j];
  1111. }
  1112. } /* CVoiceData::AddSpectralBand */
  1113. /*****************************************************************************
  1114. * CVoiceData::InverseFFT *
  1115. *---------------------------*
  1116. * Description:
  1117. * Return TRUE if consoants can be clustered.
  1118. * This subroutine computes a split-radix IFFT for real data
  1119. * It is a C version of the FORTRAN program in "Real-Valued
  1120. * Fast Fourier Transform Algorithms" by H. Sorensen et al.
  1121. * in Trans. on ASSP, June 1987, pp. 849-863. It uses half
  1122. * of the operations than its counterpart for complex data.
  1123. * *
  1124. * Length is n = 2^(fftOrder). Decimation in frequency. Result is
  1125. * in place. It uses table look-up for the trigonometric functions.
  1126. *
  1127. * Input order: *
  1128. * (Re[0], Re[1], ... Re[n/2], Im[n/2 - 1]...Im[1])
  1129. * Output order:
  1130. * (x[0], x[1], ... x[n - 1])
  1131. * The output transform exhibit hermitian symmetry (i.e. real
  1132. * part of transform is even while imaginary part is odd).
  1133. * Hence Im[0] = Im[n/2] = 0; and n memory locations suffice.
  1134. *
  1135. ********************************************************************** MC ***/
  1136. void CVoiceData::InverseFFT( float *pDest, long fftSize, long fftOrder, float *sinePtr )
  1137. {
  1138. SPDBG_FUNC( "CVoiceData::InverseFFT" );
  1139. long n1, n2, n4, n8, i0, i1, i2, i3, i4, i5, i6, i7, i8;
  1140. long is, id, i, j, k, ie, ia, ia3;
  1141. float xt, t1, t2, t3, t4, t5, *cosPtr, r1, cc1, cc3, ss1, ss3;
  1142. cosPtr = sinePtr + (fftSize / 2);
  1143. //---------------------------------
  1144. // L shaped butterflies
  1145. //---------------------------------
  1146. n2 = 2 * fftSize;
  1147. ie = 1;
  1148. for( k = 1; k < fftOrder; k++ )
  1149. {
  1150. is = 0;
  1151. id = n2;
  1152. n2 = n2 / 2;
  1153. n4 = n2 / 4;
  1154. n8 = n4 / 2;
  1155. ie *= 2;
  1156. while( is < fftSize - 1 )
  1157. {
  1158. for( i = is; i < fftSize; i += id )
  1159. {
  1160. i1 = i;
  1161. i2 = i1 + n4;
  1162. i3 = i2 + n4;
  1163. i4 = i3 + n4;
  1164. t1 = pDest[i1] - pDest[i3];
  1165. pDest[i1] = pDest[i1] + pDest[i3];
  1166. pDest[i2] = 2 * pDest[i2];
  1167. pDest[i3] = t1 - 2 * pDest[i4];
  1168. pDest[i4] = t1 + 2 * pDest[i4];
  1169. if( n4 > 1 )
  1170. {
  1171. i1 = i1 + n8;
  1172. i2 = i2 + n8;
  1173. i3 = i3 + n8;
  1174. i4 = i4 + n8;
  1175. t1 = K2 * (pDest[i2] - pDest[i1]);
  1176. t2 = K2 * (pDest[i4] + pDest[i3]);
  1177. pDest[i1] = pDest[i1] + pDest[i2];
  1178. pDest[i2] = pDest[i4] - pDest[i3];
  1179. pDest[i3] = - 2 * (t1 + t2);
  1180. pDest[i4] = 2 * (t1 - t2);
  1181. }
  1182. }
  1183. is = 2 * id - n2;
  1184. id = 4 * id;
  1185. }
  1186. ia = 0;
  1187. for( j = 1; j < n8; j++ )
  1188. {
  1189. ia += ie;
  1190. ia3 = 3 * ia;
  1191. cc1 = cosPtr[ia];
  1192. ss1 = sinePtr[ia];
  1193. cc3 = cosPtr[ia3];
  1194. ss3 = sinePtr[ia3];
  1195. is = 0;
  1196. id = 2 * n2;
  1197. while( is < fftSize - 1 )
  1198. {
  1199. for( i = is; i < fftSize; i += id )
  1200. {
  1201. i1 = i + j;
  1202. i2 = i1 + n4;
  1203. i3 = i2 + n4;
  1204. i4 = i3 + n4;
  1205. i5 = i + n4 - j;
  1206. i6 = i5 + n4;
  1207. i7 = i6 + n4;
  1208. i8 = i7 + n4;
  1209. t1 = pDest[i1] - pDest[i6];
  1210. pDest[i1] = pDest[i1] + pDest[i6];
  1211. t2 = pDest[i5] - pDest[i2];
  1212. pDest[i5] = pDest[i2] + pDest[i5];
  1213. t3 = pDest[i8] + pDest[i3];
  1214. pDest[i6] = pDest[i8] - pDest[i3];
  1215. t4 = pDest[i4] + pDest[i7];
  1216. pDest[i2] = pDest[i4] - pDest[i7];
  1217. t5 = t1 - t4;
  1218. t1 = t1 + t4;
  1219. t4 = t2 - t3;
  1220. t2 = t2 + t3;
  1221. pDest[i3] = t5 * cc1 + t4 * ss1;
  1222. pDest[i7] = - t4 * cc1 + t5 * ss1;
  1223. pDest[i4] = t1 * cc3 - t2 * ss3;
  1224. pDest[i8] = t2 * cc3 + t1 * ss3;
  1225. }
  1226. is = 2 * id - n2;
  1227. id = 4 * id;
  1228. }
  1229. }
  1230. }
  1231. //---------------------------------
  1232. // length two butterflies
  1233. //---------------------------------
  1234. is = 0;
  1235. id = 4;
  1236. while( is < fftSize - 1 )
  1237. {
  1238. for( i0 = is; i0 < fftSize; i0 += id )
  1239. {
  1240. i1 = i0 + 1;
  1241. r1 = pDest[i0];
  1242. pDest[i0] = r1 + pDest[i1];
  1243. pDest[i1] = r1 - pDest[i1];
  1244. }
  1245. is = 2 * (id - 1);
  1246. id = 4 * id;
  1247. }
  1248. //---------------------------------
  1249. // digit reverse counter
  1250. //---------------------------------
  1251. j = 0;
  1252. n1 = fftSize - 1;
  1253. for( i = 0; i < n1; i++ )
  1254. {
  1255. if( i < j )
  1256. {
  1257. xt = pDest[j];
  1258. pDest[j] = pDest[i];
  1259. pDest[i] = xt;
  1260. }
  1261. k = fftSize / 2;
  1262. while( k <= j )
  1263. {
  1264. j -= k;
  1265. k /= 2;
  1266. }
  1267. j += k;
  1268. }
  1269. for( i = 0; i < fftSize; i++ )
  1270. {
  1271. pDest[i] /= fftSize;
  1272. }
  1273. } /* CVoiceData::InverseFFT */
  1274. /*****************************************************************************
  1275. * CVoiceData::SetEpochLen *
  1276. *----------------------*
  1277. * Description:
  1278. * Copy residual epoch to 'OutSize' length from 'pInRes' to 'pOutRes'
  1279. *
  1280. ********************************************************************** MC ***/
  1281. void CVoiceData::SetEpochLen( float *pOutRes, long OutSize, float *pInRes,
  1282. long InSize )
  1283. {
  1284. SPDBG_FUNC( "CVoiceData::AddSpectralBand" );
  1285. long j, curFrame;
  1286. curFrame = MIN(InSize / 2, OutSize);
  1287. //-------------------------------
  1288. // Copy SRC to DEST
  1289. //-------------------------------
  1290. for( j = 0; j < curFrame; j++ )
  1291. pOutRes[j] = pInRes[j];
  1292. //-------------------------------
  1293. // Pad DEST if longer
  1294. //-------------------------------
  1295. for( j = curFrame; j < OutSize; j++ )
  1296. pOutRes[j] = 0.0f;
  1297. //-------------------------------
  1298. // Mix DEST if shorter
  1299. //-------------------------------
  1300. for( j = OutSize - curFrame; j < OutSize; j++ )
  1301. pOutRes[j] += pInRes[InSize - OutSize + j];
  1302. } /* CVoiceData::SetEpochLen */
  1303. /*****************************************************************************
  1304. * CVoiceData::GainDeNormalize *
  1305. *--------------------------------*
  1306. * Description:
  1307. * Scale residual to given gain.
  1308. *
  1309. ********************************************************************** MC ***/
  1310. void CVoiceData::GainDeNormalize( float *pRes, long FFTSize, float Gain )
  1311. {
  1312. SPDBG_FUNC( "CVoiceData::GainDeNormalize" );
  1313. long j;
  1314. for( j = 0; j < FFTSize; j++ )
  1315. {
  1316. pRes[j] *= Gain;
  1317. }
  1318. } /* CVoiceData::GainDeNormalize */
  1319. /*****************************************************************************
  1320. * CVoiceData::PhonHashLookup *
  1321. *-------------------------------*
  1322. * Description:
  1323. * Lookup 'sym' in 'ht' and place its associated value in
  1324. * *val. If sym is not found place its key in *val.
  1325. * RETURN
  1326. * Return 0 indicating we found the 'sym' in the table.
  1327. * Return -1 'sym' is not in ht.
  1328. *
  1329. ********************************************************************** MC ***/
  1330. long CVoiceData::PhonHashLookup(
  1331. PHON_DICT *pPD, // the hash table
  1332. char *sym, // The symbol to look up
  1333. long *val ) // Phon ID
  1334. {
  1335. SPDBG_FUNC( "CVoiceData::PhonHashLookup" );
  1336. char *cp;
  1337. unsigned long key;
  1338. long i;
  1339. HASH_TABLE *ht;
  1340. char *pStr;
  1341. HASH_ENTRY *pHE;
  1342. ht = &pPD->phonHash;
  1343. key = 0;
  1344. i = -1;
  1345. cp = sym;
  1346. pHE = (HASH_ENTRY*)((char*)pPD + ht->entryArrayOffs); // Offset to Abs address
  1347. do
  1348. {
  1349. key += *cp++ << (0xF & i--);
  1350. }
  1351. while( *cp );
  1352. while( true )
  1353. {
  1354. key %= ht->size;
  1355. if( pHE[key].obj == 0 )
  1356. {
  1357. //------------------------------
  1358. // Not in hash table!
  1359. //------------------------------
  1360. *val = (long) key;
  1361. return -1;
  1362. }
  1363. //-------------------------------
  1364. // Offset to Abs address
  1365. //-------------------------------
  1366. pStr = (char*)((char*)pPD + pHE[key].obj);
  1367. if( strcmp(pStr, sym) == 0 )
  1368. {
  1369. *val = pHE[key].val;
  1370. return 0;
  1371. }
  1372. key++;
  1373. }
  1374. } /* CVoiceData::PhonHashLookup */
  1375. /*****************************************************************************
  1376. * CVoiceData::PhonToID *
  1377. *-------------------------*
  1378. * Description:
  1379. * Return ID from phoneme string.
  1380. *
  1381. ********************************************************************** MC ***/
  1382. long CVoiceData::PhonToID( PHON_DICT *pd, char *phone_str )
  1383. {
  1384. SPDBG_FUNC( "CVoiceData::PhonToID" );
  1385. long phon_id;
  1386. if( PhonHashLookup( pd, phone_str, &phon_id ) )
  1387. {
  1388. phon_id = NO_PHON;
  1389. }
  1390. return phon_id;
  1391. } /* CVoiceData::PhonToID */
  1392. /*****************************************************************************
  1393. * CVoiceData::PhonFromID *
  1394. *---------------------------*
  1395. * Description:
  1396. * Return string from phoneme ID
  1397. *
  1398. ********************************************************************** MC ***/
  1399. char *CVoiceData::PhonFromID( PHON_DICT *pd, long phone_id )
  1400. {
  1401. SPDBG_FUNC( "CVoiceData::PhonFromID" );
  1402. char *strPtr;
  1403. long *pOffs;
  1404. pOffs = (long*)((char*)pd + pd->phones_list);
  1405. strPtr = (char*) ((char*)pd + pOffs[phone_id]);
  1406. return strPtr;
  1407. } /* CVoiceData::PhonFromID */
  1408. #define CNODE_ISA_LEAF(n) ((n)->yes < 0)
  1409. #define BADTREE_ERROR (-1)
  1410. #define PARAM_ERROR (-2)
  1411. #define END_OF_PROD 65535
  1412. #define WB_BEGIN 1
  1413. #define WB_END 2
  1414. #define WB_SINGLE 4
  1415. #define WB_WWT 8
  1416. #define POS_TYPE 4
  1417. #define GET_BIT(p,feat,i,b) \
  1418. { \
  1419. (i) = ( (p)+POS_TYPE+(feat)->nstateq ) / 32; \
  1420. (b) = 1 << ( ((p)+POS_TYPE+(feat)->nstateq ) % 32); \
  1421. }
  1422. #define GET_RBIT(p,feat,i,b) \
  1423. { \
  1424. GET_BIT(p,feat,i,b); \
  1425. (i) += (feat)->nint32perq; \
  1426. }
  1427. #define GET_CBIT(p,feat,i,b) \
  1428. { \
  1429. GET_BIT(p,feat,i,b); \
  1430. (i) += 2 * (feat)->nint32perq; \
  1431. }
  1432. /*****************************************************************************
  1433. * AnswerQ *
  1434. *---------*
  1435. * Description:
  1436. * Tree node test.
  1437. *
  1438. ********************************************************************** MC ***/
  1439. static _inline long AnswerQ( unsigned short *prod, long *uniq_prod,
  1440. long li, long bitpos, long ri, long rbitpos,
  1441. long pos, long nint32perProd)
  1442. {
  1443. UNALIGNED long *p;
  1444. for( ; *prod != END_OF_PROD; prod++ )
  1445. {
  1446. p = &uniq_prod[(*prod) * nint32perProd];
  1447. if( ((p[0] & pos) == pos) && (p[li] & bitpos) && (p[ri] & rbitpos) )
  1448. {
  1449. return true;
  1450. }
  1451. }
  1452. return false;
  1453. } /* AnswerQ */
  1454. /*****************************************************************************
  1455. * CVoiceData::GetTriphoneID *
  1456. *------------------------------*
  1457. * Description:
  1458. * Retrieve triphone ID from phoneme context.+++
  1459. * Store result into 'pResult'
  1460. *
  1461. ********************************************************************** MC ***/
  1462. HRESULT CVoiceData::GetTriphoneID( TRIPHONE_TREE *forest,
  1463. long phon, // target phon
  1464. long leftPhon, // left context
  1465. long rightPhon, // right context
  1466. long pos, // word position ("b", "e" or "s"
  1467. PHON_DICT *pd,
  1468. ULONG *pResult)
  1469. {
  1470. SPDBG_FUNC( "CVoiceData::GetTriphoneID" );
  1471. C_NODE *cnode, *croot;
  1472. TREE_ELEM *tree = NULL;
  1473. long *uniq_prod;
  1474. char *ll, *rr;
  1475. long li, bitpos, ri, rbitpos, nint32perProd, c;
  1476. unsigned short *prodspace;
  1477. FEATURE *feat;
  1478. long *pOffs;
  1479. HRESULT hr = S_OK;
  1480. long triphoneID = 0;
  1481. if( (phon < 0) || (phon >= pd->numCiPhones) ||
  1482. (leftPhon < 0) || (leftPhon >= pd->numCiPhones) ||
  1483. (rightPhon < 0) || (rightPhon >= pd->numCiPhones) )
  1484. {
  1485. //--------------------------------
  1486. // Phon out of range!
  1487. //--------------------------------
  1488. hr = E_INVALIDARG;
  1489. }
  1490. if( SUCCEEDED(hr) )
  1491. {
  1492. c = phon;
  1493. tree = &forest->tree[c];
  1494. if( tree->nnodes == 0 )
  1495. {
  1496. //--------------------------------
  1497. // No CD triphones in tree!
  1498. //--------------------------------
  1499. hr = E_INVALIDARG;
  1500. }
  1501. }
  1502. if( SUCCEEDED(hr) )
  1503. {
  1504. if( pos == 'b' || pos == 'B' )
  1505. {
  1506. pos = WB_BEGIN;
  1507. }
  1508. else if( pos == 'e' || pos == 'E' )
  1509. {
  1510. pos = WB_END;
  1511. }
  1512. else if( pos == 's' || pos == 'S' )
  1513. {
  1514. pos = WB_SINGLE;
  1515. }
  1516. else if( pos == '\0' )
  1517. {
  1518. pos = WB_WWT;
  1519. }
  1520. else
  1521. {
  1522. //--------------------------------
  1523. // Unknown word position
  1524. //--------------------------------
  1525. hr = E_INVALIDARG;
  1526. }
  1527. }
  1528. if( SUCCEEDED(hr) )
  1529. {
  1530. pOffs = (long*)((char*)pd + pd->phones_list);
  1531. ll = (char*) ((char*)pd + pOffs[leftPhon]);
  1532. if( ll[0] == '+' || _strnicmp(ll, "SIL", 3) == 0 )
  1533. {
  1534. leftPhon = forest->silPhoneId;
  1535. }
  1536. rr = (char*) ((char*)pd + pOffs[rightPhon]);
  1537. if( rr[0] == '+' || _strnicmp(rr, "SIL", 3) == 0 ) // includes SIL
  1538. {
  1539. rightPhon = forest->silPhoneId;
  1540. }
  1541. else if( forest->nonSilCxt >= 0 && (pos == WB_END || pos == WB_SINGLE) )
  1542. {
  1543. rightPhon = forest->nonSilCxt;
  1544. }
  1545. feat = &forest->feat;
  1546. GET_BIT(leftPhon,feat,li,bitpos);
  1547. GET_RBIT(rightPhon,feat,ri,rbitpos);
  1548. uniq_prod = (long*)(forest->uniq_prod_Offset + (char*)forest); // Offset to ABS
  1549. croot = cnode = (C_NODE*)(tree->nodes + (char*)forest); // Offset to ABS
  1550. nint32perProd = forest->nint32perProd;
  1551. while( ! CNODE_ISA_LEAF(cnode) )
  1552. {
  1553. prodspace = (unsigned short*)((char*)forest + cnode->prod); // Offset to ABS
  1554. if( AnswerQ (prodspace, uniq_prod, li, bitpos, ri, rbitpos, pos, nint32perProd) )
  1555. {
  1556. cnode = &croot[cnode->yes];
  1557. }
  1558. else
  1559. {
  1560. cnode = &croot[cnode->no];
  1561. }
  1562. }
  1563. //-----------------------------
  1564. // Return successful result
  1565. //-----------------------------
  1566. triphoneID = (ULONG) cnode->no;
  1567. }
  1568. *pResult = triphoneID;
  1569. return hr;
  1570. } /* CVoiceData::GetTriphoneID */
  1571. /*****************************************************************************
  1572. * FIR_Filter *
  1573. *------------*
  1574. * Description:
  1575. * FIR filter. For an input x[n] it does an FIR filter with
  1576. * output y[n]. Result is in place. pHistory contains the last
  1577. * cNumTaps values.
  1578. *
  1579. * y[n] = pFilter[0] * x[n] + pFilter[1] * x[n - 1]
  1580. * + ... + pFilter[cNumTaps - 1] * x[n - cNumTaps - 1]
  1581. *
  1582. ********************************************************************** MC ***/
  1583. void CVoiceData::FIR_Filter( float *pVector, long cNumSamples, float *pFilter,
  1584. float *pHistory, long cNumTaps )
  1585. {
  1586. SPDBG_FUNC( "CVoiceData::FIR_Filter" );
  1587. long i, j;
  1588. float sum;
  1589. for( i = 0; i < cNumSamples; i++ )
  1590. {
  1591. pHistory[0] = pVector[i];
  1592. sum = pHistory[0] * pFilter[0];
  1593. for( j = cNumTaps - 1; j > 0; j-- )
  1594. {
  1595. sum += pHistory[j] * pFilter[j];
  1596. pHistory[j] = pHistory[j - 1];
  1597. }
  1598. pVector[i] = sum;
  1599. }
  1600. } /* CVoiceData::FIR_Filter */
  1601. /*****************************************************************************
  1602. * IIR_Filter *
  1603. *------------*
  1604. * Description:
  1605. * IIR filter. For an input x[n] it does an IIR filter with
  1606. * output y[n]. Result is in place. pHistory contains the last
  1607. * cNumTaps values.
  1608. *
  1609. * y[n] = pFilter[0] * x[n] + pFilter[1] * y[n - 1]
  1610. * + ... + pFilter[cNumTaps - 1] * y[n - cNumTaps - 1]
  1611. *
  1612. ********************************************************************** MC ***/
  1613. void CVoiceData::IIR_Filter( float *pVector, long cNumSamples, float *pFilter,
  1614. float *pHistory, long cNumTaps )
  1615. {
  1616. SPDBG_FUNC( "CVoiceData::IIR_Filter" );
  1617. long i, j;
  1618. float sum;
  1619. for( i = 0; i < cNumSamples; i++ )
  1620. {
  1621. sum = pVector[i] * pFilter[0];
  1622. for( j = cNumTaps - 1; j > 0; j-- )
  1623. {
  1624. pHistory[j] = pHistory[j - 1];
  1625. sum += pHistory[j] * pFilter[j];
  1626. }
  1627. pVector[i] = sum;
  1628. pHistory[0] = sum;
  1629. }
  1630. } /* CVoiceData::IIR_Filter */