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.

1005 lines
29 KiB

  1. #include "precomp.h"
  2. #define ZONE_AP ZONE_DP
  3. #define _GetState() (m_dwState & DP_MASK_STATE)
  4. #define _SetState(s) (m_dwState = (m_dwState & ~DP_MASK_STATE) | (s & DP_MASK_STATE))
  5. #define _GetPlatform() (m_dwState & DP_MASK_PLATFORM)
  6. #define _SetPlatform(s) (m_dwState = (m_dwState & ~DP_MASK_PLATFORM) | (s & DP_MASK_PLATFORM))
  7. int g_wavein_prepare = 0;
  8. int g_waveout_prepare = 0;
  9. ///////////////////////////////////////////////////////
  10. //
  11. // Public methods
  12. //
  13. HRESULT AudioPacket::Initialize ( MEDIAPACKETINIT * p )
  14. {
  15. HRESULT hr = DPR_SUCCESS;
  16. FX_ENTRY ("AdPckt::Init")
  17. if (p == NULL)
  18. {
  19. DEBUGMSG (ZONE_AP, ("%s: invalid parameter (null ptr)\r\n", _fx_));
  20. return DPR_INVALID_PARAMETER;
  21. }
  22. hr = MediaPacket::Initialize( p);
  23. if (hr != DPR_SUCCESS)
  24. goto MyExit;
  25. // allocate conversion header only if m_pWaveData != m_pNetData
  26. if (m_pRawData != m_pNetData)
  27. {
  28. if (m_dwState & DP_FLAG_ACM)
  29. {
  30. m_pStrmConvHdr = MemAlloc (sizeof (ACMSTREAMHEADER));
  31. if (m_pStrmConvHdr == NULL)
  32. {
  33. DEBUGMSG (ZONE_AP, ("%s: MemAlloc4 (%ld) failed\r\n",
  34. _fx_, (ULONG) sizeof (ACMSTREAMHEADER)));
  35. hr = DPR_OUT_OF_MEMORY;
  36. goto MyExit;
  37. }
  38. }
  39. else
  40. {
  41. DEBUGMSG (ZONE_AP, ("%s: invalid platform (acm)\r\n", _fx_));
  42. hr = DPR_INVALID_PLATFORM;
  43. goto MyExit;
  44. }
  45. }
  46. else
  47. {
  48. m_pStrmConvHdr = NULL;
  49. }
  50. // allocate device header
  51. if (m_dwState & DP_FLAG_MMSYSTEM)
  52. {
  53. m_pDevHdr = MemAlloc (sizeof (WAVEHDR));
  54. if (m_pDevHdr == NULL)
  55. {
  56. DEBUGMSG (ZONE_AP, ("%s: MemAlloc5 (%ld) failed\r\n",
  57. _fx_, (ULONG) sizeof (WAVEHDR)));
  58. hr = DPR_OUT_OF_MEMORY;
  59. goto MyExit;
  60. }
  61. }
  62. else
  63. {
  64. DEBUGMSG (ZONE_AP, ("%s: invalid platform (mm)\r\n", _fx_));
  65. hr = DPR_INVALID_PLATFORM;
  66. goto MyExit;
  67. }
  68. MakeSilence ();
  69. MyExit:
  70. if (hr != DPR_SUCCESS)
  71. {
  72. m_fInitialized = FALSE;
  73. Release();
  74. }
  75. return hr;
  76. }
  77. HRESULT AudioPacket::Play ( MMIODEST *pmmioDest, UINT uDataType )
  78. {
  79. HRESULT hr = DPR_SUCCESS;
  80. DWORD dwState = _GetState ();
  81. MMRESULT mmr;
  82. FX_ENTRY ("AdPckt::Play")
  83. if (dwState != MP_STATE_DECODED && dwState != MP_STATE_RESET)
  84. {
  85. DEBUGMSG (ZONE_AP, ("%s: out of seq, state=0x%lX\r\n", _fx_, m_dwState));
  86. return DPR_OUT_OF_SEQUENCE;
  87. }
  88. if (uDataType == MP_DATATYPE_SILENCE)
  89. {
  90. LOG((LOGMSG_PLAY_SILENT,m_index,GetTickCount()));
  91. MakeSilence ();
  92. }
  93. else
  94. {
  95. if (uDataType == MP_DATATYPE_INTERPOLATED)
  96. {
  97. if (dwState == MP_STATE_DECODED)
  98. {
  99. LOG((LOGMSG_PLAY_INTERPOLATED,m_index,GetTickCount()));
  100. }
  101. else
  102. {
  103. LOG((LOGMSG_PLAY_SILENT,m_index,GetTickCount()));
  104. MakeSilence ();
  105. }
  106. }
  107. else
  108. {
  109. LOG((LOGMSG_PLAY,m_index, GetTickCount()));
  110. }
  111. }
  112. if (m_hDev)
  113. {
  114. if (m_dwState & DP_FLAG_MMSYSTEM)
  115. {
  116. ((WAVEHDR *) m_pDevHdr)->lpData = (char *) m_pDevData->data;
  117. // ((WAVEHDR *) m_pDevHdr)->dwBufferLength = (dwState == MP_STATE_DECODED ?
  118. // ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLengthUsed :
  119. // m_pDevData->length);
  120. ((WAVEHDR *) m_pDevHdr)->dwBufferLength = (dwState == MP_STATE_DECODED ?
  121. m_cbValidRawData : m_pDevData->length);
  122. ((WAVEHDR *) m_pDevHdr)->dwUser = (DWORD_PTR) this;
  123. ((WAVEHDR *) m_pDevHdr)->dwFlags &= ~(WHDR_DONE|WHDR_INQUEUE);
  124. ((WAVEHDR *) m_pDevHdr)->dwLoops = 0L;
  125. // feed this buffer to play
  126. mmr = waveOutWrite ((HWAVEOUT) m_hDev, (WAVEHDR *) m_pDevHdr, sizeof (WAVEHDR));
  127. if (mmr != MMSYSERR_NOERROR)
  128. {
  129. DEBUGMSG (ZONE_AP, ("%s: waveOutWrite failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  130. hr = DPR_CANT_WRITE_WAVE_DEV;
  131. // this is an extremely rare error, but we've seen it
  132. // occur on some sound cards
  133. // in this case, just set the "done" bit, mark the
  134. // state to the "playing", but still return an error.
  135. ((WAVEHDR *) m_pDevHdr)->dwFlags |= WHDR_DONE;
  136. goto MyExit;
  137. }
  138. }
  139. else
  140. {
  141. DEBUGMSG (ZONE_AP, ("%s: invalid platform (mm)\r\n", _fx_));
  142. hr = DPR_INVALID_PLATFORM;
  143. goto MyExit;
  144. }
  145. if (pmmioDest && pmmioDest->fRecordToFile && pmmioDest->hmmioDst)
  146. {
  147. // write this buffer to disk
  148. WriteToFile(pmmioDest);
  149. }
  150. }
  151. else
  152. {
  153. DEBUGMSG (ZONE_AP, ("%s: invalid handle\r\n", _fx_));
  154. hr = DPR_INVALID_HANDLE;
  155. goto MyExit;
  156. }
  157. MyExit:
  158. if ((hr == DPR_SUCCESS) || (hr == DPR_CANT_WRITE_WAVE_DEV))
  159. {
  160. _SetState (((uDataType == MP_DATATYPE_SILENCE) || (uDataType == MP_DATATYPE_INTERPOLATED))? MP_STATE_PLAYING_SILENCE : MP_STATE_PLAYING_BACK);
  161. }
  162. return hr;
  163. }
  164. HRESULT AudioPacket::Record ( void )
  165. {
  166. HRESULT hr = DPR_SUCCESS;
  167. MMRESULT mmr;
  168. FX_ENTRY ("AdPckt::Record")
  169. LOG((LOGMSG_RECORD,m_index));
  170. if (_GetState () != MP_STATE_RESET)
  171. {
  172. DEBUGMSG (ZONE_AP, ("%s: out of seq, state=0x%lX\r\n", _fx_, m_dwState));
  173. return DPR_OUT_OF_SEQUENCE;
  174. }
  175. if (m_hDev)
  176. {
  177. if (m_dwState & DP_FLAG_MMSYSTEM)
  178. {
  179. ((WAVEHDR *) m_pDevHdr)->lpData = (char *) m_pDevData->data;
  180. ((WAVEHDR *) m_pDevHdr)->dwBufferLength = m_pDevData->length;
  181. ((WAVEHDR *) m_pDevHdr)->dwUser = (DWORD_PTR) this;
  182. ((WAVEHDR *) m_pDevHdr)->dwFlags |= WHDR_PREPARED;
  183. ((WAVEHDR *) m_pDevHdr)->dwLoops = 0L;
  184. // feed this buffer to record
  185. mmr = waveInAddBuffer ((HWAVEIN)m_hDev, (WAVEHDR *) m_pDevHdr, sizeof (WAVEHDR));
  186. if (mmr != MMSYSERR_NOERROR)
  187. {
  188. DEBUGMSG (ZONE_AP, ("%s: waveInAddBuffer failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  189. hr = DPR_CANT_ADD_BUFFER;
  190. goto MyExit;
  191. }
  192. }
  193. else
  194. {
  195. DEBUGMSG (ZONE_AP, ("%s: invalid platform (mm)\r\n", _fx_));
  196. hr = DPR_INVALID_PLATFORM;
  197. goto MyExit;
  198. }
  199. }
  200. else
  201. {
  202. DEBUGMSG (ZONE_AP, ("%s: invalid handle\r\n", _fx_));
  203. hr = DPR_INVALID_HANDLE;
  204. goto MyExit;
  205. }
  206. MyExit:
  207. if (hr == DPR_SUCCESS) _SetState (MP_STATE_RECORDING);
  208. return hr;
  209. }
  210. BOOL AudioPacket::IsBufferDone ( void )
  211. {
  212. FX_ENTRY ("AdPckt::IsBufferDone")
  213. if (m_hDev)
  214. {
  215. if (m_dwState & DP_FLAG_MMSYSTEM)
  216. {
  217. return (((WAVEHDR *) m_pDevHdr)->dwFlags & WHDR_DONE);
  218. }
  219. }
  220. return FALSE;
  221. }
  222. HRESULT AudioPacket::MakeSilence ( void )
  223. {
  224. // create white noise!!!
  225. FX_ENTRY ("AdPckt::MakeSilence")
  226. if (m_pDevFmt)
  227. {
  228. if (m_pDevData)
  229. {
  230. FillSilenceBuf ((WAVEFORMATEX *) m_pDevFmt, (PBYTE) m_pDevData->data,
  231. (ULONG) m_pDevData->length);
  232. }
  233. #if 0
  234. if (m_pRawData != m_pDevData)
  235. {
  236. if (m_pRawData)
  237. ZeroMemory (m_pRawData->data, m_pRawData->length);
  238. }
  239. if (m_pNetData != m_pRawData)
  240. {
  241. if (m_pNetData)
  242. ZeroMemory (m_pNetData->data, m_pNetData->length);
  243. }
  244. #endif
  245. }
  246. _SetState(MP_STATE_RESET);
  247. return DPR_SUCCESS;
  248. }
  249. /*
  250. Returns the max. peak-to-peak signal value scaled to
  251. the range [0,0xffff]
  252. Optional argument returns the peak value as well
  253. */
  254. HRESULT AudioPacket::GetSignalStrength ( PDWORD pdwMaxStrength)
  255. {
  256. return ComputePower(pdwMaxStrength, NULL);
  257. }
  258. HRESULT AudioPacket::ComputePower(PDWORD pdwMaxStrength, PWORD pwPeakStrength)
  259. {
  260. BYTE bMax, bMin, *pb;
  261. short sMax, sMin, *ps;
  262. UINT cbSize;
  263. FX_ENTRY ("AdPckt::GetSignalStrength")
  264. if (((WAVEFORMATEX *) m_pDevFmt)->wFormatTag != WAVE_FORMAT_PCM) return FALSE;
  265. switch (((WAVEFORMATEX *) m_pDevFmt)->wBitsPerSample)
  266. {
  267. case 8: // unsigned char
  268. pb = (PBYTE) (m_pDevData->data);
  269. cbSize = m_pDevData->length;
  270. bMax = 0;
  271. bMin = 255;
  272. for ( ; cbSize; cbSize--, pb++)
  273. {
  274. if (*pb > bMax) bMax = *pb;
  275. if (*pb < bMin) bMin = *pb;
  276. }
  277. if (pdwMaxStrength)
  278. {
  279. // 2^9 <-- 2^16 / 2^7
  280. *pdwMaxStrength = ((DWORD) (bMax - bMin)) << 8;
  281. }
  282. if (pwPeakStrength)
  283. {
  284. *pwPeakStrength = (bMax > bMin) ? bMax : (WORD)(-bMin);
  285. *pwPeakStrength = (*pwPeakStrength) << 8;
  286. }
  287. break;
  288. case 16: // (signed) short
  289. ps = (short *) (m_pDevData->data);
  290. cbSize = m_pDevData->length;
  291. sMax = sMin = 0;
  292. for (cbSize >>= 1; cbSize; cbSize--, ps++)
  293. {
  294. if (*ps > sMax) sMax = *ps;
  295. if (*ps < sMin) sMin = *ps;
  296. }
  297. if (pdwMaxStrength)
  298. {
  299. *pdwMaxStrength = (DWORD) (sMax - sMin); // drop sign bit
  300. }
  301. if (pwPeakStrength)
  302. {
  303. *pwPeakStrength = ((WORD)(sMax) > (WORD)(-sMin)) ? sMax : (WORD)(-sMin);
  304. }
  305. break;
  306. default:
  307. if (pdwMaxStrength)
  308. *pdwMaxStrength = 0;
  309. if (pwPeakStrength)
  310. *pwPeakStrength = 0;
  311. break;
  312. }
  313. //LOG((LOGMSG_SILENT,m_index,fResult));
  314. return DPR_SUCCESS;
  315. }
  316. HRESULT AudioPacket::Interpolate ( MediaPacket * pPrev, MediaPacket * pNext)
  317. {
  318. HRESULT hr = DPR_SUCCESS;
  319. DPHANDLE hPrevDevAudio;
  320. NETBUF *pPrevDevData;
  321. PVOID pPrevDevHdr;
  322. WAVEFORMATEX *pPrevpwfDevAudio;
  323. WAVEFORMATEX *pNextpwfDevAudio;
  324. NETBUF *pNextDevData;
  325. PVOID pNextDevHdr;
  326. PCMSUB PCMSub;
  327. FX_ENTRY ("AdPckt::Interpolate")
  328. // Make sure this really is an empty packet, that the previous packet is not an
  329. // empty packet and is being played back. It is not that important that we get
  330. // a handle to the next packet. If the next packet is decoded, then it's cool,
  331. // we can do a good job at interpolating between previous and next packet. If it's
  332. // not, well, too bad, we'll just work with the previous packet.
  333. if ((_GetState() != MP_STATE_RESET) || (pPrev->GetState() != MP_STATE_PLAYING_BACK))
  334. {
  335. // DEBUGMSG (ZONE_AP, ("%s: out of seq, state=0x%lX\r\n", _fx_, m_dwState));
  336. hr = DPR_OUT_OF_SEQUENCE;
  337. goto MyExit;
  338. }
  339. // Get pointers to the member variables of interest in the previous and next
  340. // packet. Test the next packet to find out if we can use it in the interpolation
  341. // algorithm.
  342. pPrev->GetProp (MP_PROP_DEV_HANDLE, (PDWORD_PTR)&hPrevDevAudio);
  343. pPrev->GetProp (MP_PROP_DEV_DATA, (PDWORD_PTR)&pPrevDevData);
  344. pPrev->GetProp (MP_PROP_DEV_MEDIA_HDR, (PDWORD_PTR)&pPrevDevHdr);
  345. pPrev->GetProp (MP_PROP_DEV_MEDIA_FORMAT, (PDWORD_PTR)&pPrevpwfDevAudio);
  346. if (hPrevDevAudio && pPrevDevData && pPrevDevHdr && pPrevpwfDevAudio && (pPrevpwfDevAudio->wFormatTag == 1) && (pPrevpwfDevAudio->nSamplesPerSec == 8000) && (pPrevpwfDevAudio->wBitsPerSample == 16))
  347. {
  348. PCMSub.pwWaSuBf = (short *)m_pDevData->data;
  349. PCMSub.dwBfSize = ((WAVEHDR *) pPrevDevHdr)->dwBufferLength >> 1;
  350. PCMSub.dwSaPeSe = (DWORD)pPrevpwfDevAudio->nSamplesPerSec;
  351. PCMSub.dwBiPeSa = (DWORD)pPrevpwfDevAudio->wBitsPerSample;
  352. PCMSub.pwPrBf = (short *)pPrevDevData->data;
  353. pNext->GetProp (MP_PROP_DEV_DATA, (PDWORD_PTR)&pNextDevData);
  354. pNext->GetProp (MP_PROP_DEV_MEDIA_HDR, (PDWORD_PTR)&pNextDevHdr);
  355. pNext->GetProp (MP_PROP_DEV_MEDIA_FORMAT, (PDWORD_PTR)&pNextpwfDevAudio);
  356. // Do a bit of checking
  357. if ((pNext->GetState() == MP_STATE_DECODED) && pNextDevData && pNextDevHdr
  358. && (PCMSub.dwBfSize == (((WAVEHDR *) pNextDevHdr)->dwBufferLength >> 1))
  359. && pNextpwfDevAudio && (pNextpwfDevAudio->wFormatTag == 1) && (pNextpwfDevAudio->nSamplesPerSec == 8000)
  360. && (pNextpwfDevAudio->wBitsPerSample == 16))
  361. {
  362. PCMSub.eTech = techPATT_MATCH_BOTH_SIGN_CC;
  363. //PCMSub.eTech = techDUPLICATE_PREV;
  364. PCMSub.pwNeBf = (short *)pNextDevData->data;
  365. PCMSub.fScal = TRUE;
  366. }
  367. else
  368. {
  369. PCMSub.eTech = techPATT_MATCH_PREV_SIGN_CC;
  370. //PCMSub.eTech = techDUPLICATE_PREV;
  371. PCMSub.pwNeBf = (short *)NULL;
  372. PCMSub.fScal = FALSE;
  373. }
  374. // Do the actual interpolation
  375. hr = PCMSubstitute(&PCMSub);
  376. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLengthUsed = ((WAVEHDR *) pPrevDevHdr)->dwBufferLength;
  377. }
  378. else
  379. {
  380. DEBUGMSG (ZONE_AP, ("%s: can't interpolate\r\n", _fx_));
  381. hr = DPR_INVALID_HANDLE;
  382. goto MyExit;
  383. }
  384. LOG((LOGMSG_INTERPOLATED,m_index));
  385. MyExit:
  386. if (hr == DPR_SUCCESS)
  387. _SetState (MP_STATE_DECODED);
  388. else
  389. _SetState (MP_STATE_RESET);
  390. return hr;
  391. }
  392. HRESULT AudioPacket::Open ( UINT uType, DPHANDLE hdl )
  393. // called by RxStream or TxStream
  394. {
  395. HRESULT hr = DPR_SUCCESS;
  396. MMRESULT mmr;
  397. FX_ENTRY ("AdPckt::Open")
  398. switch (uType)
  399. {
  400. #ifdef PREP_HDR_PER_CONV
  401. case MP_TYPE_RECVSTRMCONV:
  402. m_hStrmConv = hdl;
  403. break;
  404. #endif
  405. case MP_TYPE_STREAMCONV:
  406. if ((m_hStrmConv = hdl) != NULL)
  407. {
  408. if (m_dwState & DP_FLAG_ACM)
  409. {
  410. // initialize the header
  411. ZeroMemory (m_pStrmConvHdr, sizeof (ACMSTREAMHEADER));
  412. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbStruct = sizeof (ACMSTREAMHEADER);
  413. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->fdwStatus = 0;
  414. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->dwUser = 0;
  415. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->dwSrcUser = 0;
  416. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLengthUsed = 0;
  417. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->dwDstUser = 0;
  418. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLengthUsed = 0;
  419. if (m_dwState & DP_FLAG_SEND)
  420. {
  421. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pRawData->data;
  422. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pRawData->length;
  423. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->pbDst = m_pNetData->data;
  424. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLength = m_pNetData->length;
  425. }
  426. else
  427. if (m_dwState & DP_FLAG_RECV)
  428. {
  429. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pNetData->data;
  430. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pNetData->length;
  431. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->pbDst = m_pRawData->data;
  432. ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLength = m_pRawData->length;
  433. }
  434. // prepare the header
  435. mmr = acmStreamPrepareHeader ((HACMSTREAM) m_hStrmConv,
  436. (ACMSTREAMHEADER *) m_pStrmConvHdr, 0);
  437. if (mmr != MMSYSERR_NOERROR)
  438. {
  439. DEBUGMSG (ZONE_AP, ("%s: acmStreamPrepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  440. hr = DPR_CANT_PREPARE_HEADER;
  441. goto MyExit;
  442. }
  443. m_fStrmPrepared = TRUE;
  444. }
  445. else
  446. {
  447. hr = DPR_INVALID_PLATFORM;
  448. goto MyExit;
  449. }
  450. }
  451. break;
  452. case MP_TYPE_DEV:
  453. if ((m_hDev = hdl) != NULL)
  454. {
  455. if (m_dwState & DP_FLAG_MMSYSTEM)
  456. {
  457. // initialize the header
  458. ZeroMemory (m_pDevHdr, sizeof (WAVEHDR));
  459. ((WAVEHDR *) m_pDevHdr)->lpData = (char *) m_pDevData->data;
  460. ((WAVEHDR *) m_pDevHdr)->dwBufferLength = m_pDevData->length;
  461. ((WAVEHDR *) m_pDevHdr)->dwUser = (DWORD_PTR) this;
  462. ((WAVEHDR *) m_pDevHdr)->dwFlags = 0L;
  463. ((WAVEHDR *) m_pDevHdr)->dwLoops = 0L;
  464. if (m_dwState & DP_FLAG_SEND)
  465. {
  466. g_wavein_prepare++;
  467. // prepare the header
  468. mmr = waveInPrepareHeader ((HWAVEIN) m_hDev, (WAVEHDR *) m_pDevHdr, sizeof (WAVEHDR));
  469. if (mmr != MMSYSERR_NOERROR)
  470. {
  471. DEBUGMSG (ZONE_AP, ("%s: waveInPrepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  472. hr = DPR_CANT_PREPARE_HEADER;
  473. goto MyExit;
  474. }
  475. }
  476. else
  477. if (m_dwState & DP_FLAG_RECV)
  478. {
  479. g_waveout_prepare++;
  480. // prepare header
  481. mmr = waveOutPrepareHeader ((HWAVEOUT) m_hDev, (WAVEHDR *) m_pDevHdr, sizeof (WAVEHDR));
  482. if (mmr != MMSYSERR_NOERROR)
  483. {
  484. DEBUGMSG (ZONE_AP, ("%s: waveOutPrepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  485. hr = DPR_CANT_PREPARE_HEADER;
  486. goto MyExit;
  487. }
  488. }
  489. else
  490. {
  491. hr = DPR_INVALID_PARAMETER;
  492. goto MyExit;
  493. }
  494. m_fDevPrepared = TRUE;
  495. }
  496. else
  497. {
  498. hr = DPR_INVALID_PLATFORM;
  499. goto MyExit;
  500. }
  501. }
  502. else
  503. {
  504. hr = DPR_INVALID_HANDLE;
  505. goto MyExit;
  506. }
  507. break;
  508. default:
  509. hr = DPR_INVALID_PARAMETER;
  510. goto MyExit;
  511. }
  512. MyExit:
  513. return hr;
  514. }
  515. HRESULT AudioPacket::Close ( UINT uType )
  516. // called by RxStream or TxStream
  517. {
  518. HRESULT hr = DPR_SUCCESS;
  519. MMRESULT mmr;
  520. FX_ENTRY ("AdPckt::Close")
  521. switch (uType)
  522. {
  523. #ifdef PREP_HDR_PER_CONV
  524. case MP_TYPE_RECVSTRMCONV:
  525. #endif
  526. case MP_TYPE_STREAMCONV:
  527. if (m_hStrmConv)
  528. {
  529. if (m_dwState & DP_FLAG_ACM)
  530. {
  531. if (m_fStrmPrepared)
  532. {
  533. // unprepare the header
  534. if (m_dwState & DP_FLAG_RECV)
  535. {
  536. // Within acmStreamUnprepareHeader, there is a test that compares ((ACMSTREAMHEADER *)m_pStrmConvHdr)->cbSrcLength
  537. // to ((ACMSTREAMHEADER *)m_pStrmConvHdr)->cbPreparedSrcLength. If there isn't an exact match, MSACM32 will fail
  538. // this call. That test is Ok when the size of the input buffer is constant, but with the variable bit rate codecs,
  539. // we can receive packets with a size smaller than the max size we advertize when we prepare the buffers. In
  540. // order to make this call succeed, we fix up ((ACMSTREAMHEADER *)m_pStrmConvHdr)->cbSrcLength before the call.
  541. ((ACMSTREAMHEADER *)m_pStrmConvHdr)->cbSrcLength = ((ACMSTREAMHEADER *)m_pStrmConvHdr)->dwReservedDriver[7];
  542. }
  543. mmr = acmStreamUnprepareHeader ((HACMSTREAM) m_hStrmConv,
  544. (ACMSTREAMHEADER *) m_pStrmConvHdr, 0);
  545. m_fStrmPrepared = FALSE; // don't care about any error
  546. if (mmr != MMSYSERR_NOERROR)
  547. {
  548. DEBUGMSG (ZONE_AP, ("%s: acmStreamUnprepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr));
  549. hr = DPR_CANT_UNPREPARE_HEADER;
  550. goto MyExit;
  551. }
  552. }
  553. }
  554. if (uType == MP_TYPE_STREAMCONV) m_hStrmConv = NULL;
  555. }
  556. break;
  557. case MP_TYPE_DEV:
  558. if (m_hDev)
  559. {
  560. if (m_fDevPrepared)
  561. {
  562. if (m_dwState & DP_FLAG_SEND)
  563. {
  564. g_wavein_prepare--;
  565. mmr = waveInUnprepareHeader ((HWAVEIN) m_hDev,
  566. (WAVEHDR *) m_pDevHdr,
  567. sizeof (WAVEHDR));
  568. }
  569. else
  570. if (m_dwState & DP_FLAG_RECV)
  571. {
  572. g_waveout_prepare--;
  573. mmr = waveOutUnprepareHeader ((HWAVEOUT) m_hDev,
  574. (WAVEHDR *) m_pDevHdr,
  575. sizeof (WAVEHDR));
  576. }
  577. else
  578. {
  579. hr = DPR_INVALID_PARAMETER;
  580. goto MyExit;
  581. }
  582. m_fDevPrepared = FALSE; // don't care about any error
  583. if (mmr != MMSYSERR_NOERROR)
  584. {
  585. DEBUGMSG (ZONE_AP, ("%s: Unprep hdr failed, mmr=0x%lX\r\n", _fx_, mmr));
  586. hr = DPR_CANT_UNPREPARE_HEADER;
  587. goto MyExit;
  588. }
  589. }
  590. m_hDev = NULL;
  591. }
  592. else
  593. {
  594. hr = DPR_INVALID_HANDLE;
  595. goto MyExit;
  596. }
  597. break;
  598. default:
  599. hr = DPR_INVALID_PARAMETER;
  600. goto MyExit;
  601. }
  602. MyExit:
  603. return hr;
  604. }
  605. void AudioPacket::WriteToFile (MMIODEST *pmmioDest)
  606. {
  607. MMRESULT mmr;
  608. long dwDataLength;
  609. FX_ENTRY ("AdPckt::WriteToFile")
  610. AudioFile::WriteDestFile(pmmioDest, m_pDevData->data, m_pDevData->length);
  611. }
  612. void AudioPacket::ReadFromFile (MMIOSRC *pmmioSrc)
  613. {
  614. AudioFile::ReadSourceFile(pmmioSrc, (BYTE*)(((WAVEHDR*)m_pDevHdr)->lpData), ((WAVEHDR*)m_pDevHdr)->dwBytesRecorded);
  615. }
  616. BOOL AudioPacket::IsSameMediaFormat(PVOID fmt1,PVOID fmt2)
  617. {
  618. return IsSameWaveFormat(fmt1,fmt2);
  619. }
  620. /*************************************************************************
  621. Function: PCMSubstitute(PCMSUB *)
  622. Purpose : Fills up missing buffer with wave data.
  623. Returns : HRESULT. DPR_SUCCESS if everything is cool, some error code
  624. otherwise.
  625. Params : pPCMSub == Pointer to wave substitution structure
  626. Techniques: * Straight replication of the previous packet
  627. * Straight replication of the next packet
  628. * Replication of some part of the previous packet based on pattern matching
  629. * Replication of some part of the next packet based on pattern matching
  630. * Search window size need to be at least twice the size of the pattern!!!
  631. Comments: * The algorithm searches previous packets to find pPCMSub->dwBfSize
  632. samples that resemble the missing packet. To do so it uses as a
  633. template the M speech samples that came just before
  634. the missing packet. The algorithm scans a search window of
  635. duration N samples to find the M samples that best match the
  636. template. It then uses as a replacement packet the L samples
  637. that follow the best match.
  638. * Current code assumes all the packets (current, previous, and
  639. next) have the same size.
  640. * Current code only takes 8kHz data.
  641. * Current code only takes 16bit data.
  642. * Current code requires that the matching pattern be smaller than packet.
  643. History : Date Reason
  644. 04/16/95 Created - PhilF
  645. *************************************************************************/
  646. HRESULT AudioPacket::PCMSubstitute(PCMSUB *pPCMSub)
  647. {
  648. DWORD dwPaSize; // Pattern size in samples
  649. DWORD dwSeWiSize; // Search window size in samples
  650. short *pwPa = (short *)NULL; // Pointer to the pattern
  651. short *pwPaSav = (short *)NULL; // Pointer to the pattern (copy)
  652. short *pwPrSeWi = (short *)NULL; // Pointer to the previous buffer (search window)
  653. short *pwPrSeWiSav = (short *)NULL; // Pointer to the previous buffer (search window) (copy)
  654. short *pwNeSeWi = (short *)NULL; // Pointer to the next buffer (search window)
  655. short *pwNeSeWiSav = (short *)NULL; // Pointer to the next buffer (search window) (copy)
  656. DWORD i, j; // Counters
  657. DWORD dwPrCCPosMax; // Sample position of the maximum cross-correlation between pattern and previous buffer
  658. DWORD dwNeCCPosMax; // Sample position of the maximum cross-correlation between pattern and previous buffer
  659. long lPrCCMax; // Max cross-correlation with previous buffer
  660. long lNeCCMax; // Max cross-correlation with next buffer
  661. long lCCNum; // Cross-correlation numerator
  662. DWORD dwNuSaToCopy; // Number of samples to copy in the missing buffer
  663. DWORD dwNuSaCopied; // Number of samples copied in the missing buffer
  664. long alSign[2] = {1,-1}; // Sign array
  665. DWORD dwPaAmp; // Amplitude of the pattern
  666. DWORD dwPaAmpExp; // Expected amplitude of the pattern
  667. DWORD dwNeSeWiAmp; // Amplitude of a segment of the window following the current window
  668. DWORD dwNumPaInSeWin; // Number of patterns in search window
  669. DWORD dwPrSeWiAmp; // Amplitude of a segment of the current window
  670. BOOL fPaInPr; // Pattern is at the end of previous buffer of at the beginning of next buffer
  671. // Test input parameters
  672. if ((!pPCMSub) || (!pPCMSub->pwWaSuBf) || (pPCMSub->dwBiPeSa != 16) || (pPCMSub->dwSaPeSe != 8000))
  673. return DPR_INVALID_PARAMETER;
  674. // Check number of buffer available before and after missing packet
  675. // In case there are no packet before or after the missing packet,
  676. // just return; the packet will be filled with silence data later.
  677. if (!pPCMSub->pwPrBf && !pPCMSub->pwNeBf)
  678. return DPR_CANT_INTERPOLATE;
  679. // Just replicate previous packet
  680. if ((pPCMSub->eTech == techDUPLICATE_PREV) && pPCMSub->pwPrBf)
  681. CopyMemory(pPCMSub->pwWaSuBf, pPCMSub->pwPrBf, pPCMSub->dwBfSize << 1);
  682. else // Just replicate next packet
  683. if ((pPCMSub->eTech == techDUPLICATE_NEXT) && pPCMSub->pwNeBf)
  684. CopyMemory(pPCMSub->pwWaSuBf, pPCMSub->pwNeBf, pPCMSub->dwBfSize << 1);
  685. else
  686. if ((pPCMSub->eTech == techPATT_MATCH_PREV_SIGN_CC) || (pPCMSub->eTech == techPATT_MATCH_NEXT_SIGN_CC) || (pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC))
  687. {
  688. // We use a search window with a size double the size of the matching pattern
  689. // Experimentation will tell if this is a reasonable size or not
  690. // Experimentation will also tell if 4ms size of the matching pattern is Ok
  691. dwPaSize = pPCMSub->dwSaPeSe / 1000 * PATTERN_SIZE;
  692. if (dwPaSize > (pPCMSub->dwBfSize/2))
  693. dwPaSize = pPCMSub->dwBfSize/2;
  694. if (!dwPaSize)
  695. return DPR_CANT_INTERPOLATE;
  696. #if 1
  697. // For now look up the whole previous frame
  698. dwSeWiSize = pPCMSub->dwBfSize;
  699. #else
  700. dwSeWiSize = min(pPCMSub->dwBfSize, pPCMSub->dwSaPeSe / 1000 * SEARCH_SIZE);
  701. #endif
  702. // In order to use pattern matching based techniques we need to have the
  703. // previous buffer when doing a backward search, the next buffer
  704. // when doing a forward search, the previous buffer and the next buffer
  705. // when doing a full search
  706. if (pPCMSub->pwPrBf && (pPCMSub->eTech == techPATT_MATCH_PREV_SIGN_CC))
  707. {
  708. pwPa = pwPaSav = pPCMSub->pwPrBf + pPCMSub->dwBfSize - dwPaSize;
  709. pwPrSeWi = pwPrSeWiSav = pPCMSub->pwPrBf + pPCMSub->dwBfSize - dwSeWiSize;
  710. }
  711. else
  712. if (pPCMSub->pwNeBf && (pPCMSub->eTech == techPATT_MATCH_NEXT_SIGN_CC))
  713. {
  714. pwPa = pwPaSav = pPCMSub->pwNeBf;
  715. pwNeSeWi = pwNeSeWiSav = pPCMSub->pwNeBf;
  716. }
  717. else
  718. if (pPCMSub->pwPrBf && pPCMSub->pwNeBf && (pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC))
  719. {
  720. // Use the pattern with the highest amplitude
  721. pwPa = pwPaSav = pPCMSub->pwPrBf + pPCMSub->dwBfSize - dwPaSize;
  722. pwNeSeWi = pPCMSub->pwNeBf;
  723. pwPrSeWi = pwPrSeWiSav = pPCMSub->pwPrBf + pPCMSub->dwBfSize - dwSeWiSize;
  724. fPaInPr = TRUE;
  725. for (i=0, dwPaAmp = 0, dwNeSeWiAmp = 0; i<dwPaSize; i++, pwPa++, pwNeSeWi++)
  726. {
  727. dwPaAmp += abs(*pwPa);
  728. dwNeSeWiAmp += abs(*pwNeSeWi);
  729. }
  730. if (dwNeSeWiAmp > dwPaAmp)
  731. {
  732. pwPaSav = pPCMSub->pwNeBf;
  733. fPaInPr = FALSE;
  734. }
  735. pwPa = pwPaSav;
  736. pwNeSeWi = pwNeSeWiSav = pPCMSub->pwNeBf + dwPaSize/2;
  737. }
  738. if (pwPa && (pwPrSeWi || pwNeSeWi))
  739. {
  740. // Look for best match in previous packet
  741. dwPrCCPosMax = 0; lPrCCMax = -((long)dwPaSize+1);
  742. if (pwPrSeWi && ((pPCMSub->eTech == techPATT_MATCH_PREV_SIGN_CC) || ((fPaInPr) && (pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC))))
  743. {
  744. // Look for the highest sign correlation between pattern and search window
  745. for (i=0; i<(dwSeWiSize-dwPaSize-dwPaSize/2+1); i++, pwPa = pwPaSav, pwPrSeWi = pwPrSeWiSav + i)
  746. {
  747. // Compute the sign correlation between pattern, and search window
  748. for (j=0, lCCNum = 0; j<dwPaSize; j++, pwPa++, pwPrSeWi++)
  749. lCCNum += alSign[(*pwPa ^ *pwPrSeWi)>> 15 & 1];
  750. // Save position and value of highest sign correlation
  751. if (lCCNum>lPrCCMax)
  752. {
  753. dwPrCCPosMax = i;
  754. lPrCCMax = lCCNum;
  755. }
  756. }
  757. }
  758. // Look for best match in next packet
  759. dwNeCCPosMax = dwPaSize/2; lNeCCMax = -((long)dwPaSize+1);
  760. if (pwNeSeWi && ((pPCMSub->eTech == techPATT_MATCH_NEXT_SIGN_CC) || ((!fPaInPr) && (pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC))))
  761. {
  762. // Look for the highest sign correlation between pattern and search window
  763. for (i=dwPaSize/2; i<(dwSeWiSize-dwPaSize-dwPaSize/2+1); i++, pwPa = pwPaSav, pwNeSeWi = pwNeSeWiSav + i)
  764. {
  765. // Compute the sign correlation between pattern, and search window
  766. for (j=0, lCCNum = 0; j<dwPaSize; j++, pwPa++, pwNeSeWi++)
  767. lCCNum += alSign[(*pwPa ^ *pwNeSeWi)>> 15 & 1];
  768. // Save position and value of highest sign correlation
  769. if (lCCNum>lNeCCMax)
  770. {
  771. dwNeCCPosMax = i;
  772. lNeCCMax = lCCNum;
  773. }
  774. }
  775. }
  776. if ((pPCMSub->eTech == techPATT_MATCH_PREV_SIGN_CC) || (pwPrSeWiSav && fPaInPr && (pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC)))
  777. {
  778. // Copy matching samples from the previous frame in missing frame
  779. dwNuSaToCopy = pPCMSub->dwBfSize-dwPaSize-dwPrCCPosMax;
  780. CopyMemory(pPCMSub->pwWaSuBf, pwPrSeWiSav+dwPaSize+dwPrCCPosMax, dwNuSaToCopy << 1);
  781. // Do it until missing packet is full
  782. for (dwNuSaCopied = dwNuSaToCopy; dwNuSaCopied<pPCMSub->dwBfSize;dwNuSaCopied += dwNuSaToCopy)
  783. {
  784. dwNuSaToCopy = min(pPCMSub->dwBfSize-dwNuSaCopied, dwNuSaToCopy);
  785. CopyMemory(pPCMSub->pwWaSuBf + dwNuSaCopied, pwPrSeWiSav+dwPaSize+dwPrCCPosMax, dwNuSaToCopy << 1);
  786. }
  787. }
  788. else
  789. {
  790. // Copy matching samples from the next frame in missing frame
  791. dwNuSaToCopy = dwNeCCPosMax;
  792. CopyMemory(pPCMSub->pwWaSuBf + pPCMSub->dwBfSize - dwNuSaToCopy, pPCMSub->pwNeBf, dwNuSaToCopy << 1);
  793. // Do it until missing packet is full
  794. for (dwNuSaCopied = dwNuSaToCopy; dwNuSaCopied<pPCMSub->dwBfSize;dwNuSaCopied += dwNuSaToCopy)
  795. {
  796. dwNuSaToCopy = min(pPCMSub->dwBfSize-dwNuSaCopied, dwNuSaToCopy);
  797. CopyMemory(pPCMSub->pwWaSuBf + pPCMSub->dwBfSize - dwNuSaCopied - dwNuSaToCopy, pPCMSub->pwNeBf+dwNeCCPosMax-dwNuSaToCopy, dwNuSaToCopy << 1);
  798. }
  799. }
  800. if ((pPCMSub->eTech == techPATT_MATCH_BOTH_SIGN_CC) && pwNeSeWiSav && pwPrSeWiSav)
  801. {
  802. if (pPCMSub->fScal)
  803. {
  804. // Compute the amplitude of the pattern
  805. for (i=0, dwPrSeWiAmp = 0, dwNeSeWiAmp = 0, pwPrSeWi = pPCMSub->pwPrBf + pPCMSub->dwBfSize - dwPaSize, pwNeSeWi = pPCMSub->pwNeBf; i<dwPaSize; i++, pwPrSeWi++, pwNeSeWi++)
  806. {
  807. dwPrSeWiAmp += abs(*pwPrSeWi);
  808. dwNeSeWiAmp += abs(*pwNeSeWi);
  809. }
  810. // Scale data
  811. dwNumPaInSeWin = pPCMSub->dwBfSize/dwPaSize;
  812. for (i=0, pwPaSav = pPCMSub->pwWaSuBf; i<dwNumPaInSeWin; i++, pwPaSav += dwPaSize)
  813. {
  814. for (j=0, pwPa = pwPaSav, dwPaAmp = 0; j<dwPaSize; j++, pwPa++)
  815. dwPaAmp += abs(*pwPa);
  816. dwPaAmpExp = (dwPrSeWiAmp * (dwNumPaInSeWin - i) + dwNeSeWiAmp * (i + 1)) / (dwNumPaInSeWin + 1);
  817. for (;dwPaAmpExp > 65536; dwPaAmpExp >>= 1, dwPaAmp >>= 1)
  818. ;
  819. if (dwPaAmp && (dwPaAmp != dwPaAmpExp))
  820. for (j=0, pwPa = pwPaSav; j<dwPaSize; j++, pwPa++)
  821. *pwPa = (short)((long)*pwPa * (long)dwPaAmpExp / (long)dwPaAmp);
  822. }
  823. }
  824. }
  825. }
  826. }
  827. else
  828. return DPR_CANT_INTERPOLATE;
  829. return DPR_SUCCESS;
  830. }
  831. // returns length of uncompressed PCM data in buffer
  832. DWORD
  833. AudioPacket::GetDevDataSamples()
  834. {
  835. DWORD dwState = _GetState();
  836. DWORD cbData;
  837. if (dwState == MP_STATE_DECODED)
  838. // return actual length
  839. cbData = ((ACMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLengthUsed ;
  840. else if (m_pDevData)
  841. // return size of buffer
  842. cbData = m_pDevData->length;
  843. else
  844. cbData = 0;
  845. return cbData * 8/ ((WAVEFORMATEX *) m_pDevFmt)->wBitsPerSample;
  846. }
  847.