Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1827 lines
60 KiB

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