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.

882 lines
25 KiB

  1. /******************************************************************************
  2. * CFmtConvert.cpp *
  3. *-----------------*
  4. * Functions of CFmtConvert class.
  5. *------------------------------------------------------------------------------
  6. * Copyright (C) 2000 Microsoft Corporation Date: 05/03/00
  7. * All Rights Reserved
  8. *
  9. ********************************************************************** DING ***/
  10. #include "FmtConvert.h"
  11. #include "sigproc.h"
  12. #include "vapiIo.h"
  13. #include <math.h>
  14. #include <assert.h>
  15. /*****************************************************************************
  16. * Constructor *
  17. *---------------*
  18. * Description:
  19. *
  20. ********************************************************************* DING ***/
  21. CFmtConvert::CFmtConvert(double dHalfFilterLen)
  22. {
  23. m_fResetFilter = true;
  24. m_pdFilterCoef = NULL;
  25. m_pdLeftMemory = NULL;
  26. m_pdRightMemory = NULL;
  27. m_dHalfFilterLen = dHalfFilterLen;
  28. }
  29. /*****************************************************************************
  30. * Destructor *
  31. *---------------*
  32. * Description:
  33. *
  34. ********************************************************************* DING ***/
  35. CFmtConvert::~CFmtConvert()
  36. {
  37. DeleteResamplingFilter();
  38. DeleteBuffers();
  39. }
  40. /*****************************************************************************
  41. * SetInputFormat *
  42. *----------------------*
  43. * Description:
  44. *
  45. ********************************************************************* DING ***/
  46. void CFmtConvert::SetInputFormat(WAVEFORMATEX* pUserWavFormat)
  47. {
  48. assert(pUserWavFormat);
  49. assert(pUserWavFormat->nSamplesPerSec > 0 );
  50. if ( pUserWavFormat )
  51. {
  52. m_InWavFormat = *pUserWavFormat;
  53. m_fResetFilter = true;
  54. }
  55. }
  56. /*****************************************************************************
  57. * SetOutputFormat *
  58. *----------------------*
  59. * Description:
  60. *
  61. ********************************************************************* DING ***/
  62. void CFmtConvert::SetOutputFormat(WAVEFORMATEX* pUserWavFormat)
  63. {
  64. assert(pUserWavFormat);
  65. if ( pUserWavFormat )
  66. {
  67. m_OutWavFormat = *pUserWavFormat;
  68. m_fResetFilter = true;
  69. }
  70. }
  71. /*****************************************************************************
  72. * ConvertSamples *
  73. *----------------------*
  74. * Description:
  75. * first read samples into VAPI_PCM16, then judge cases :
  76. * 1. STEREO -> mono + resampling
  77. * STEREO -> 1 mono -> reSampling
  78. * 2. mono -> STEREO + resampling
  79. * mono -> reSampling -> STEREO
  80. * 3. STEREO -> STEREO + resampling
  81. * STEREO -> 2 MONO - > reSampling -> 2 MONO -> STEREO
  82. * 4. mono -> mono + resampling
  83. * mono -> reSampling -> mono
  84. *
  85. ********************************************************************* DING ***/
  86. HRESULT CFmtConvert::ConvertSamples(const void* pvInSamples, int iInSampleLen,
  87. void** ppvOutSamples, int* piOutSampleLen)
  88. {
  89. short* pnInSample = NULL;
  90. short* pnOutSample = NULL;
  91. short *pnBuff = NULL;
  92. short *pnBuff2 = NULL;
  93. double *pdBuff = NULL;
  94. double *pdBuff1 = NULL;
  95. int iLen;
  96. int iNumSamples = iInSampleLen;
  97. int iInFormatType;
  98. int iOutFormatType;
  99. HRESULT hr = S_OK;
  100. assert( m_InWavFormat.nSamplesPerSec > 0 );
  101. assert( m_InWavFormat.nChannels <= 2 );
  102. assert( m_InWavFormat.nChannels > 0 );
  103. assert( m_OutWavFormat.nChannels > 0 );
  104. assert( m_OutWavFormat.nSamplesPerSec > 0 );
  105. assert( m_OutWavFormat.nChannels <= 2 );
  106. //--- need reset filter
  107. if (m_fResetFilter)
  108. {
  109. DeleteResamplingFilter();
  110. DeleteBuffers();
  111. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  112. {
  113. hr = CreateResamplingFilter(m_InWavFormat.nSamplesPerSec, m_OutWavFormat.nSamplesPerSec);
  114. if (FAILED(hr))
  115. {
  116. return hr;
  117. }
  118. hr = CreateBuffers();
  119. if (FAILED(hr))
  120. {
  121. return hr;
  122. }
  123. }
  124. m_fResetFilter = false;
  125. }
  126. iInFormatType = VapiIO::TypeOf (&m_InWavFormat);
  127. iOutFormatType = VapiIO::TypeOf (&m_OutWavFormat);
  128. if ( iInFormatType < 0 || iOutFormatType < 0 )
  129. {
  130. return E_FAIL;
  131. }
  132. if ( m_OutWavFormat.nSamplesPerSec == m_InWavFormat.nSamplesPerSec && iOutFormatType == iInFormatType && m_OutWavFormat.nChannels == m_InWavFormat.nChannels )
  133. {
  134. *piOutSampleLen = iInSampleLen;
  135. if ( (*ppvOutSamples = (void *)new char [*piOutSampleLen * VapiIO::SizeOf(iOutFormatType)]) == NULL )
  136. {
  137. return E_OUTOFMEMORY;
  138. }
  139. memcpy((char*)(*ppvOutSamples), (char*)pvInSamples, (*piOutSampleLen) * VapiIO::SizeOf(iOutFormatType));
  140. return hr;
  141. }
  142. //--- Convert samples to VAPI_PCM16
  143. if ((pnInSample = new short [iNumSamples]) == NULL)
  144. {
  145. return E_OUTOFMEMORY;
  146. }
  147. VapiIO::DataFormatConversion ((char *)pvInSamples, iInFormatType, (char*)pnInSample, VAPI_PCM16, iNumSamples);
  148. //--- case 1
  149. if ( m_InWavFormat.nChannels == 2 && m_OutWavFormat.nChannels == 1 )
  150. {
  151. Stereo2Mono(pnInSample, &iNumSamples, &pnOutSample);
  152. delete[] pnInSample;
  153. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  154. {
  155. pdBuff1 = Short2Double (pnOutSample, iNumSamples);
  156. delete[] pnOutSample;
  157. if ( pdBuff1 == NULL )
  158. {
  159. return E_OUTOFMEMORY;
  160. }
  161. //--- resample
  162. hr = Resampling(pdBuff1, iNumSamples, m_pdLeftMemory, &pdBuff, &iLen);
  163. if ( FAILED(hr) )
  164. {
  165. return hr;
  166. }
  167. delete[] pdBuff1;
  168. pnBuff = Double2Short (pdBuff, iLen);
  169. delete[] pdBuff;
  170. if ( pnBuff == NULL )
  171. {
  172. return E_OUTOFMEMORY;
  173. }
  174. iNumSamples = iLen;
  175. }
  176. else
  177. {
  178. if ( (pnBuff = new short [iNumSamples]) == NULL )
  179. {
  180. return E_OUTOFMEMORY;
  181. }
  182. memcpy(pnBuff, pnOutSample, iNumSamples * sizeof(*pnInSample));
  183. delete[] pnOutSample;
  184. }
  185. }
  186. //--- case 2
  187. if ( m_InWavFormat.nChannels == 1 && m_OutWavFormat.nChannels == 2 )
  188. {
  189. //--- resampling
  190. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  191. {
  192. pdBuff1 = Short2Double (pnInSample, iNumSamples);
  193. delete[] pnInSample;
  194. if ( pdBuff1 == NULL )
  195. {
  196. return E_OUTOFMEMORY;
  197. }
  198. //--- resample
  199. hr = Resampling(pdBuff1, iNumSamples, m_pdLeftMemory, &pdBuff, &iLen);
  200. if ( FAILED(hr) )
  201. {
  202. return hr;
  203. }
  204. delete[] pdBuff1;
  205. iNumSamples = iLen;
  206. pnInSample = Double2Short (pdBuff, iLen);
  207. delete[] pdBuff;
  208. if ( pnInSample == NULL )
  209. {
  210. return E_OUTOFMEMORY;
  211. }
  212. }
  213. //--- mono -> stereo
  214. Mono2Stereo(pnInSample, &iNumSamples, &pnBuff);
  215. delete[] pnInSample;
  216. }
  217. //--- case 3
  218. if ( m_InWavFormat.nChannels == 2 && m_OutWavFormat.nChannels == 2 )
  219. {
  220. //--- resampling
  221. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  222. {
  223. SplitStereo(pnInSample, &iNumSamples, &pnBuff, &pnBuff2);
  224. delete[] pnInSample;
  225. // channel 1
  226. pdBuff1 = Short2Double (pnBuff, iNumSamples);
  227. delete[] pnBuff;
  228. if ( pdBuff1 == NULL )
  229. {
  230. return E_OUTOFMEMORY;
  231. }
  232. //--- resample
  233. hr = Resampling(pdBuff1, iNumSamples, m_pdLeftMemory, &pdBuff, &iLen);
  234. if ( FAILED(hr) )
  235. {
  236. return hr;
  237. }
  238. delete[] pdBuff1;
  239. pnInSample = Double2Short (pdBuff, iLen);
  240. if ( pnInSample == NULL )
  241. {
  242. return E_OUTOFMEMORY;
  243. }
  244. delete[] pdBuff;
  245. // channel 2
  246. pdBuff1 = Short2Double (pnBuff2, iNumSamples);
  247. delete[] pnBuff2;
  248. if ( pdBuff1 == NULL )
  249. {
  250. return E_OUTOFMEMORY;
  251. }
  252. //--- resample
  253. hr = Resampling(pdBuff1, iNumSamples, m_pdRightMemory, &pdBuff, &iLen);
  254. if ( FAILED(hr) )
  255. {
  256. return hr;
  257. }
  258. delete[] pdBuff1;
  259. iNumSamples = iLen;
  260. pnOutSample = Double2Short (pdBuff, iNumSamples);
  261. if ( pnOutSample == NULL )
  262. {
  263. return E_OUTOFMEMORY;
  264. }
  265. delete[] pdBuff;
  266. MergeStereo(pnInSample, pnOutSample, &iNumSamples, &pnBuff);
  267. delete[] pnInSample;
  268. delete[] pnOutSample;
  269. }
  270. else
  271. {
  272. if ( (pnBuff = new short [iNumSamples]) == NULL )
  273. {
  274. return E_OUTOFMEMORY;
  275. }
  276. memcpy(pnBuff, pnInSample, iNumSamples * sizeof(*pnBuff));
  277. delete[] pnInSample;
  278. }
  279. }
  280. //--- case 4
  281. if ( m_InWavFormat.nChannels == 1 && m_OutWavFormat.nChannels == 1 )
  282. {
  283. //--- resampling
  284. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  285. {
  286. pdBuff1 = Short2Double (pnInSample, iNumSamples);
  287. delete[] pnInSample;
  288. if ( pdBuff1 == NULL )
  289. {
  290. return E_OUTOFMEMORY;
  291. }
  292. //--- resample
  293. hr = Resampling(pdBuff1, iNumSamples, m_pdLeftMemory, &pdBuff, &iLen);
  294. if ( FAILED(hr) )
  295. {
  296. return hr;
  297. }
  298. delete[] pdBuff1;
  299. iNumSamples = iLen;
  300. pnBuff = Double2Short (pdBuff, iLen);
  301. delete[] pdBuff;
  302. if ( pnBuff == NULL )
  303. {
  304. return E_OUTOFMEMORY;
  305. }
  306. }
  307. else
  308. {
  309. if ( (pnBuff = new short [iNumSamples]) == NULL )
  310. {
  311. return E_OUTOFMEMORY;
  312. }
  313. memcpy(pnBuff, pnInSample, iNumSamples * sizeof(*pnBuff));
  314. delete[] pnInSample;
  315. }
  316. }
  317. //--- output
  318. if ( iOutFormatType < 0 )
  319. {
  320. iOutFormatType = iInFormatType;
  321. }
  322. *piOutSampleLen = iNumSamples;
  323. //---Convert samples to output format
  324. if ( (*ppvOutSamples = (void *) new char [iNumSamples * VapiIO::SizeOf(iOutFormatType)]) == NULL )
  325. {
  326. return E_OUTOFMEMORY;
  327. }
  328. VapiIO::DataFormatConversion((char*)pnBuff, VAPI_PCM16, (char*)*ppvOutSamples, iOutFormatType, iNumSamples);
  329. delete[] pnBuff;
  330. m_eChunkStatus = FMTCNVT_BLOCK;
  331. return hr;
  332. }
  333. /*****************************************************************************
  334. * FlushLastBuff *
  335. *---------------------*
  336. * Description:
  337. *
  338. ********************************************************************* DING ***/
  339. HRESULT CFmtConvert::FlushLastBuff(void** ppvOutSamples, int* piOutSampleLen)
  340. {
  341. short* pnInSample = NULL;
  342. short* pnOutSample = NULL;
  343. short *pnBuff = NULL;
  344. double *pdBuff1 = NULL;
  345. double *pdBuff2 = NULL;
  346. int iBuffLen;
  347. int iOutFormatType = VapiIO::TypeOf (&m_OutWavFormat);
  348. HRESULT hr = S_OK;
  349. assert( m_InWavFormat.nSamplesPerSec > 0 );
  350. assert( m_InWavFormat.nChannels <= 2 );
  351. assert( m_InWavFormat.nChannels > 0 );
  352. assert( m_OutWavFormat.nChannels > 0 );
  353. assert( m_OutWavFormat.nSamplesPerSec > 0 );
  354. assert( m_OutWavFormat.nChannels <= 2 );
  355. m_eChunkStatus = FMTCNVT_LAST;
  356. if ( m_InWavFormat.nSamplesPerSec != m_OutWavFormat.nSamplesPerSec )
  357. {
  358. if ( m_InWavFormat.nChannels == 2 && m_OutWavFormat.nChannels == 2 )
  359. {
  360. hr = Resampling(pdBuff1, 0, m_pdLeftMemory, &pdBuff1, &iBuffLen);
  361. if ( FAILED(hr) )
  362. {
  363. return hr;
  364. }
  365. hr = Resampling(pdBuff1, 0, m_pdRightMemory, &pdBuff2, &iBuffLen);
  366. if ( FAILED(hr) )
  367. {
  368. return hr;
  369. }
  370. pnInSample = Double2Short (pdBuff1, iBuffLen);
  371. if ( pnInSample == NULL )
  372. {
  373. return E_OUTOFMEMORY;
  374. }
  375. delete[] pdBuff1;
  376. pnOutSample = Double2Short (pdBuff2, iBuffLen);
  377. if ( pnOutSample == NULL )
  378. {
  379. return E_OUTOFMEMORY;
  380. }
  381. delete[] pdBuff2;
  382. MergeStereo(pnInSample, pnOutSample, &iBuffLen, &pnBuff);
  383. delete[] pnInSample;
  384. delete[] pnOutSample;
  385. }
  386. else
  387. {
  388. hr = Resampling(pdBuff1, 0, m_pdLeftMemory, &pdBuff1, &iBuffLen);
  389. if ( FAILED(hr) )
  390. {
  391. return hr;
  392. }
  393. pnBuff = Double2Short (pdBuff1, iBuffLen);
  394. if ( pnBuff == NULL )
  395. {
  396. return E_OUTOFMEMORY;
  397. }
  398. delete[] pdBuff1;
  399. if ( m_InWavFormat.nChannels == 1 && m_OutWavFormat.nChannels == 2 )
  400. {
  401. if ( (pnOutSample = new short [iBuffLen]) == NULL )
  402. {
  403. return E_OUTOFMEMORY;
  404. }
  405. memcpy((char *)pnOutSample, (char *)pnBuff, iBuffLen * sizeof(*pnBuff));
  406. delete[] pnBuff;
  407. Mono2Stereo(pnOutSample, &iBuffLen, &pnBuff);
  408. delete[] pnOutSample;
  409. }
  410. }
  411. *piOutSampleLen = iBuffLen;
  412. //---Convert samples to output format
  413. if ( (*ppvOutSamples = (void *) new char [iBuffLen * VapiIO::SizeOf(iOutFormatType)]) == NULL )
  414. {
  415. return E_OUTOFMEMORY;
  416. }
  417. VapiIO::DataFormatConversion((char*)pnBuff, VAPI_PCM16, (char*)*ppvOutSamples, iOutFormatType, iBuffLen);
  418. delete[] pnBuff;
  419. }
  420. return hr;
  421. }
  422. /*****************************************************************************
  423. * Short2Double *
  424. *----------------------*
  425. * Description:
  426. * convert short array to double array
  427. *
  428. ********************************************************************* DING ***/
  429. double* CFmtConvert::Short2Double (short* pnIn, int iLen)
  430. {
  431. double* pdOut = NULL;
  432. if ( (pdOut = new double [iLen]) != NULL )
  433. {
  434. for ( int i = 0; i < iLen; i++)
  435. {
  436. pdOut[i] = (double)pnIn[i];
  437. }
  438. }
  439. return pdOut;
  440. }
  441. /*****************************************************************************
  442. * Double2Short *
  443. *----------------------*
  444. * Description:
  445. * convert double array to short array
  446. *
  447. ********************************************************************* DING ***/
  448. short* CFmtConvert::Double2Short (double* pdIn, int iLen)
  449. {
  450. short* pnOut = NULL;
  451. if ( (pnOut = new short [iLen]) != NULL )
  452. {
  453. for ( int i = 0; i < iLen; i++)
  454. {
  455. pnOut[i] = (short)(pdIn[i] + 0.5);
  456. }
  457. }
  458. return pnOut;
  459. }
  460. /*****************************************************************************
  461. * Mono2Stereo *
  462. *----------------------*
  463. * Description:
  464. * convert mono speech to stereo speech
  465. *
  466. ********************************************************************* DING ***/
  467. HRESULT CFmtConvert::Mono2Stereo (short* pnInSample, int* piNumSamples, short** ppnOutSample)
  468. {
  469. int iLen;
  470. iLen = *piNumSamples;
  471. if ( (*ppnOutSample = new short [iLen * 2]) == NULL )
  472. {
  473. return E_OUTOFMEMORY;
  474. }
  475. int k = 0;
  476. for ( int i = 0; i < iLen; i++)
  477. {
  478. (*ppnOutSample)[k] = pnInSample[i];
  479. (*ppnOutSample)[k + 1] = pnInSample[i];
  480. k +=2;
  481. }
  482. *piNumSamples = 2 * iLen;
  483. return S_OK;
  484. }
  485. /*****************************************************************************
  486. * Stereo2Mono *
  487. *----------------------*
  488. * Description:
  489. * convert stereo speech to mono speech
  490. *
  491. ********************************************************************* DING ***/
  492. HRESULT CFmtConvert::Stereo2Mono (short* pnInSample, int* piNumSamples, short** ppnOutSample)
  493. {
  494. int iLen = (*piNumSamples) / 2;
  495. if ( (*ppnOutSample = new short [iLen]) == NULL )
  496. {
  497. return E_OUTOFMEMORY;
  498. }
  499. int k = 0;
  500. for ( int i = 0;i < *piNumSamples; i += 2)
  501. {
  502. (*ppnOutSample)[k++] = (short)( (double)(pnInSample[i] + pnInSample[i + 1]) / 2.0 + 0.5);
  503. }
  504. *piNumSamples = iLen;
  505. return S_OK;
  506. }
  507. /*****************************************************************************
  508. * MergeStereo *
  509. *----------------------*
  510. * Description:
  511. * merge 2 channel signals into one signal
  512. *
  513. ********************************************************************* DING ***/
  514. HRESULT CFmtConvert::MergeStereo (short* pnLeftSamples, short* pnRightSamples,
  515. int *piNumSamples, short** ppnOutSamples)
  516. {
  517. int iLen = (*piNumSamples) * 2;
  518. if ( (*ppnOutSamples = new short [iLen]) == NULL )
  519. {
  520. return E_OUTOFMEMORY;
  521. }
  522. int k = 0;
  523. for ( int i = 0; i < *piNumSamples; i++)
  524. {
  525. (*ppnOutSamples)[k] = pnLeftSamples[i];
  526. (*ppnOutSamples)[k + 1] = pnRightSamples[i];
  527. k += 2;
  528. }
  529. *piNumSamples = iLen;
  530. return S_OK;
  531. }
  532. /*****************************************************************************
  533. * SplitStereo *
  534. *----------------------*
  535. * Description:
  536. * split stereo signals into 2 channel mono signals
  537. *
  538. ********************************************************************* DING ***/
  539. HRESULT CFmtConvert::SplitStereo (short* pnInSample, int* piNumSamples,
  540. short** ppnLeftSamples, short** ppnRightSamples)
  541. {
  542. int iLen = (*piNumSamples) / 2;
  543. if ( (*ppnLeftSamples = new short [iLen]) == NULL )
  544. {
  545. return E_OUTOFMEMORY;
  546. }
  547. if ( (*ppnRightSamples = new short [iLen]) == NULL )
  548. {
  549. return E_OUTOFMEMORY;
  550. }
  551. int k = 0;
  552. for ( int i = 0; i < *piNumSamples; i += 2)
  553. {
  554. (*ppnLeftSamples)[k] = pnInSample[i];
  555. (*ppnRightSamples)[k] = pnInSample[i + 1];
  556. k++;
  557. }
  558. *piNumSamples = iLen;
  559. return S_OK;
  560. }
  561. /*****************************************************************************
  562. * CreateResamplingFilter *
  563. *------------------------*
  564. * Description:
  565. *
  566. ******************************************************************* DING ***/
  567. HRESULT CFmtConvert::CreateResamplingFilter (int iInSampFreq, int iOutSampFreq)
  568. {
  569. int iLimitFactor;
  570. assert (iInSampFreq > 0);
  571. assert (iOutSampFreq > 0);
  572. FindResampleFactors (iInSampFreq, iOutSampFreq);
  573. iLimitFactor = (m_iUpFactor > m_iDownFactor) ? m_iUpFactor : m_iDownFactor;
  574. m_iFilterHalf = (int)(iInSampFreq * iLimitFactor * m_dHalfFilterLen);
  575. m_iFilterLen = 2 * m_iFilterHalf + 1;
  576. if ( !(m_pdFilterCoef = WindowedLowPass(.5 / (double)iLimitFactor, (double)m_iUpFactor)))
  577. {
  578. return E_FAIL;
  579. }
  580. return S_OK;
  581. }
  582. /*****************************************************************************
  583. * DeleteResamplingFilter *
  584. *------------------------*
  585. * Description:
  586. *
  587. ******************************************************************* DING ***/
  588. void CFmtConvert::DeleteResamplingFilter()
  589. {
  590. if ( m_pdFilterCoef )
  591. {
  592. delete[] m_pdFilterCoef;
  593. m_pdFilterCoef = NULL;
  594. }
  595. }
  596. /*****************************************************************************
  597. * CreateBuffers *
  598. *----------------*
  599. * Description:
  600. *
  601. ******************************************************************* DING ***/
  602. HRESULT CFmtConvert::CreateBuffers()
  603. {
  604. assert(m_iUpFactor > 0);
  605. m_iBuffLen = (int)( (double)m_iFilterLen / (double)m_iUpFactor);
  606. if ( (m_pdLeftMemory = new double [m_iBuffLen]) == NULL )
  607. {
  608. return E_OUTOFMEMORY;
  609. }
  610. if ( (m_pdRightMemory = new double [m_iBuffLen]) == NULL )
  611. {
  612. return E_OUTOFMEMORY;
  613. }
  614. for ( int i = 0; i < m_iBuffLen; i++)
  615. {
  616. m_pdLeftMemory[i] = 0.0;
  617. m_pdRightMemory[i] = 0.0;
  618. }
  619. m_eChunkStatus = FMTCNVT_FIRST; // first chunk
  620. return S_OK;
  621. }
  622. /*****************************************************************************
  623. * DeleteBuffers *
  624. *----------------*
  625. * Description:
  626. *
  627. ******************************************************************* DING ***/
  628. void CFmtConvert::DeleteBuffers()
  629. {
  630. if ( m_pdLeftMemory )
  631. {
  632. delete[] m_pdLeftMemory;
  633. m_pdLeftMemory = NULL;
  634. }
  635. if ( m_pdRightMemory )
  636. {
  637. delete[] m_pdRightMemory;
  638. m_pdRightMemory = NULL;
  639. }
  640. }
  641. /*****************************************************************************
  642. * WindowedLowPass *
  643. *-----------------*
  644. * Description:
  645. * Creates a low pass filter using the windowing method.
  646. * dCutOff is spec. in normalized frequency
  647. ******************************************************************* DING ***/
  648. double* CFmtConvert::WindowedLowPass (double dCutOff, double dGain)
  649. {
  650. double* pdCoeffs = NULL;
  651. double* pdWindow = NULL;
  652. double dArg;
  653. double dSinc;
  654. assert (dCutOff>0.0 && dCutOff<0.5);
  655. pdWindow = ComputeWindow(WINDOW_BLACK, m_iFilterLen, true);
  656. if (!pdWindow)
  657. {
  658. return NULL;
  659. }
  660. pdCoeffs = new double[m_iFilterLen];
  661. if (pdCoeffs)
  662. {
  663. dArg = 2.0 * M_PI * dCutOff;
  664. pdCoeffs[m_iFilterHalf] = (double)(dGain * 2.0 * dCutOff);
  665. for (long i = 1; i <= m_iFilterHalf; i++)
  666. {
  667. dSinc = dGain * sin(dArg * i) / (M_PI * i) * pdWindow[m_iFilterHalf- i];
  668. pdCoeffs[m_iFilterHalf+i] = (double)dSinc;
  669. pdCoeffs[m_iFilterHalf-i] = (double)dSinc;
  670. }
  671. }
  672. delete[] pdWindow;
  673. return pdCoeffs;
  674. }
  675. /*****************************************************************************
  676. * FindResampleFactors *
  677. *---------------------*
  678. * Description:
  679. *
  680. ******************************************************************* DING ***/
  681. void CFmtConvert::FindResampleFactors (int iInSampFreq, int iOutSampFreq)
  682. {
  683. static int piPrimes[] = {2,3,5,7,11,13,17,19,23,29,31,37};
  684. static int iPrimesLen = sizeof (piPrimes) / sizeof (piPrimes[0]);
  685. int iDiv = 1;
  686. int i;
  687. while (iDiv)
  688. {
  689. iDiv = 0;
  690. for (i = 0; i < iPrimesLen; i++)
  691. {
  692. if ( (iInSampFreq % piPrimes[i]) == 0 && (iOutSampFreq % piPrimes[i]) == 0 )
  693. {
  694. iInSampFreq /= piPrimes[i];
  695. iOutSampFreq /= piPrimes[i];
  696. iDiv = 1;
  697. break;
  698. }
  699. }
  700. }
  701. m_iUpFactor = iOutSampFreq;
  702. m_iDownFactor = iInSampFreq;
  703. }
  704. /*****************************************************************************
  705. * Resampling *
  706. *------------*
  707. * Description:
  708. *
  709. ******************************************************************* DING ***/
  710. HRESULT CFmtConvert::Resampling (double* pdInSamples, int iInNumSamples, double *pdMemory,
  711. double** ppdOutSamples, int* piOutNumSamples)
  712. {
  713. int iPhase;
  714. double dAcum;
  715. int j;
  716. int n;
  717. int iAddHalf;
  718. if(m_eChunkStatus == FMTCNVT_FIRST)
  719. {
  720. *piOutNumSamples = (iInNumSamples * m_iUpFactor - m_iFilterHalf) / m_iDownFactor;
  721. iAddHalf = 1;
  722. }
  723. else if(m_eChunkStatus == FMTCNVT_BLOCK)
  724. {
  725. *piOutNumSamples = (iInNumSamples * m_iUpFactor) / m_iDownFactor;
  726. iAddHalf = 2;
  727. }
  728. else if(m_eChunkStatus == FMTCNVT_LAST)
  729. {
  730. *piOutNumSamples = (m_iFilterHalf * m_iUpFactor) / m_iDownFactor;
  731. iAddHalf = 2;
  732. }
  733. *ppdOutSamples = new double[*piOutNumSamples];
  734. if (*ppdOutSamples == NULL)
  735. {
  736. return E_FAIL;
  737. }
  738. for (int i = 0; i < *piOutNumSamples; i++)
  739. {
  740. dAcum = 0.0;
  741. n = (int)((i * m_iDownFactor - iAddHalf * m_iFilterHalf) / (double)m_iUpFactor);
  742. iPhase = (i * m_iDownFactor) - ( n * m_iUpFactor + iAddHalf * m_iFilterHalf);
  743. for ( j = 0; j < m_iFilterLen / m_iUpFactor; j++)
  744. {
  745. if (m_iUpFactor * j > iPhase)
  746. {
  747. if ( n + j >= 0 && n + j < iInNumSamples)
  748. {
  749. dAcum += pdInSamples[n + j] * m_pdFilterCoef[m_iUpFactor * j - iPhase];
  750. }
  751. else if ( n + j < 0 )
  752. {
  753. dAcum += pdMemory[m_iBuffLen + n + j] * m_pdFilterCoef[m_iUpFactor * j - iPhase];
  754. }
  755. }
  756. }
  757. (*ppdOutSamples)[i] = dAcum;
  758. }
  759. //--- store samples into buffer
  760. if(m_eChunkStatus != FMTCNVT_LAST)
  761. {
  762. for (n = 0, i = 0; i < m_iBuffLen; i++)
  763. {
  764. if (i + iInNumSamples >= m_iBuffLen)
  765. {
  766. pdMemory[i] = pdInSamples[n++];
  767. }
  768. else
  769. {
  770. pdMemory[i] = 0.0;
  771. }
  772. }
  773. }
  774. return S_OK;
  775. }