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.

1822 lines
58 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. strcpy( &pUnits[i].szUnitName[0], pName );
  442. //-----------------------------
  443. // Get unit stats
  444. //-----------------------------
  445. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  446. pStats = &pStats[senoneID+1];
  447. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  448. pStats = &pStats[senoneID-1];
  449. pStats = (UNALIGNED UNIT_STATS*)(m_SenoneBlock[curID] + (char*)m_SenoneBlock);
  450. pStats = &pStats[senoneID];
  451. pUnits[i].Dur = pStats->dur / 1000.0f; // ms -> sec
  452. pUnits[i].Amp = pStats->amp;
  453. pUnits[i].AmpRatio = (float)sqrt(pStats->ampRatio);
  454. //----------------------------------------------------------
  455. // Looks like the "SENONE" table durations are
  456. // incorrect (not even close!).
  457. // Calc the real duration from inv epochs
  458. // TODO: Make new table in voice data block
  459. //----------------------------------------------------------
  460. //hr = GetUnitDur( pUnits[i].UnitID, &pUnits[i].Dur );
  461. if( FAILED(hr) )
  462. {
  463. break;
  464. }
  465. }
  466. }
  467. }
  468. }
  469. return hr;
  470. } /* CVoiceDataObj::GetUnitIDs */
  471. /*****************************************************************************
  472. * GetDataBlock *
  473. *--------------*
  474. * Description:
  475. * Return ptr and length of specified voice data block. +++
  476. *
  477. ********************************************************************** MC ***/
  478. HRESULT CVoiceDataObj::GetDataBlock( VOICEDATATYPE type, char **ppvOut, ULONG *pdwSize )
  479. {
  480. SPDBG_FUNC( "CVoiceDataObj::GetDataBlock" );
  481. long *offs;
  482. HRESULT hr = S_OK;
  483. long dataType;
  484. if( !m_pVoiceData )
  485. {
  486. hr = E_INVALIDARG;
  487. }
  488. else
  489. {
  490. dataType = (long)type * 2; // x2 since each entry is an offset/length pair
  491. offs = (long*)&m_pVoiceData->PhonOffset; // Table start
  492. *ppvOut = offs[dataType] + ((char*)m_pVoiceData); // Offset -> abs address
  493. *pdwSize = offs[dataType + 1];
  494. }
  495. return hr;
  496. } /* CVoiceDataObj::GetDataBlock */
  497. /*****************************************************************************
  498. * InitVoiceData *
  499. *---------------*
  500. * Description:
  501. * Create pointers to voice data blocks from m_pVoiceData offsets.+++
  502. *
  503. ********************************************************************** MC ***/
  504. HRESULT CVoiceDataObj::InitVoiceData()
  505. {
  506. SPDBG_FUNC( "CVoiceDataObj::InitVoiceData" );
  507. char *pRawData;
  508. ULONG dataSize;
  509. HRESULT hr = S_OK;
  510. //------------------------------------------
  511. // Check data type and version
  512. //------------------------------------------
  513. if( (m_pVoiceData != NULL)
  514. && (m_pVoiceData->Type == MS_DATA_TYPE)
  515. && (m_pVoiceData->Version == HEADER_VERSION) )
  516. {
  517. //-------------------------------
  518. // Get ptr to PHONs
  519. //-------------------------------
  520. hr = GetDataBlock( MSVD_PHONE, &pRawData, &dataSize );
  521. m_pd = (PHON_DICT*)pRawData;
  522. //-------------------------------
  523. // Get ptr to TREE
  524. //-------------------------------
  525. if( SUCCEEDED(hr) )
  526. {
  527. hr = GetDataBlock( MSVD_TREEIMAGE, &pRawData, &dataSize );
  528. m_pForest = (TRIPHONE_TREE*)pRawData;
  529. }
  530. //-------------------------------
  531. // Get ptr to SENONE
  532. //-------------------------------
  533. if( SUCCEEDED(hr) )
  534. {
  535. hr = GetDataBlock( MSVD_SENONE, &pRawData, &dataSize );
  536. m_SenoneBlock = (long*)pRawData;
  537. }
  538. //-------------------------------
  539. // Get ptr to ALLOID
  540. //-------------------------------
  541. if( SUCCEEDED(hr) )
  542. {
  543. hr = GetDataBlock( MSVD_ALLOID, &pRawData, &dataSize );
  544. m_AlloToUnitTbl = (short*)pRawData;
  545. m_NumOfAllos = dataSize / 8;
  546. }
  547. if( SUCCEEDED(hr) )
  548. {
  549. m_First_Context_Phone = m_pd->numCiPhones;
  550. m_Sil_Index = PhonToID( m_pd, "SIL" );
  551. }
  552. //-----------------------------------------------------
  553. // Init voice data INVENTORY parameters
  554. //-----------------------------------------------------
  555. if( SUCCEEDED(hr) )
  556. {
  557. hr = GetDataBlock( MSVD_INVENTORY, &pRawData, &dataSize );
  558. if( SUCCEEDED(hr) )
  559. {
  560. m_pInv = (INVENTORY*)pRawData;
  561. m_CompressionType = m_pVoiceDef->CompressionType;
  562. //---------------------------------------------
  563. // Convert REL to ABS
  564. //---------------------------------------------
  565. m_pUnit = (long*)((char*)m_pInv + m_pInv->UnitsOffset);
  566. m_pTrig = (float*)((char*)m_pInv + m_pInv->TrigOffset);
  567. m_pWindow = (float*)((char*)m_pInv + m_pInv->WindowOffset);
  568. m_pGauss = (float*)((char*)m_pInv + m_pInv->pGaussOffset);
  569. m_SampleRate = (float)m_pInv->SampleRate;
  570. m_FFTSize = m_pInv->FFTSize;
  571. m_cOrder = m_pInv->cOrder;
  572. m_GaussID = 0;
  573. m_NumOfUnits = m_pInv->cNumUnits;
  574. }
  575. }
  576. }
  577. else
  578. {
  579. //-------------------------
  580. // Not a voice file!
  581. //-------------------------
  582. hr = E_FAIL;
  583. }
  584. return hr;
  585. } /* CVoiceDataObj::InitVoiceData */
  586. /*****************************************************************************
  587. * CVoiceDataObj::DecompressUnit *
  588. *-------------------------------*
  589. * Description:
  590. * Decompress acoustic unit.+++
  591. *
  592. * INPUT:
  593. * UnitID - unit number (1 - 3333 typ)
  594. *
  595. * OUTPUT:
  596. * Fills pSynth if success
  597. *
  598. ********************************************************************** MC ***/
  599. HRESULT CVoiceDataObj::DecompressUnit( ULONG UnitID, MSUNITDATA* pSynth )
  600. {
  601. SPDBG_FUNC( "CVoiceDataObj::DecompressUnit" );
  602. long i, j, k, cNumEpochs, cBytes, cOrder = 0, VectDim;
  603. long frameSize, cNumBins, startBin;
  604. char *pCurStor;
  605. unsigned char index;
  606. float pLSP[MAX_LPCORDER], pFFT[MAX_FFTSIZE], pRes[MAX_FFTSIZE], Gain;
  607. float *pCurLSP, *pCurLPC, *pMean, *pCurRes;
  608. HRESULT hr = S_OK;
  609. memset( pSynth, 0, sizeof(MSUNITDATA) );
  610. //-----------------------------------------
  611. // Pointer to unit data from inventory
  612. //-----------------------------------------
  613. pCurStor = (char*)((char*)m_pInv + m_pUnit[UnitID] ); // Rel to abs
  614. //---------------------------------
  615. // Get epoch count - 'cNumEpochs'
  616. //---------------------------------
  617. cBytes = sizeof(long);
  618. memcpy( &cNumEpochs, pCurStor, cBytes );
  619. pSynth->cNumEpochs = cNumEpochs;
  620. pCurStor += cBytes;
  621. //---------------------------------
  622. // Get epoch lengths - 'pEpoch'
  623. //---------------------------------
  624. pSynth->pEpoch = new float[cNumEpochs];
  625. if( pSynth->pEpoch == NULL )
  626. {
  627. hr = E_OUTOFMEMORY;
  628. }
  629. if( SUCCEEDED(hr) )
  630. {
  631. cBytes = DecompressEpoch( (signed char *) pCurStor, cNumEpochs, pSynth->pEpoch );
  632. pCurStor += cBytes;
  633. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  634. //
  635. // Uncompress LPC coefficients...
  636. //
  637. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  638. cOrder = m_pInv->cOrder;
  639. pSynth->cOrder = cOrder;
  640. pSynth->pLPC = new float[cNumEpochs * (1 + cOrder)];
  641. if( pSynth->pLPC == NULL )
  642. {
  643. hr = E_OUTOFMEMORY;
  644. }
  645. }
  646. if( SUCCEEDED(hr) )
  647. {
  648. pCurLPC = pSynth->pLPC;
  649. //---------------------------------
  650. // ... for each epoch
  651. //---------------------------------
  652. for( i = 0; i < cNumEpochs; i++, pCurLPC += (1 + cOrder) )
  653. {
  654. //-------------------------------------
  655. // Decode quantized LSP's...
  656. //-------------------------------------
  657. pCurLSP = pLSP;
  658. for( k = 0; k < m_pInv->cNumLPCBooks; k++ )
  659. {
  660. VectDim = m_pInv->LPCBook[k].cCodeDim;
  661. memcpy( &index, pCurStor, sizeof(char));
  662. pCurStor += sizeof(char);
  663. pMean = ((float*)((char*)m_pInv + m_pInv->LPCBook[k].pData)) + (index * VectDim);
  664. for( j = 0; j < VectDim; j++ )
  665. pCurLSP[j] = pMean[j];
  666. pCurLSP += VectDim;
  667. }
  668. //--------------------------------------------------
  669. // ...then convert to predictor coefficients
  670. // (LSP's quantize better than PC's)
  671. //--------------------------------------------------
  672. LSPtoPC( pLSP, pCurLPC, cOrder, i );
  673. }
  674. //---------------------------------------
  675. // Get pointer to residual gains
  676. //---------------------------------------
  677. cBytes = cNumEpochs * sizeof(float);
  678. pSynth->pGain = (float*) pCurStor;
  679. pCurStor += cBytes;
  680. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  681. //
  682. // Uncompress residual waveform
  683. //
  684. //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  685. //--------------------------------------------
  686. // First, figure out the buffer length...
  687. //--------------------------------------------
  688. pSynth->cNumSamples = 0;
  689. for( j = 0; j < cNumEpochs; j++ )
  690. {
  691. pSynth->cNumSamples += (long) ABS(pSynth->pEpoch[j]);
  692. }
  693. //--------------------------------------------
  694. // ...get buffer memory...
  695. //--------------------------------------------
  696. pSynth->pRes = new float[pSynth->cNumSamples];
  697. if( pSynth->pRes == NULL )
  698. {
  699. hr = E_OUTOFMEMORY;
  700. }
  701. }
  702. if( SUCCEEDED(hr) )
  703. {
  704. //--------------------------------------------
  705. // ...and fill with uncompressed residual
  706. //--------------------------------------------
  707. pCurRes = pSynth->pRes;
  708. for( i = 0; i < (long)pSynth->cNumEpochs; i++ )
  709. {
  710. //-------------------------------------
  711. // Get epoch length
  712. //-------------------------------------
  713. frameSize = (long)(ABS(pSynth->pEpoch[i]));
  714. // restore whisper
  715. //if( (pSynth->pEpoch[i] > 0) && !(m_fModifiers & BACKEND_BITFLAG_WHISPER) )
  716. if( pSynth->pEpoch[i] > 0 )
  717. {
  718. //-----------------------------------------------
  719. // VOICED epoch
  720. //-----------------------------------------------
  721. if( (m_pInv->cNumDresBooks == 0) || (i == 0) || (pSynth->pEpoch[i - 1] < 0) )
  722. {
  723. //--------------------------------------
  724. // Do static quantization
  725. //--------------------------------------
  726. for( j = 0; j < m_pInv->FFTSize; j++ )
  727. {
  728. pFFT[j] = 0.0f;
  729. }
  730. startBin = 1;
  731. for( k = 0; k < m_pInv->cNumResBooks; k++ )
  732. {
  733. VectDim = m_pInv->ResBook[k].cCodeDim;
  734. cNumBins = VectDim / 2;
  735. memcpy( &index, pCurStor, sizeof(char) );
  736. pCurStor += sizeof(char);
  737. //------------------------------------------
  738. // Uncompress spectrum using 'pResBook'
  739. //------------------------------------------
  740. pMean = ((float*)((char*)m_pInv + m_pInv->ResBook[k].pData)) + (index * VectDim);
  741. PutSpectralBand( pFFT, pMean, startBin, cNumBins, m_pInv->FFTSize );
  742. startBin += cNumBins;
  743. }
  744. }
  745. else
  746. {
  747. //--------------------------------------
  748. // Do delta quantization
  749. //--------------------------------------
  750. startBin = 1;
  751. for( k = 0; k < m_pInv->cNumDresBooks; k++ )
  752. {
  753. VectDim = m_pInv->DresBook[k].cCodeDim;
  754. cNumBins = VectDim / 2;
  755. memcpy( &index, pCurStor, sizeof(char));
  756. pCurStor += sizeof(char);
  757. //------------------------------------------
  758. // Uncompress spectrum using 'pDresBook'
  759. //------------------------------------------
  760. pMean = ((float*)((char*)m_pInv + m_pInv->DresBook[k].pData)) + (index * VectDim);
  761. AddSpectralBand( pFFT, pMean, startBin, cNumBins, m_pInv->FFTSize );
  762. startBin += cNumBins;
  763. }
  764. }
  765. //--------------------------------------------------------
  766. // Convert quantized FFT back to time residual
  767. //--------------------------------------------------------
  768. memcpy( pRes, pFFT, m_pInv->FFTSize * sizeof(float) ); // preserve original for delta residual
  769. InverseFFT( pRes, m_pInv->FFTSize, m_pInv->FFTOrder, m_pTrig );
  770. GainDeNormalize( pRes, (long)m_pInv->FFTSize, ((UNALIGNED float*)pSynth->pGain)[i] );
  771. SetEpochLen( pCurRes, frameSize, pRes, m_pInv->FFTSize );
  772. }
  773. else
  774. {
  775. //-----------------------------------------------
  776. // UNVOICED epoch
  777. // NOTE: Assumes 'm_pGauss' is 1 sec
  778. //-----------------------------------------------
  779. Gain = 0.02f * ((UNALIGNED float*)pSynth->pGain)[i];
  780. if( m_GaussID + frameSize >= m_pInv->SampleRate)
  781. {
  782. m_GaussID = 0;
  783. }
  784. //----------------------------------------------------------
  785. // Generate gaussian random noise for unvoiced sounds
  786. //----------------------------------------------------------
  787. for( j = 0; j < frameSize; j++ )
  788. {
  789. pCurRes[j] = Gain * m_pGauss[j + m_GaussID];
  790. }
  791. m_GaussID += frameSize;
  792. }
  793. // restore whisper
  794. /*if( (pSynth->pEpoch[i] > 0) && m_fModifiers & BACKEND_BITFLAG_WHISPER)
  795. {
  796. pSynth->pEpoch[i] = - pSynth->pEpoch[i];
  797. }*/
  798. pCurRes += frameSize;
  799. }
  800. }
  801. if( FAILED(hr) )
  802. {
  803. //----------------------------------
  804. // Cleanup allocated memory
  805. //----------------------------------
  806. if( pSynth->pEpoch )
  807. {
  808. delete pSynth->pEpoch;
  809. pSynth->pEpoch = NULL;
  810. }
  811. if( pSynth->pRes )
  812. {
  813. delete pSynth->pRes;
  814. pSynth->pRes = NULL;
  815. }
  816. if( pSynth->pLPC )
  817. {
  818. delete pSynth->pLPC;
  819. pSynth->pLPC = NULL;
  820. }
  821. }
  822. return hr;
  823. } /* CVoiceDataObj::DecompressUnit */
  824. /*****************************************************************************
  825. * CVoiceDataObj::DecompressUnit *
  826. *-------------------------------*
  827. * Description:
  828. * Decompress acoustic unit. +++
  829. *
  830. * INPUT:
  831. * UnitID - unit number (1 - 3333 typ)
  832. *
  833. * OUTPUT:
  834. * Fills pSynth if success
  835. *
  836. ********************************************************************** MC ***/
  837. HRESULT CVoiceDataObj::GetUnitDur( ULONG UnitID, float* pDur )
  838. {
  839. SPDBG_FUNC( "CVoiceDataObj::GetUnitDur" );
  840. char *pCurStor;
  841. float *pEpoch = NULL;
  842. long cBytes, cNumEpochs, i;
  843. float totalDur;
  844. HRESULT hr = S_OK;
  845. totalDur = 0;
  846. if( UnitID > m_NumOfUnits )
  847. {
  848. //--------------------------
  849. // ID is out of range!
  850. //--------------------------
  851. hr = E_INVALIDARG;
  852. }
  853. if( SUCCEEDED(hr) )
  854. {
  855. //-----------------------------------------
  856. // Pointer to unit data from inventory
  857. //-----------------------------------------
  858. pCurStor = (char*)((char*)m_pInv + m_pUnit[UnitID] ); // Rel to abs
  859. //---------------------------------
  860. // Get epoch count - 'cNumEpochs'
  861. //---------------------------------
  862. cBytes = sizeof(long);
  863. memcpy( &cNumEpochs, pCurStor, cBytes );
  864. pCurStor += cBytes;
  865. //---------------------------------
  866. // Get epoch lengths - 'pEpoch'
  867. //---------------------------------
  868. pEpoch = new float[cNumEpochs];
  869. if( pEpoch == NULL )
  870. {
  871. hr = E_OUTOFMEMORY;
  872. }
  873. if( SUCCEEDED(hr) )
  874. {
  875. cBytes = DecompressEpoch( (signed char *) pCurStor, cNumEpochs, pEpoch );
  876. for( i = 0; i < cNumEpochs; i++)
  877. {
  878. totalDur += ABS(pEpoch[i]);
  879. }
  880. }
  881. }
  882. *pDur = totalDur / 22050;
  883. //----------------------------------
  884. // Cleanup allocated memory
  885. //----------------------------------
  886. if( pEpoch )
  887. {
  888. delete pEpoch;
  889. }
  890. return hr;
  891. } /* CVoiceDataObj::GetUnitDur */
  892. /*****************************************************************************
  893. * CVoiceDataObj::DecompressEpoch *
  894. *--------------------------------*
  895. * Description:
  896. * Decompress epoch len stream from RLE. Fills 'pEpoch' with lengths.
  897. * Returns number of 'rgbyte' src bytes consumed.
  898. *
  899. ********************************************************************** MC ***/
  900. long CVoiceDataObj::DecompressEpoch( signed char *rgbyte, long cNumEpochs, float *pEpoch )
  901. {
  902. SPDBG_FUNC( "CVoiceDataObj::DecompressEpoch" );
  903. long iDest, iSrc;
  904. for( iSrc = 0, iDest = 0; iDest < cNumEpochs; ++iDest, ++iSrc )
  905. {
  906. //--------------------------------------
  907. // Decode RLE for VOICED epochs
  908. //--------------------------------------
  909. if( rgbyte[iSrc] == 127 )
  910. {
  911. pEpoch[iDest] = 127.0f;
  912. while( rgbyte[iSrc] == 127 )
  913. {
  914. pEpoch[iDest] += rgbyte[++iSrc];
  915. }
  916. }
  917. //--------------------------------------
  918. // Decode RLE for UNVOICED epochs
  919. //--------------------------------------
  920. else if( rgbyte[iSrc] == - 128 )
  921. {
  922. pEpoch[iDest] = - 128.0f;
  923. while( rgbyte[iSrc] == - 128 )
  924. pEpoch[iDest] += rgbyte[++iSrc];
  925. }
  926. //--------------------------------------
  927. // No compression here
  928. //--------------------------------------
  929. else
  930. {
  931. pEpoch[iDest] = rgbyte[iSrc];
  932. }
  933. }
  934. return iSrc;
  935. } /* CVoiceDataObj::DecompressEpoch */
  936. /*****************************************************************************
  937. * LSPCompare *
  938. *------------*
  939. * Description:
  940. * QSORT callback
  941. *
  942. ********************************************************************** MC ***/
  943. static int __cdecl LSPCompare( const void *a, const void *b )
  944. {
  945. SPDBG_FUNC( "LSPCompare" );
  946. if( *((PFLOAT) a) > *((PFLOAT) b) )
  947. {
  948. return 1;
  949. }
  950. else if( *((PFLOAT) a) == *((PFLOAT) b) )
  951. {
  952. return 0;
  953. }
  954. else
  955. {
  956. return -1;
  957. }
  958. } /* LSPCompare */
  959. /*****************************************************************************
  960. * CVoiceDataObj::OrderLSP *
  961. *-------------------------*
  962. * Description:
  963. * This routine reorders the LSP frequencies so that they are monotonic
  964. *
  965. ********************************************************************** MC ***/
  966. long CVoiceDataObj::OrderLSP( PFLOAT pLSPFrame, INT cOrder )
  967. {
  968. SPDBG_FUNC( "CVoiceDataObj::OrderLSP" );
  969. long i, retCode = true;
  970. for( i = 1; i < cOrder; i++ )
  971. {
  972. if( pLSPFrame[i - 1] > pLSPFrame[i] )
  973. {
  974. retCode = false;
  975. }
  976. }
  977. qsort( (void *) pLSPFrame, (size_t) cOrder, (size_t) sizeof (float), LSPCompare );
  978. return retCode;
  979. } /* CVoiceDataObj::OrderLSP */
  980. /*****************************************************************************
  981. * CVoiceDataObj::LSPtoPC *
  982. *------------------------*
  983. * Description:
  984. * Converts line spectral frequencies to LPC predictor coefficients.
  985. *
  986. ********************************************************************** MC ***/
  987. void CVoiceDataObj::LSPtoPC( float *pLSP, float *pLPC, long cOrder, long /*frame*/ )
  988. {
  989. SPDBG_FUNC( "CVoiceDataObj::LSPtoPC" );
  990. long i, j, k, noh;
  991. double freq[MAXNO], p[MAXNO / 2], q[MAXNO / 2];
  992. double a[MAXNO / 2 + 1], a1[MAXNO / 2 + 1], a2[MAXNO / 2 + 1];
  993. double b[MAXNO / 2 + 1], b1[MAXNO / 2 + 1], b2[MAXNO / 2 + 1];
  994. double pi, xx, xf;
  995. //----------------------------------
  996. // Check for non-monotonic LSPs
  997. //----------------------------------
  998. for( i = 1; i < cOrder; i++ )
  999. {
  1000. if( pLSP[i] <= pLSP[i - 1] )
  1001. {
  1002. //-----------------------------
  1003. // Reorder LSPs
  1004. //-----------------------------
  1005. OrderLSP( pLSP, cOrder );
  1006. break;
  1007. }
  1008. }
  1009. //--------------------------
  1010. // Initialization
  1011. //--------------------------
  1012. pi = KTWOPI;
  1013. noh = cOrder / 2;
  1014. for( j = 0; j < cOrder; j++ )
  1015. {
  1016. freq[j] = pLSP[j];
  1017. }
  1018. for( i = 0; i < noh + 1; i++ )
  1019. {
  1020. a[i] = 0.0f;
  1021. a1[i] = 0.0f;
  1022. a2[i] = 0.0f;
  1023. b[i] = 0.0f;
  1024. b1[i] = 0.0f;
  1025. b2[i] = 0.0f;
  1026. }
  1027. //-------------------------------------
  1028. // LSP filter parameters
  1029. //-------------------------------------
  1030. for( i = 0; i < noh; i++ )
  1031. {
  1032. p[i] = - 2.0 * cos( pi * freq[2 * i] );
  1033. q[i] = - 2.0 * cos( pi * freq[2 * i + 1] );
  1034. }
  1035. //-------------------------------------
  1036. // Impulse response of analysis filter
  1037. //-------------------------------------
  1038. xf = 0.0f;
  1039. for( k = 0; k < cOrder + 1; k++ )
  1040. {
  1041. xx = 0.0f;
  1042. if( k == 0 )
  1043. {
  1044. xx = 1.0f;
  1045. }
  1046. a[0] = xx + xf;
  1047. b[0] = xx - xf;
  1048. xf = xx;
  1049. for( i = 0; i < noh; i++ )
  1050. {
  1051. a[i + 1] = a[i] + p[i] * a1[i] + a2[i];
  1052. b[i + 1] = b[i] + q[i] * b1[i] + b2[i];
  1053. a2[i] = a1[i];
  1054. a1[i] = a[i];
  1055. b2[i] = b1[i];
  1056. b1[i] = b[i];
  1057. }
  1058. if( k != 0)
  1059. {
  1060. pLPC[k - 1] = (float) (- 0.5 * (a[noh] + b[noh]));
  1061. }
  1062. }
  1063. //-------------------------------------------------------
  1064. // Convert to predictor coefficient array configuration
  1065. //-------------------------------------------------------
  1066. for( i = cOrder - 1; i >= 0; i-- )
  1067. {
  1068. pLPC[i + 1] = - pLPC[i];
  1069. }
  1070. pLPC[0] = 1.0f;
  1071. } /* CVoiceDataObj::LSPtoPC */
  1072. /*****************************************************************************
  1073. * CVoiceDataObj::PutSpectralBand *
  1074. *--------------------------------*
  1075. * Description:
  1076. * This routine copies the frequency band specified by StartBin as
  1077. * is initial FFT bin, and containing cNumBins.
  1078. *
  1079. ********************************************************************** MC ***/
  1080. void CVoiceDataObj::PutSpectralBand( float *pFFT, float *pBand, long StartBin,
  1081. long cNumBins, long FFTSize )
  1082. {
  1083. SPDBG_FUNC( "CVoiceDataObj::PutSpectralBand" );
  1084. long j, k, VectDim;
  1085. VectDim = 2 * cNumBins;
  1086. for( j = 0, k = StartBin; j < cNumBins; j++, k++ )
  1087. {
  1088. pFFT[k] = pBand[j];
  1089. }
  1090. k = FFTSize - (StartBin - 1 + cNumBins);
  1091. for( j = cNumBins; j < 2 * cNumBins; j++, k++ )
  1092. {
  1093. pFFT[k] = pBand[j];
  1094. }
  1095. } /* CVoiceDataObj::PutSpectralBand */
  1096. /*****************************************************************************
  1097. * CVoiceDataObj::AddSpectralBand *
  1098. *--------------------------------*
  1099. * Description:
  1100. * This routine adds the frequency band specified by StartBin as
  1101. * is initial FFT bin, and containing cNumBins, to the existing band.
  1102. *
  1103. ********************************************************************** MC ***/
  1104. void CVoiceDataObj::AddSpectralBand( float *pFFT, float *pBand, long StartBin,
  1105. long cNumBins, long FFTSize )
  1106. {
  1107. SPDBG_FUNC( "CVoiceDataObj::AddSpectralBand" );
  1108. long j, k, VectDim;
  1109. VectDim = 2 * cNumBins;
  1110. for( j = 0, k = StartBin; j < cNumBins; j++, k++ )
  1111. {
  1112. pFFT[k] += pBand[j];
  1113. }
  1114. k = FFTSize - (StartBin - 1 + cNumBins);
  1115. for( j = cNumBins; j < 2 * cNumBins; j++, k++ )
  1116. {
  1117. pFFT[k] += pBand[j];
  1118. }
  1119. } /* CVoiceDataObj::AddSpectralBand */
  1120. /*****************************************************************************
  1121. * CVoiceDataObj::InverseFFT *
  1122. *---------------------------*
  1123. * Description:
  1124. * Return TRUE if consoants can be clustered.
  1125. * This subroutine computes a split-radix IFFT for real data
  1126. * It is a C version of the FORTRAN program in "Real-Valued
  1127. * Fast Fourier Transform Algorithms" by H. Sorensen et al.
  1128. * in Trans. on ASSP, June 1987, pp. 849-863. It uses half
  1129. * of the operations than its counterpart for complex data.
  1130. * *
  1131. * Length is n = 2^(fftOrder). Decimation in frequency. Result is
  1132. * in place. It uses table look-up for the trigonometric functions.
  1133. *
  1134. * Input order: *
  1135. * (Re[0], Re[1], ... Re[n/2], Im[n/2 - 1]...Im[1])
  1136. * Output order:
  1137. * (x[0], x[1], ... x[n - 1])
  1138. * The output transform exhibit hermitian symmetry (i.e. real
  1139. * part of transform is even while imaginary part is odd).
  1140. * Hence Im[0] = Im[n/2] = 0; and n memory locations suffice.
  1141. *
  1142. ********************************************************************** MC ***/
  1143. void CVoiceDataObj::InverseFFT( float *pDest, long fftSize, long fftOrder, float *sinePtr )
  1144. {
  1145. SPDBG_FUNC( "CVoiceDataObj::InverseFFT" );
  1146. long n1, n2, n4, n8, i0, i1, i2, i3, i4, i5, i6, i7, i8;
  1147. long is, id, i, j, k, ie, ia, ia3;
  1148. float xt, t1, t2, t3, t4, t5, *cosPtr, r1, cc1, cc3, ss1, ss3;
  1149. cosPtr = sinePtr + (fftSize / 2);
  1150. //---------------------------------
  1151. // L shaped butterflies
  1152. //---------------------------------
  1153. n2 = 2 * fftSize;
  1154. ie = 1;
  1155. for( k = 1; k < fftOrder; k++ )
  1156. {
  1157. is = 0;
  1158. id = n2;
  1159. n2 = n2 / 2;
  1160. n4 = n2 / 4;
  1161. n8 = n4 / 2;
  1162. ie *= 2;
  1163. while( is < fftSize - 1 )
  1164. {
  1165. for( i = is; i < fftSize; i += id )
  1166. {
  1167. i1 = i;
  1168. i2 = i1 + n4;
  1169. i3 = i2 + n4;
  1170. i4 = i3 + n4;
  1171. t1 = pDest[i1] - pDest[i3];
  1172. pDest[i1] = pDest[i1] + pDest[i3];
  1173. pDest[i2] = 2 * pDest[i2];
  1174. pDest[i3] = t1 - 2 * pDest[i4];
  1175. pDest[i4] = t1 + 2 * pDest[i4];
  1176. if( n4 > 1 )
  1177. {
  1178. i1 = i1 + n8;
  1179. i2 = i2 + n8;
  1180. i3 = i3 + n8;
  1181. i4 = i4 + n8;
  1182. t1 = K2 * (pDest[i2] - pDest[i1]);
  1183. t2 = K2 * (pDest[i4] + pDest[i3]);
  1184. pDest[i1] = pDest[i1] + pDest[i2];
  1185. pDest[i2] = pDest[i4] - pDest[i3];
  1186. pDest[i3] = - 2 * (t1 + t2);
  1187. pDest[i4] = 2 * (t1 - t2);
  1188. }
  1189. }
  1190. is = 2 * id - n2;
  1191. id = 4 * id;
  1192. }
  1193. ia = 0;
  1194. for( j = 1; j < n8; j++ )
  1195. {
  1196. ia += ie;
  1197. ia3 = 3 * ia;
  1198. cc1 = cosPtr[ia];
  1199. ss1 = sinePtr[ia];
  1200. cc3 = cosPtr[ia3];
  1201. ss3 = sinePtr[ia3];
  1202. is = 0;
  1203. id = 2 * n2;
  1204. while( is < fftSize - 1 )
  1205. {
  1206. for( i = is; i < fftSize; i += id )
  1207. {
  1208. i1 = i + j;
  1209. i2 = i1 + n4;
  1210. i3 = i2 + n4;
  1211. i4 = i3 + n4;
  1212. i5 = i + n4 - j;
  1213. i6 = i5 + n4;
  1214. i7 = i6 + n4;
  1215. i8 = i7 + n4;
  1216. t1 = pDest[i1] - pDest[i6];
  1217. pDest[i1] = pDest[i1] + pDest[i6];
  1218. t2 = pDest[i5] - pDest[i2];
  1219. pDest[i5] = pDest[i2] + pDest[i5];
  1220. t3 = pDest[i8] + pDest[i3];
  1221. pDest[i6] = pDest[i8] - pDest[i3];
  1222. t4 = pDest[i4] + pDest[i7];
  1223. pDest[i2] = pDest[i4] - pDest[i7];
  1224. t5 = t1 - t4;
  1225. t1 = t1 + t4;
  1226. t4 = t2 - t3;
  1227. t2 = t2 + t3;
  1228. pDest[i3] = t5 * cc1 + t4 * ss1;
  1229. pDest[i7] = - t4 * cc1 + t5 * ss1;
  1230. pDest[i4] = t1 * cc3 - t2 * ss3;
  1231. pDest[i8] = t2 * cc3 + t1 * ss3;
  1232. }
  1233. is = 2 * id - n2;
  1234. id = 4 * id;
  1235. }
  1236. }
  1237. }
  1238. //---------------------------------
  1239. // length two butterflies
  1240. //---------------------------------
  1241. is = 0;
  1242. id = 4;
  1243. while( is < fftSize - 1 )
  1244. {
  1245. for( i0 = is; i0 < fftSize; i0 += id )
  1246. {
  1247. i1 = i0 + 1;
  1248. r1 = pDest[i0];
  1249. pDest[i0] = r1 + pDest[i1];
  1250. pDest[i1] = r1 - pDest[i1];
  1251. }
  1252. is = 2 * (id - 1);
  1253. id = 4 * id;
  1254. }
  1255. //---------------------------------
  1256. // digit reverse counter
  1257. //---------------------------------
  1258. j = 0;
  1259. n1 = fftSize - 1;
  1260. for( i = 0; i < n1; i++ )
  1261. {
  1262. if( i < j )
  1263. {
  1264. xt = pDest[j];
  1265. pDest[j] = pDest[i];
  1266. pDest[i] = xt;
  1267. }
  1268. k = fftSize / 2;
  1269. while( k <= j )
  1270. {
  1271. j -= k;
  1272. k /= 2;
  1273. }
  1274. j += k;
  1275. }
  1276. for( i = 0; i < fftSize; i++ )
  1277. {
  1278. pDest[i] /= fftSize;
  1279. }
  1280. } /* CVoiceDataObj::InverseFFT */
  1281. /*****************************************************************************
  1282. * CVoiceDataObj::SetEpochLen *
  1283. *----------------------*
  1284. * Description:
  1285. * Copy residual epoch to 'OutSize' length from 'pInRes' to 'pOutRes'
  1286. *
  1287. ********************************************************************** MC ***/
  1288. void CVoiceDataObj::SetEpochLen( float *pOutRes, long OutSize, float *pInRes,
  1289. long InSize )
  1290. {
  1291. SPDBG_FUNC( "CVoiceDataObj::AddSpectralBand" );
  1292. long j, curFrame;
  1293. curFrame = MIN(InSize / 2, OutSize);
  1294. //-------------------------------
  1295. // Copy SRC to DEST
  1296. //-------------------------------
  1297. for( j = 0; j < curFrame; j++ )
  1298. pOutRes[j] = pInRes[j];
  1299. //-------------------------------
  1300. // Pad DEST if longer
  1301. //-------------------------------
  1302. for( j = curFrame; j < OutSize; j++ )
  1303. pOutRes[j] = 0.0f;
  1304. //-------------------------------
  1305. // Mix DEST if shorter
  1306. //-------------------------------
  1307. for( j = OutSize - curFrame; j < OutSize; j++ )
  1308. pOutRes[j] += pInRes[InSize - OutSize + j];
  1309. } /* CVoiceDataObj::SetEpochLen */
  1310. /*****************************************************************************
  1311. * CVoiceDataObj::GainDeNormalize *
  1312. *--------------------------------*
  1313. * Description:
  1314. * Scale residual to given gain.
  1315. *
  1316. ********************************************************************** MC ***/
  1317. void CVoiceDataObj::GainDeNormalize( float *pRes, long FFTSize, float Gain )
  1318. {
  1319. SPDBG_FUNC( "CVoiceDataObj::GainDeNormalize" );
  1320. long j;
  1321. for( j = 0; j < FFTSize; j++ )
  1322. {
  1323. pRes[j] *= Gain;
  1324. }
  1325. } /* CVoiceDataObj::GainDeNormalize */
  1326. /*****************************************************************************
  1327. * CVoiceDataObj::PhonHashLookup *
  1328. *-------------------------------*
  1329. * Description:
  1330. * Lookup 'sym' in 'ht' and place its associated value in
  1331. * *val. If sym is not found place its key in *val.
  1332. * RETURN
  1333. * Return 0 indicating we found the 'sym' in the table.
  1334. * Return -1 'sym' is not in ht.
  1335. *
  1336. ********************************************************************** MC ***/
  1337. long CVoiceDataObj::PhonHashLookup(
  1338. PHON_DICT *pPD, // the hash table
  1339. char *sym, // The symbol to look up
  1340. long *val ) // Phon ID
  1341. {
  1342. SPDBG_FUNC( "CVoiceDataObj::PhonHashLookup" );
  1343. char *cp;
  1344. unsigned long key;
  1345. long i;
  1346. HASH_TABLE *ht;
  1347. char *pStr;
  1348. HASH_ENTRY *pHE;
  1349. ht = &pPD->phonHash;
  1350. key = 0;
  1351. i = -1;
  1352. cp = sym;
  1353. pHE = (HASH_ENTRY*)((char*)pPD + ht->entryArrayOffs); // Offset to Abs address
  1354. do
  1355. {
  1356. key += *cp++ << (0xF & i--);
  1357. }
  1358. while( *cp );
  1359. while( true )
  1360. {
  1361. key %= ht->size;
  1362. if( pHE[key].obj == 0 )
  1363. {
  1364. //------------------------------
  1365. // Not in hash table!
  1366. //------------------------------
  1367. *val = (long) key;
  1368. return -1;
  1369. }
  1370. //-------------------------------
  1371. // Offset to Abs address
  1372. //-------------------------------
  1373. pStr = (char*)((char*)pPD + pHE[key].obj);
  1374. if( strcmp(pStr, sym) == 0 )
  1375. {
  1376. *val = pHE[key].val;
  1377. return 0;
  1378. }
  1379. key++;
  1380. }
  1381. } /* CVoiceDataObj::PhonHashLookup */
  1382. /*****************************************************************************
  1383. * CVoiceDataObj::PhonToID *
  1384. *-------------------------*
  1385. * Description:
  1386. * Return ID from phoneme string.
  1387. *
  1388. ********************************************************************** MC ***/
  1389. long CVoiceDataObj::PhonToID( PHON_DICT *pd, char *phone_str )
  1390. {
  1391. SPDBG_FUNC( "CVoiceDataObj::PhonToID" );
  1392. long phon_id;
  1393. if( PhonHashLookup( pd, phone_str, &phon_id ) )
  1394. {
  1395. phon_id = NO_PHON;
  1396. }
  1397. return phon_id;
  1398. } /* CVoiceDataObj::PhonToID */
  1399. /*****************************************************************************
  1400. * CVoiceDataObj::PhonFromID *
  1401. *---------------------------*
  1402. * Description:
  1403. * Return string from phoneme ID
  1404. *
  1405. ********************************************************************** MC ***/
  1406. char *CVoiceDataObj::PhonFromID( PHON_DICT *pd, long phone_id )
  1407. {
  1408. SPDBG_FUNC( "CVoiceDataObj::PhonFromID" );
  1409. char *strPtr;
  1410. long *pOffs;
  1411. pOffs = (long*)((char*)pd + pd->phones_list);
  1412. strPtr = (char*) ((char*)pd + pOffs[phone_id]);
  1413. return strPtr;
  1414. } /* CVoiceDataObj::PhonFromID */
  1415. #define CNODE_ISA_LEAF(n) ((n)->yes < 0)
  1416. #define BADTREE_ERROR (-1)
  1417. #define PARAM_ERROR (-2)
  1418. #define END_OF_PROD 65535
  1419. #define WB_BEGIN 1
  1420. #define WB_END 2
  1421. #define WB_SINGLE 4
  1422. #define WB_WWT 8
  1423. #define POS_TYPE 4
  1424. #define GET_BIT(p,feat,i,b) \
  1425. { \
  1426. (i) = ( (p)+POS_TYPE+(feat)->nstateq ) / 32; \
  1427. (b) = 1 << ( ((p)+POS_TYPE+(feat)->nstateq ) % 32); \
  1428. }
  1429. #define GET_RBIT(p,feat,i,b) \
  1430. { \
  1431. GET_BIT(p,feat,i,b); \
  1432. (i) += (feat)->nint32perq; \
  1433. }
  1434. #define GET_CBIT(p,feat,i,b) \
  1435. { \
  1436. GET_BIT(p,feat,i,b); \
  1437. (i) += 2 * (feat)->nint32perq; \
  1438. }
  1439. /*****************************************************************************
  1440. * AnswerQ *
  1441. *---------*
  1442. * Description:
  1443. * Tree node test.
  1444. *
  1445. ********************************************************************** MC ***/
  1446. static _inline long AnswerQ( unsigned short *prod, long *uniq_prod,
  1447. long li, long bitpos, long ri, long rbitpos,
  1448. long pos, long nint32perProd)
  1449. {
  1450. UNALIGNED long *p;
  1451. for( ; *prod != END_OF_PROD; prod++ )
  1452. {
  1453. p = &uniq_prod[(*prod) * nint32perProd];
  1454. if( ((p[0] & pos) == pos) && (p[li] & bitpos) && (p[ri] & rbitpos) )
  1455. {
  1456. return true;
  1457. }
  1458. }
  1459. return false;
  1460. } /* AnswerQ */
  1461. /*****************************************************************************
  1462. * CVoiceDataObj::GetTriphoneID *
  1463. *------------------------------*
  1464. * Description:
  1465. * Retrieve triphone ID from phoneme context.+++
  1466. * Store result into 'pResult'
  1467. *
  1468. ********************************************************************** MC ***/
  1469. HRESULT CVoiceDataObj::GetTriphoneID( TRIPHONE_TREE *forest,
  1470. long phon, // target phon
  1471. long leftPhon, // left context
  1472. long rightPhon, // right context
  1473. long pos, // word position ("b", "e" or "s"
  1474. PHON_DICT *pd,
  1475. ULONG *pResult)
  1476. {
  1477. SPDBG_FUNC( "CVoiceDataObj::GetTriphoneID" );
  1478. C_NODE *cnode, *croot;
  1479. TREE_ELEM *tree = NULL;
  1480. long *uniq_prod;
  1481. char *ll, *rr;
  1482. long li, bitpos, ri, rbitpos, nint32perProd, c;
  1483. unsigned short *prodspace;
  1484. FEATURE *feat;
  1485. long *pOffs;
  1486. HRESULT hr = S_OK;
  1487. long triphoneID = 0;
  1488. if( (phon < 0) || (phon >= pd->numCiPhones) ||
  1489. (leftPhon < 0) || (leftPhon >= pd->numCiPhones) ||
  1490. (rightPhon < 0) || (rightPhon >= pd->numCiPhones) )
  1491. {
  1492. //--------------------------------
  1493. // Phon out of range!
  1494. //--------------------------------
  1495. hr = E_INVALIDARG;
  1496. }
  1497. if( SUCCEEDED(hr) )
  1498. {
  1499. c = phon;
  1500. tree = &forest->tree[c];
  1501. if( tree->nnodes == 0 )
  1502. {
  1503. //--------------------------------
  1504. // No CD triphones in tree!
  1505. //--------------------------------
  1506. hr = E_INVALIDARG;
  1507. }
  1508. }
  1509. if( SUCCEEDED(hr) )
  1510. {
  1511. if( pos == 'b' || pos == 'B' )
  1512. {
  1513. pos = WB_BEGIN;
  1514. }
  1515. else if( pos == 'e' || pos == 'E' )
  1516. {
  1517. pos = WB_END;
  1518. }
  1519. else if( pos == 's' || pos == 'S' )
  1520. {
  1521. pos = WB_SINGLE;
  1522. }
  1523. else if( pos == '\0' )
  1524. {
  1525. pos = WB_WWT;
  1526. }
  1527. else
  1528. {
  1529. //--------------------------------
  1530. // Unknown word position
  1531. //--------------------------------
  1532. hr = E_INVALIDARG;
  1533. }
  1534. }
  1535. if( SUCCEEDED(hr) )
  1536. {
  1537. pOffs = (long*)((char*)pd + pd->phones_list);
  1538. ll = (char*) ((char*)pd + pOffs[leftPhon]);
  1539. if( ll[0] == '+' || _strnicmp(ll, "SIL", 3) == 0 )
  1540. {
  1541. leftPhon = forest->silPhoneId;
  1542. }
  1543. rr = (char*) ((char*)pd + pOffs[rightPhon]);
  1544. if( rr[0] == '+' || _strnicmp(rr, "SIL", 3) == 0 ) // includes SIL
  1545. {
  1546. rightPhon = forest->silPhoneId;
  1547. }
  1548. else if( forest->nonSilCxt >= 0 && (pos == WB_END || pos == WB_SINGLE) )
  1549. {
  1550. rightPhon = forest->nonSilCxt;
  1551. }
  1552. feat = &forest->feat;
  1553. GET_BIT(leftPhon,feat,li,bitpos);
  1554. GET_RBIT(rightPhon,feat,ri,rbitpos);
  1555. uniq_prod = (long*)(forest->uniq_prod_Offset + (char*)forest); // Offset to ABS
  1556. croot = cnode = (C_NODE*)(tree->nodes + (char*)forest); // Offset to ABS
  1557. nint32perProd = forest->nint32perProd;
  1558. while( ! CNODE_ISA_LEAF(cnode) )
  1559. {
  1560. prodspace = (unsigned short*)((char*)forest + cnode->prod); // Offset to ABS
  1561. if( AnswerQ (prodspace, uniq_prod, li, bitpos, ri, rbitpos, pos, nint32perProd) )
  1562. {
  1563. cnode = &croot[cnode->yes];
  1564. }
  1565. else
  1566. {
  1567. cnode = &croot[cnode->no];
  1568. }
  1569. }
  1570. //-----------------------------
  1571. // Return successful result
  1572. //-----------------------------
  1573. triphoneID = (ULONG) cnode->no;
  1574. }
  1575. *pResult = triphoneID;
  1576. return hr;
  1577. } /* CVoiceDataObj::GetTriphoneID */
  1578. /*****************************************************************************
  1579. * FIR_Filter *
  1580. *------------*
  1581. * Description:
  1582. * FIR filter. For an input x[n] it does an FIR filter with
  1583. * output y[n]. Result is in place. pHistory contains the last
  1584. * cNumTaps values.
  1585. *
  1586. * y[n] = pFilter[0] * x[n] + pFilter[1] * x[n - 1]
  1587. * + ... + pFilter[cNumTaps - 1] * x[n - cNumTaps - 1]
  1588. *
  1589. ********************************************************************** MC ***/
  1590. void CVoiceDataObj::FIR_Filter( float *pVector, long cNumSamples, float *pFilter,
  1591. float *pHistory, long cNumTaps )
  1592. {
  1593. SPDBG_FUNC( "CVoiceDataObj::FIR_Filter" );
  1594. long i, j;
  1595. float sum;
  1596. for( i = 0; i < cNumSamples; i++ )
  1597. {
  1598. pHistory[0] = pVector[i];
  1599. sum = pHistory[0] * pFilter[0];
  1600. for( j = cNumTaps - 1; j > 0; j-- )
  1601. {
  1602. sum += pHistory[j] * pFilter[j];
  1603. pHistory[j] = pHistory[j - 1];
  1604. }
  1605. pVector[i] = sum;
  1606. }
  1607. } /* CVoiceDataObj::FIR_Filter */
  1608. /*****************************************************************************
  1609. * IIR_Filter *
  1610. *------------*
  1611. * Description:
  1612. * IIR filter. For an input x[n] it does an IIR filter with
  1613. * output y[n]. Result is in place. pHistory contains the last
  1614. * cNumTaps values.
  1615. *
  1616. * y[n] = pFilter[0] * x[n] + pFilter[1] * y[n - 1]
  1617. * + ... + pFilter[cNumTaps - 1] * y[n - cNumTaps - 1]
  1618. *
  1619. ********************************************************************** MC ***/
  1620. void CVoiceDataObj::IIR_Filter( float *pVector, long cNumSamples, float *pFilter,
  1621. float *pHistory, long cNumTaps )
  1622. {
  1623. SPDBG_FUNC( "CVoiceDataObj::IIR_Filter" );
  1624. long i, j;
  1625. float sum;
  1626. for( i = 0; i < cNumSamples; i++ )
  1627. {
  1628. sum = pVector[i] * pFilter[0];
  1629. for( j = cNumTaps - 1; j > 0; j-- )
  1630. {
  1631. pHistory[j] = pHistory[j - 1];
  1632. sum += pHistory[j] * pFilter[j];
  1633. }
  1634. pVector[i] = sum;
  1635. pHistory[0] = sum;
  1636. }
  1637. } /* CVoiceDataObj::IIR_Filter */