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.

2635 lines
90 KiB

  1. //==========================================================================
  2. //
  3. // lhacm.c
  4. //
  5. // Description:
  6. // This file contains the DriverProc and other routines which respond
  7. // to ACM messages.
  8. //
  9. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  10. //
  11. //==========================================================================
  12. #ifndef STRICT
  13. #define STRICT
  14. #endif
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <mmsystem.h>
  18. #include "mmddk.h"
  19. #include <ctype.h>
  20. #include <mmreg.h>
  21. #include <msacm.h>
  22. #include "msacmdrv.h"
  23. #include "fv_x8.h"
  24. #include "lhacm.h"
  25. #define NEW_ANSWER 1
  26. #include "resource.h"
  27. enum
  28. {
  29. #ifdef CELP4800
  30. IDX_LH_CELP,
  31. #endif
  32. IDX_LH_SB8,
  33. IDX_LH_SB12,
  34. IDX_LH_SB16,
  35. IDX_PCM,
  36. NumOfTagIndices
  37. };
  38. const UINT gauFormatTagIndexToTag[NumOfTagIndices] =
  39. {
  40. #ifdef CELP4800
  41. WAVE_FORMAT_LH_CELP,
  42. #endif
  43. WAVE_FORMAT_LH_SB8,
  44. WAVE_FORMAT_LH_SB12,
  45. WAVE_FORMAT_LH_SB16,
  46. WAVE_FORMAT_PCM
  47. };
  48. const UINT gauTagNameIds[NumOfTagIndices] =
  49. {
  50. #ifdef CELP4800
  51. IDS_CODEC_NAME_CELP,
  52. #endif
  53. IDS_CODEC_NAME_SB8,
  54. IDS_CODEC_NAME_SB12,
  55. IDS_CODEC_NAME_SB16,
  56. 0
  57. };
  58. #define ACM_DRIVER_MAX_FORMAT_TAGS SIZEOF_ARRAY(gauFormatTagIndexToTag)
  59. #define ACM_DRIVER_MAX_FILTER_TAGS 0
  60. // arrays of sample rates supported.
  61. // L&H codecs don't do sample rate conversion.
  62. UINT gauPCMFormatIndexToSampleRate[] =
  63. {
  64. LH_PCM_SAMPLESPERSEC
  65. };
  66. #ifdef CELP4800
  67. UINT gauLHCELPFormatIndexToSampleRate[] =
  68. {
  69. LH_CELP_SAMPLESPERSEC
  70. };
  71. #endif
  72. UINT gauLHSB8FormatIndexToSampleRate[] =
  73. {
  74. LH_SB8_SAMPLESPERSEC
  75. };
  76. UINT gauLHSB12FormatIndexToSampleRate[] =
  77. {
  78. LH_SB12_SAMPLESPERSEC
  79. };
  80. UINT gauLHSB16FormatIndexToSampleRate[] =
  81. {
  82. LH_SB16_SAMPLESPERSEC
  83. };
  84. #define ACM_DRIVER_MAX_PCM_SAMPLE_RATES SIZEOF_ARRAY(gauPCMFormatIndexToSampleRate)
  85. #ifdef CELP4800
  86. #define ACM_DRIVER_MAX_LH_CELP_SAMPLE_RATES SIZEOF_ARRAY(gauLHCELPFormatIndexToSampleRate)
  87. #endif
  88. #define ACM_DRIVER_MAX_LH_SB8_SAMPLE_RATES SIZEOF_ARRAY(gauLHSB8FormatIndexToSampleRate)
  89. #define ACM_DRIVER_MAX_LH_SB12_SAMPLE_RATES SIZEOF_ARRAY(gauLHSB12FormatIndexToSampleRate)
  90. #define ACM_DRIVER_MAX_LH_SB16_SAMPLE_RATES SIZEOF_ARRAY(gauLHSB16FormatIndexToSampleRate)
  91. #define ACM_DRIVER_MAX_CHANNELS 1
  92. // array of bits per sample supported.
  93. // the current version of the LH codecs require 16 bit
  94. UINT gauPCMFormatIndexToBitsPerSample[] =
  95. {
  96. LH_PCM_BITSPERSAMPLE
  97. };
  98. #ifdef CELP4800
  99. UINT gauLHCELPFormatIndexToBitsPerSample[] =
  100. {
  101. LH_CELP_BITSPERSAMPLE
  102. };
  103. #endif
  104. UINT gauLHSB8FormatIndexToBitsPerSample[] =
  105. {
  106. LH_SB8_BITSPERSAMPLE
  107. };
  108. UINT gauLHSB12FormatIndexToBitsPerSample[] =
  109. {
  110. LH_SB12_BITSPERSAMPLE
  111. };
  112. UINT gauLHSB16FormatIndexToBitsPerSample[] =
  113. {
  114. LH_SB16_BITSPERSAMPLE
  115. };
  116. #define ACM_DRIVER_MAX_BITSPERSAMPLE_PCM SIZEOF_ARRAY(gauPCMFormatIndexToBitsPerSample)
  117. #ifdef CELP4800
  118. #define ACM_DRIVER_MAX_BITSPERSAMPLE_LH_CELP SIZEOF_ARRAY(gauLHCELPFormatIndexToBitsPerSample)
  119. #endif
  120. #define ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB8 SIZEOF_ARRAY(gauLHSB8FormatIndexToBitsPerSample)
  121. #define ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB12 SIZEOF_ARRAY(gauLHSB12FormatIndexToBitsPerSample)
  122. #define ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB16 SIZEOF_ARRAY(gauLHSB16FormatIndexToBitsPerSample)
  123. // number of formats we enumerate per format tag is number of sample rates
  124. // times number of channels times number of types (bits per sample).
  125. #define ACM_DRIVER_MAX_FORMATS_PCM \
  126. (ACM_DRIVER_MAX_PCM_SAMPLE_RATES * \
  127. ACM_DRIVER_MAX_CHANNELS * \
  128. ACM_DRIVER_MAX_BITSPERSAMPLE_PCM)
  129. #ifdef CELP4800
  130. #define ACM_DRIVER_MAX_FORMATS_LH_CELP \
  131. (ACM_DRIVER_MAX_LH_CELP_SAMPLE_RATES * \
  132. ACM_DRIVER_MAX_CHANNELS * \
  133. ACM_DRIVER_MAX_BITSPERSAMPLE_LH_CELP)
  134. #endif
  135. #define ACM_DRIVER_MAX_FORMATS_LH_SB8 \
  136. (ACM_DRIVER_MAX_LH_SB8_SAMPLE_RATES * \
  137. ACM_DRIVER_MAX_CHANNELS * \
  138. ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB8)
  139. #define ACM_DRIVER_MAX_FORMATS_LH_SB12 \
  140. (ACM_DRIVER_MAX_LH_SB12_SAMPLE_RATES * \
  141. ACM_DRIVER_MAX_CHANNELS * \
  142. ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB12)
  143. #define ACM_DRIVER_MAX_FORMATS_LH_SB16 \
  144. (ACM_DRIVER_MAX_LH_SB16_SAMPLE_RATES * \
  145. ACM_DRIVER_MAX_CHANNELS * \
  146. ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB16)
  147. //////////////////////////////////////////////////////////
  148. //
  149. // lonchanc: special shorthand for L&H codecs
  150. //
  151. static DWORD _GetAvgBytesPerSec ( PCODECINFO pCodecInfo )
  152. {
  153. return ((pCodecInfo->dwSampleRate * (DWORD) pCodecInfo->wCodedBufferSize)
  154. /
  155. ((DWORD) pCodecInfo->wPCMBufferSize / (DWORD) (pCodecInfo->wBitsPerSamplePCM >> 3)));
  156. }
  157. static PCODECINFO _GetCodecInfoFromFormatIdx ( PINSTANCEDATA pid, int idx )
  158. {
  159. PCODECINFO pCodecInfo = NULL;
  160. switch (gauFormatTagIndexToTag[idx])
  161. {
  162. #ifdef CELP4800
  163. case WAVE_FORMAT_LH_CELP: pCodecInfo = &(pid->CELP.CodecInfo); break;
  164. #endif
  165. case WAVE_FORMAT_LH_SB8: pCodecInfo = &(pid->SB8.CodecInfo); break;
  166. case WAVE_FORMAT_LH_SB12: pCodecInfo = &(pid->SB12.CodecInfo); break;
  167. case WAVE_FORMAT_LH_SB16: pCodecInfo = &(pid->SB16.CodecInfo); break;
  168. default: break;
  169. }
  170. return pCodecInfo;
  171. }
  172. //--------------------------------------------------------------------------;
  173. //
  174. // int LoadStringCodec
  175. //
  176. // Description:
  177. // This function should be used by all codecs to load resource strings
  178. // which will be passed back to the ACM.
  179. //
  180. // The 32-bit ACM always expects Unicode strings. Therefore,
  181. // when UNICODE is defined, this function is compiled to
  182. // LoadStringW to load a Unicode string. When UNICODE is
  183. // not defined, this function loads an ANSI string, converts
  184. // it to Unicode, and returns the Unicode string to the
  185. // codec.
  186. //
  187. // Note that you may use LoadString for other strings (strings which
  188. // will not be passed back to the ACM), because these strings will
  189. // always be consistent with the definition of UNICODE.
  190. //
  191. // Arguments:
  192. // Same as LoadString, except that it expects an LPSTR for Win16 and a
  193. // LPWSTR for Win32.
  194. //
  195. // Return (int):
  196. // Same as LoadString.
  197. //
  198. //--------------------------------------------------------------------------;
  199. #ifdef UNICODE
  200. #define LoadStringCodec LoadStringW
  201. #else
  202. int LoadStringCodec ( HINSTANCE hInst, UINT uID, LPWSTR lpwstr, int cch )
  203. {
  204. LPSTR lpstr;
  205. int iReturn;
  206. lpstr = (LPSTR) LocalAlloc (LPTR, cch);
  207. if (NULL == lpstr)
  208. {
  209. return 0;
  210. }
  211. iReturn = LoadStringA (hInst, uID, lpstr, cch);
  212. if (0 == iReturn)
  213. {
  214. if (0 != cch)
  215. {
  216. lpwstr[0] = '\0';
  217. }
  218. }
  219. else
  220. {
  221. MultiByteToWideChar (GetACP(), 0, lpstr, cch, lpwstr, cch);
  222. }
  223. LocalFree ((HLOCAL) lpstr);
  224. return iReturn;
  225. }
  226. #endif // UNICODE
  227. //--------------------------------------------------------------------------;
  228. //
  229. // BOOL pcmIsValidFormat
  230. //
  231. // Description:
  232. // This function verifies that a wave format header is a valid PCM
  233. // header that _this_ ACM driver can deal with.
  234. //
  235. // Arguments:
  236. // LPWAVEFORMATEX pwfx: Pointer to format header to verify.
  237. //
  238. // Return (BOOL):
  239. // The return value is non-zero if the format header looks valid. A
  240. // zero return means the header is not valid.
  241. //
  242. //--------------------------------------------------------------------------;
  243. BOOL pcmIsValidFormat( LPWAVEFORMATEX pwfx )
  244. {
  245. BOOL fReturn = FALSE;
  246. FUNCTION_ENTRY ("pcmIsValidFormat")
  247. if (NULL == pwfx)
  248. {
  249. DBGMSG (1, (_T ("%s: pwfx is null\r\n"), SZFN));
  250. goto MyExit;
  251. }
  252. if (WAVE_FORMAT_PCM != pwfx->wFormatTag)
  253. {
  254. DBGMSG (1, (_T ("%s: bad wFormatTag=%d\r\n"), SZFN, (UINT) pwfx->wFormatTag));
  255. goto MyExit;
  256. }
  257. //
  258. // verify nChannels member is within the allowed range
  259. //
  260. if ((pwfx->nChannels < 1) || (pwfx->nChannels > ACM_DRIVER_MAX_CHANNELS))
  261. {
  262. DBGMSG (1, (_T ("%s: bad nChannels=%d\r\n"), SZFN, (UINT) pwfx->nChannels));
  263. goto MyExit;
  264. }
  265. //
  266. // only allow the bits per sample that we can encode and decode with
  267. //
  268. if (pwfx->wBitsPerSample != LH_PCM_BITSPERSAMPLE)
  269. {
  270. DBGMSG (1, (_T ("%s: bad wBitsPerSample=%d\r\n"), SZFN, (UINT) pwfx->wBitsPerSample));
  271. goto MyExit;
  272. }
  273. // lonchanc: BUG BUG do we really care about the alignment???
  274. //
  275. // now verify that the block alignment is correct..
  276. //
  277. if (PCM_BLOCKALIGNMENT (pwfx) != pwfx->nBlockAlign)
  278. {
  279. DBGMSG (1, (_T ("%s: bad nBlockAlign=%d\r\n"), SZFN, (UINT) pwfx->nBlockAlign));
  280. goto MyExit;
  281. }
  282. // lonchanc: BUG BUG this only check the integrity of the wave format struct
  283. // but does not ensure that this is a good PCM for us.
  284. //
  285. // finally, verify that avg bytes per second is correct
  286. //
  287. if (PCM_AVGBYTESPERSEC (pwfx) != pwfx->nAvgBytesPerSec)
  288. {
  289. DBGMSG (1, (_T ("%s: bad nAvgBytesPerSec=%d\r\n"), SZFN, (UINT) pwfx->nAvgBytesPerSec));
  290. goto MyExit;
  291. }
  292. fReturn = TRUE;
  293. MyExit:
  294. DBGMSG (1, (_T ("%s: fReturn=%d\r\n"), SZFN, (UINT) fReturn));
  295. return fReturn;
  296. } // pcmIsValidFormat()
  297. //--------------------------------------------------------------------------;
  298. //
  299. // BOOL lhacmIsValidFormat
  300. //
  301. // Description:
  302. // This function ensures that the header is a valid LH header
  303. //
  304. //--------------------------------------------------------------------------;
  305. BOOL lhacmIsValidFormat ( LPWAVEFORMATEX pwfx, PINSTANCEDATA pid )
  306. {
  307. BOOL fReturn = FALSE;
  308. PCODECINFO pCodecInfo;
  309. WORD cbSize;
  310. FUNCTION_ENTRY ("lhacmIsValidFormat()");
  311. if (NULL == pwfx)
  312. {
  313. DBGMSG (1, (_T ("%s: pwfx is null\r\n"), SZFN));
  314. goto MyExit;
  315. }
  316. if ((pwfx->nChannels < 1) || (pwfx->nChannels > ACM_DRIVER_MAX_CHANNELS))
  317. {
  318. DBGMSG (1, (_T ("%s: bad nChannels=%d\r\n"), SZFN, (UINT) pwfx->nChannels));
  319. goto MyExit;
  320. }
  321. switch (pwfx->wFormatTag)
  322. {
  323. #ifdef CELP4800
  324. case WAVE_FORMAT_LH_CELP:
  325. pCodecInfo = &(pid->CELP.CodecInfo);
  326. break;
  327. #endif
  328. case WAVE_FORMAT_LH_SB8:
  329. pCodecInfo = &(pid->SB8.CodecInfo);
  330. break;
  331. case WAVE_FORMAT_LH_SB12:
  332. pCodecInfo = &(pid->SB12.CodecInfo);
  333. break;
  334. case WAVE_FORMAT_LH_SB16:
  335. pCodecInfo = &(pid->SB16.CodecInfo);
  336. break;
  337. default:
  338. DBGMSG (1, (_T ("%s: bad wFormatTag=%d\r\n"), SZFN, (UINT) pwfx->wFormatTag));
  339. goto MyExit;
  340. }
  341. cbSize = 0;
  342. if (pwfx->wBitsPerSample != pCodecInfo->wBitsPerSamplePCM)
  343. {
  344. DBGMSG (1, (_T ("%s: bad wBitsPerSample=%d\r\n"), SZFN, (UINT) pwfx->wBitsPerSample));
  345. goto MyExit;
  346. }
  347. if (pwfx->nBlockAlign != pCodecInfo->wCodedBufferSize)
  348. {
  349. DBGMSG (1, (_T ("%s: bad nBlockAlign=%d\r\n"), SZFN, (UINT) pwfx->nBlockAlign));
  350. goto MyExit;
  351. }
  352. if (pwfx->nSamplesPerSec != pCodecInfo->dwSampleRate)
  353. {
  354. DBGMSG (1, (_T ("%s: bad nSamplesPerSec=%d\r\n"), SZFN, (UINT) pwfx->nSamplesPerSec));
  355. goto MyExit;
  356. }
  357. if (pwfx->cbSize != cbSize)
  358. {
  359. DBGMSG (1, (_T ("%s: bad cbSize=%d\r\n"), SZFN, (UINT) pwfx->cbSize));
  360. goto MyExit;
  361. }
  362. fReturn = TRUE;
  363. MyExit:
  364. DBGMSG (1, (_T ("%s: fReturn=%d\r\n"), SZFN, (UINT) fReturn));
  365. return fReturn;
  366. } // lhacmIsValidFormat()
  367. //==========================================================================;
  368. //
  369. // The followings are message handlers...
  370. //
  371. //
  372. //==========================================================================;
  373. //==========================================================================;
  374. //
  375. // on DRV_OPEN
  376. //
  377. //==========================================================================;
  378. LRESULT FAR PASCAL acmdDriverOpen
  379. (
  380. HDRVR hdrvr,
  381. LPACMDRVOPENDESC paod
  382. )
  383. {
  384. PINSTANCEDATA pdata = NULL;
  385. FUNCTION_ENTRY ("acmdDriverOpen")
  386. //
  387. // the [optional] open description that is passed to this driver can
  388. // be from multiple 'managers.' for example, AVI looks for installable
  389. // drivers that are tagged with 'vidc' and 'vcap'. we need to verify
  390. // that we are being opened as an Audio Compression Manager driver.
  391. //
  392. // if paod is NULL, then the driver is being opened for some purpose
  393. // other than converting (that is, there will be no stream open
  394. // requests for this instance of being opened). the most common case
  395. // of this is the Control Panel's Drivers option checking for config
  396. // support (DRV_[QUERY]CONFIGURE).
  397. //
  398. // we want to succeed this open, but be able to know that this
  399. // open instance is bogus for creating streams. for this purpose we
  400. // leave most of the members of our instance structure that we
  401. // allocate below as zero...
  402. //
  403. if (paod)
  404. {
  405. //
  406. // refuse to open if we are not being opened as an ACM driver.
  407. // note that we do NOT modify the value of paod->dwError in this
  408. // case.
  409. //
  410. if (paod->fccType != ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC)
  411. {
  412. return 0;
  413. }
  414. }
  415. // !!! add check for LH DLL version here
  416. // we're not using the instance data for much right
  417. // now. when we add a configuration dialog it will
  418. // be more useful
  419. pdata= LocalAlloc (LPTR, sizeof (INSTANCEDATA));
  420. if (pdata == NULL)
  421. {
  422. if (paod)
  423. {
  424. paod->dwError = MMSYSERR_NOMEM;
  425. }
  426. return 0;
  427. }
  428. pdata->cbStruct = sizeof (INSTANCEDATA);
  429. pdata->hInst = GetDriverModuleHandle (hdrvr);
  430. #ifdef CELP4800
  431. pdata->CELP.wFormatTag = WAVE_FORMAT_LH_CELP;
  432. MSLHSB_GetCodecInfo (&(pdata->CELP.CodecInfo), 4800);
  433. DBGMSG (1, (_T ("%s: CELP's codec info\r\n"), SZFN));
  434. DBGMSG (1, (_T ("%s: wPCMBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->CELP.CodecInfo.wPCMBufferSize));
  435. DBGMSG (1, (_T ("%s: wCodedBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->CELP.CodecInfo.wCodedBufferSize));
  436. DBGMSG (1, (_T ("%s: wBitsPerSamplePCM=0x%X\r\n"), SZFN, (UINT) pdata->CELP.CodecInfo.wBitsPerSamplePCM));
  437. DBGMSG (1, (_T ("%s: dwSampleRate=0x%lX\r\n"), SZFN, pdata->CELP.CodecInfo.dwSampleRate));
  438. DBGMSG (1, (_T ("%s: wFormatSubTag=0x%X\r\n"), SZFN, (UINT) pdata->CELP.CodecInfo.wFormatSubTag));
  439. DBGMSG (1, (_T ("%s: wFormatSubTagName=[%s]\r\n"), SZFN, pdata->CELP.CodecInfo.wFormatSubTagName));
  440. DBGMSG (1, (_T ("%s: dwDLLVersion=0x%lX\r\n"), SZFN, pdata->CELP.CodecInfo.dwDLLVersion));
  441. #endif
  442. pdata->SB8.wFormatTag = WAVE_FORMAT_LH_SB8;
  443. MSLHSB_GetCodecInfo (&(pdata->SB8.CodecInfo), 8000);
  444. DBGMSG (1, (_T ("%s: SB8's codec info\r\n"), SZFN));
  445. DBGMSG (1, (_T ("%s: wPCMBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB8.CodecInfo.wPCMBufferSize));
  446. DBGMSG (1, (_T ("%s: wCodedBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB8.CodecInfo.wCodedBufferSize));
  447. DBGMSG (1, (_T ("%s: wBitsPerSamplePCM=0x%X\r\n"), SZFN, (UINT) pdata->SB8.CodecInfo.wBitsPerSamplePCM));
  448. DBGMSG (1, (_T ("%s: dwSampleRate=0x%lX\r\n"), SZFN, pdata->SB8.CodecInfo.dwSampleRate));
  449. DBGMSG (1, (_T ("%s: wFormatSubTag=0x%X\r\n"), SZFN, (UINT) pdata->SB8.CodecInfo.wFormatSubTag));
  450. DBGMSG (1, (_T ("%s: wFormatSubTagName=[%s]\r\n"), SZFN, pdata->SB8.CodecInfo.wFormatSubTagName));
  451. DBGMSG (1, (_T ("%s: dwDLLVersion=0x%lX\r\n"), SZFN, pdata->SB8.CodecInfo.dwDLLVersion));
  452. pdata->SB12.wFormatTag = WAVE_FORMAT_LH_SB12;
  453. MSLHSB_GetCodecInfo (&(pdata->SB12.CodecInfo), 12000);
  454. DBGMSG (1, (_T ("%s: SB12's codec info\r\n"), SZFN));
  455. DBGMSG (1, (_T ("%s: wPCMBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB12.CodecInfo.wPCMBufferSize));
  456. DBGMSG (1, (_T ("%s: wCodedBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB12.CodecInfo.wCodedBufferSize));
  457. DBGMSG (1, (_T ("%s: wBitsPerSamplePCM=0x%X\r\n"), SZFN, (UINT) pdata->SB12.CodecInfo.wBitsPerSamplePCM));
  458. DBGMSG (1, (_T ("%s: dwSampleRate=0x%lX\r\n"), SZFN, pdata->SB12.CodecInfo.dwSampleRate));
  459. DBGMSG (1, (_T ("%s: wFormatSubTag=0x%X\r\n"), SZFN, (UINT) pdata->SB12.CodecInfo.wFormatSubTag));
  460. DBGMSG (1, (_T ("%s: wFormatSubTagName=[%s]\r\n"), SZFN, pdata->SB12.CodecInfo.wFormatSubTagName));
  461. DBGMSG (1, (_T ("%s: dwDLLVersion=0x%lX\r\n"), SZFN, pdata->SB12.CodecInfo.dwDLLVersion));
  462. pdata->SB16.wFormatTag = WAVE_FORMAT_LH_SB16;
  463. MSLHSB_GetCodecInfo (&(pdata->SB16.CodecInfo), 16000);
  464. DBGMSG (1, (_T ("%s: SB16's codec info\r\n"), SZFN));
  465. DBGMSG (1, (_T ("%s: wPCMBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB16.CodecInfo.wPCMBufferSize));
  466. DBGMSG (1, (_T ("%s: wCodedBufferSize=0x%X\r\n"), SZFN, (UINT) pdata->SB16.CodecInfo.wCodedBufferSize));
  467. DBGMSG (1, (_T ("%s: wBitsPerSamplePCM=0x%X\r\n"), SZFN, (UINT) pdata->SB16.CodecInfo.wBitsPerSamplePCM));
  468. DBGMSG (1, (_T ("%s: dwSampleRate=0x%lX\r\n"), SZFN, pdata->SB16.CodecInfo.dwSampleRate));
  469. DBGMSG (1, (_T ("%s: wFormatSubTag=0x%X\r\n"), SZFN, (UINT) pdata->SB16.CodecInfo.wFormatSubTag));
  470. DBGMSG (1, (_T ("%s: wFormatSubTagName=[%s]\r\n"), SZFN, pdata->SB16.CodecInfo.wFormatSubTagName));
  471. DBGMSG (1, (_T ("%s: dwDLLVersion=0x%lX\r\n"), SZFN, pdata->SB16.CodecInfo.dwDLLVersion));
  472. pdata->fInit = TRUE;
  473. // let's update some global data
  474. gauPCMFormatIndexToSampleRate[0] = pdata->CELP.CodecInfo.dwSampleRate;
  475. #ifdef CELP4800
  476. gauLHCELPFormatIndexToSampleRate[0] = pdata->CELP.CodecInfo.dwSampleRate;
  477. #endif
  478. gauLHSB8FormatIndexToSampleRate[0] = pdata->SB8.CodecInfo.dwSampleRate;
  479. gauLHSB12FormatIndexToSampleRate[0] = pdata->SB12.CodecInfo.dwSampleRate;
  480. gauLHSB16FormatIndexToSampleRate[0] = pdata->SB16.CodecInfo.dwSampleRate;
  481. gauPCMFormatIndexToBitsPerSample[0] = pdata->CELP.CodecInfo.wBitsPerSamplePCM;
  482. #ifdef CELP4800
  483. gauLHCELPFormatIndexToBitsPerSample[0] = pdata->CELP.CodecInfo.wBitsPerSamplePCM;
  484. #endif
  485. gauLHSB8FormatIndexToBitsPerSample[0] = pdata->SB8.CodecInfo.wBitsPerSamplePCM;
  486. gauLHSB12FormatIndexToBitsPerSample[0] = pdata->SB12.CodecInfo.wBitsPerSamplePCM;
  487. gauLHSB16FormatIndexToBitsPerSample[0] = pdata->SB16.CodecInfo.wBitsPerSamplePCM;
  488. // report success
  489. if (paod)
  490. {
  491. paod->dwError = MMSYSERR_NOERROR;
  492. }
  493. return (LRESULT) pdata;
  494. } // acmdDriverOpen()
  495. //==========================================================================;
  496. //
  497. // on DRV_CLOSE
  498. //
  499. //==========================================================================;
  500. LRESULT FAR PASCAL acmdDriverClose
  501. (
  502. PINSTANCEDATA pid
  503. )
  504. {
  505. FUNCTION_ENTRY ("acmdDriverClose")
  506. if (pid)
  507. {
  508. LocalFree ((HLOCAL) pid);
  509. }
  510. return 1;
  511. } // acmdDriverClose()
  512. //--------------------------------------------------------------------------;
  513. //
  514. // on DRV_CONFIGURE
  515. //
  516. //--------------------------------------------------------------------------;
  517. LRESULT FAR PASCAL acmdDriverConfigure
  518. (
  519. PINSTANCEDATA pid,
  520. HWND hwnd,
  521. LPDRVCONFIGINFO pdci
  522. )
  523. {
  524. //
  525. // first check to see if we are only being queried for hardware
  526. // configuration support. if hwnd == (HWND)-1 then we are being
  527. // queried and should return zero for 'not supported' and non-zero
  528. // for 'supported'.
  529. //
  530. if (hwnd == (HWND) -1)
  531. {
  532. //
  533. // this codec does not support hardware configuration so return
  534. // zero...
  535. //
  536. return 0;
  537. }
  538. //
  539. // we are being asked to bring up our hardware configuration dialog.
  540. // if this codec can bring up a dialog box, then after the dialog
  541. // is dismissed we return non-zero. if we are not able to display a
  542. // dialog, then return zero.
  543. //
  544. return 0;
  545. } // acmdDriverConfigure()
  546. //--------------------------------------------------------------------------;
  547. //
  548. // on ACMDM_DRIVER_DETAILS
  549. //
  550. //--------------------------------------------------------------------------;
  551. LRESULT FAR PASCAL acmdDriverDetails
  552. (
  553. PINSTANCEDATA pid,
  554. LPACMDRIVERDETAILS padd
  555. )
  556. {
  557. ACMDRIVERDETAILS add;
  558. DWORD cbStruct;
  559. FUNCTION_ENTRY ("acmdDriverDetails")
  560. //
  561. // it is easiest to fill in a temporary structure with valid info
  562. // and then copy the requested number of bytes to the destination
  563. // buffer.
  564. //
  565. ZeroMemory (&add, sizeof (add));
  566. cbStruct = min (padd->cbStruct, sizeof (ACMDRIVERDETAILS));
  567. add.cbStruct = cbStruct;
  568. //
  569. // for the current implementation of an ACM driver, the fccType and
  570. // fccComp members *MUST* always be ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
  571. // ('audc') and ACMDRIVERDETAILS_FCCCOMP_UNDEFINED (0) respectively.
  572. //
  573. add.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
  574. add.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
  575. //
  576. // the manufacturer id (wMid) and product id (wPid) must be filled
  577. // in with your company's _registered_ identifier's. for more
  578. // information on these identifier's and how to get them registered
  579. // contact Microsoft and get the Multimedia Developer Registration Kit:
  580. //
  581. // Microsoft Corporation
  582. // Multimedia Technology Group
  583. // One Microsoft Way
  584. // Redmond, WA 98052-6399
  585. //
  586. // Developer Services Phone: (800) 227-4679 x11771
  587. //
  588. // note that during the development phase or your ACM driver, you may
  589. // use the reserved value of '0' for both wMid and wPid. however it
  590. // is not acceptable to ship a driver with these values.
  591. //
  592. add.wMid = MM_ACM_MID_LH;
  593. add.wPid = MM_ACM_PID_LH;
  594. //
  595. // the vdwACM and vdwDriver members contain version information for
  596. // the driver.
  597. //
  598. // vdwACM: must contain the version of the *ACM* that the driver was
  599. // _designed_ for. this is the _minimum_ version number of the ACM
  600. // that the driver will work with. this value must be >= V2.00.000.
  601. //
  602. // vdwDriver: the version of this ACM driver.
  603. //
  604. // ACM driver versions are 32 bit numbers broken into three parts as
  605. // follows (note these parts are displayed as decimal values):
  606. //
  607. // bits 24 - 31: 8 bit _major_ version number
  608. // bits 16 - 23: 8 bit _minor_ version number
  609. // bits 0 - 15: 16 bit build number
  610. //
  611. add.vdwACM = VERSION_MSACM;
  612. add.vdwDriver = VERSION_ACM_DRIVER;
  613. //
  614. // the following flags are used to specify the type of conversion(s)
  615. // that the ACM driver supports. note that a driver may support one or
  616. // more of these flags in any combination.
  617. //
  618. // ACMDRIVERDETAILS_SUPPORTF_CODEC: this flag is set if the driver
  619. // supports conversions from one format tag to another format tag. for
  620. // example, if a converter compresses or decompresses WAVE_FORMAT_PCM
  621. // and WAVE_FORMAT_IMA_ADPCM, then this bit should be set. this is
  622. // true even if the data is not actually changed in size--for example
  623. // a conversion from u-Law to A-Law will still set this bit because
  624. // the format tags differ.
  625. //
  626. // ACMDRIVERDETAILS_SUPPORTF_CONVERTER: this flags is set if the
  627. // driver supports conversions on the same format tag. as an example,
  628. // the PCM converter that is built into the ACM sets this bit (and only
  629. // this bit) because it converts only between PCM formats (bits, sample
  630. // rate).
  631. //
  632. // ACMDRIVERDETAILS_SUPPORTF_FILTER: this flag is set if the driver
  633. // supports transformations on a single format tag but does change
  634. // the base characteristics of the format (bit depth, sample rate, etc
  635. // will remain the same). for example, a driver that changed the
  636. // 'volume' of PCM data or applied a low pass filter would set this bit.
  637. //
  638. add.fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  639. // the number of individual format tags this ACM driver supports. for
  640. // example, if a driver uses the WAVE_FORMAT_IMA_ADPCM and
  641. // WAVE_FORMAT_PCM format tags, then this value would be two. if the
  642. // driver only supports filtering on WAVE_FORMAT_PCM, then this value
  643. // would be one. if this driver supported WAVE_FORMAT_ALAW,
  644. // WAVE_FORMAT_MULAW and WAVE_FORMAT_PCM, then this value would be
  645. // three. etc, etc.
  646. add.cFormatTags = ACM_DRIVER_MAX_FORMAT_TAGS;
  647. // the number of individual filter tags this ACM driver supports. if
  648. // a driver supports no filters (ACMDRIVERDETAILS_SUPPORTF_FILTER is
  649. // NOT set in the fdwSupport member), then this value must be zero.
  650. add.cFilterTags = ACM_DRIVER_MAX_FILTER_TAGS;
  651. // the remaining members in the ACMDRIVERDETAILS structure are sometimes
  652. // not needed. because of this we make a quick check to see if we
  653. // should go through the effort of filling in these members.
  654. if (FIELD_OFFSET (ACMDRIVERDETAILS, hicon) < cbStruct)
  655. {
  656. // fill in the hicon member will a handle to a custom icon for
  657. // the ACM driver. this allows the driver to be represented by
  658. // an application graphically (usually this will be a company
  659. // logo or something). if a driver does not wish to have a custom
  660. // icon displayed, then simply set this member to NULL and a
  661. // generic icon will be displayed instead.
  662. //
  663. // See the MSFILTER sample for a codec which contains a custom icon.
  664. add.hicon = NULL;
  665. // the short name and long name are used to represent the driver
  666. // in a unique description. the short name is intended for small
  667. // display areas (for example, in a menu or combo box). the long
  668. // name is intended for more descriptive displays (for example,
  669. // in an 'about box').
  670. //
  671. // NOTE! an ACM driver should never place formatting characters
  672. // of any sort in these strings (for example CR/LF's, etc). it
  673. // is up to the application to format the text.
  674. LoadStringCodec (pid->hInst, IDS_CODEC_SHORTNAME,
  675. add.szShortName, SIZEOFACMSTR (add.szShortName));
  676. LoadStringCodec (pid->hInst, IDS_CODEC_LONGNAME,
  677. add.szLongName, SIZEOFACMSTR (add.szLongName));
  678. // the last three members are intended for 'about box' information.
  679. // these members are optional and may be zero length strings if
  680. // the driver wishes.
  681. //
  682. // NOTE! an ACM driver should never place formatting characters
  683. // of any sort in these strings (for example CR/LF's, etc). it
  684. // is up to the application to format the text.
  685. if (FIELD_OFFSET (ACMDRIVERDETAILS, szCopyright) < cbStruct)
  686. {
  687. LoadStringCodec (pid->hInst, IDS_CODEC_COPYRIGHT,
  688. add.szCopyright, SIZEOFACMSTR (add.szCopyright));
  689. LoadStringCodec (pid->hInst, IDS_CODEC_LICENSING,
  690. add.szLicensing, SIZEOFACMSTR (add.szLicensing));
  691. LoadStringCodec (pid->hInst, IDS_CODEC_FEATURES,
  692. add.szFeatures, SIZEOFACMSTR (add.szFeatures));
  693. }
  694. }
  695. // now copy the correct number of bytes to the caller's buffer
  696. CopyMemory (padd, &add, (UINT) add.cbStruct);
  697. // success!
  698. return MMSYSERR_NOERROR;
  699. } // acmdDriverDetails()
  700. //--------------------------------------------------------------------------;
  701. //
  702. // on ACMDM_DRIVER_ABOUT
  703. //
  704. //--------------------------------------------------------------------------;
  705. LRESULT FAR PASCAL acmdDriverAbout
  706. (
  707. PINSTANCEDATA pid,
  708. HWND hwnd
  709. )
  710. {
  711. FUNCTION_ENTRY ("acmdDriverAbout")
  712. //
  713. // first check to see if we are only being queried for custom about
  714. // box support. if hwnd == (HWND)-1 then we are being queried and
  715. // should return MMSYSERR_NOTSUPPORTED for 'not supported' and
  716. // MMSYSERR_NOERROR for 'supported'.
  717. //
  718. // this driver does not support a custom dialog, so tell the ACM or
  719. // calling application to display one for us. note that this is the
  720. // _recommended_ method for consistency and simplicity of ACM drivers.
  721. // why write code when you don't have to?
  722. return MMSYSERR_NOTSUPPORTED;
  723. } // acmdDriverAbout()
  724. //--------------------------------------------------------------------------;
  725. //
  726. // on ACMDM_FORMAT_SUGGEST
  727. //
  728. //--------------------------------------------------------------------------;
  729. LRESULT FAR PASCAL acmdFormatSuggest
  730. (
  731. PINSTANCEDATA pid,
  732. LPACMDRVFORMATSUGGEST padfs
  733. )
  734. {
  735. #define ACMD_FORMAT_SUGGEST_SUPPORT (ACM_FORMATSUGGESTF_WFORMATTAG | \
  736. ACM_FORMATSUGGESTF_NCHANNELS | \
  737. ACM_FORMATSUGGESTF_NSAMPLESPERSEC |\
  738. ACM_FORMATSUGGESTF_WBITSPERSAMPLE)
  739. LPWAVEFORMATEX pwfxSrc;
  740. LPWAVEFORMATEX pwfxDst;
  741. DWORD fdwSuggest;
  742. DWORD nSamplesPerSec;
  743. WORD wBitsPerSample;
  744. FUNCTION_ENTRY ("acmdFormatSuggest")
  745. // grab the suggestion restriction bits and verify that we support
  746. // the ones that are specified... an ACM driver must return the
  747. // MMSYSERR_NOTSUPPORTED if the suggestion restriction bits specified
  748. // are not supported.
  749. fdwSuggest = (ACM_FORMATSUGGESTF_TYPEMASK & padfs->fdwSuggest);
  750. if (~ACMD_FORMAT_SUGGEST_SUPPORT & fdwSuggest)
  751. return MMSYSERR_NOTSUPPORTED;
  752. // get the source and destination formats in more convenient variables
  753. pwfxSrc = padfs->pwfxSrc;
  754. pwfxDst = padfs->pwfxDst;
  755. switch (pwfxSrc->wFormatTag)
  756. {
  757. case WAVE_FORMAT_PCM:
  758. DBGMSG (1, (_T ("%s: src wFormatTag=WAVE_FORMAT_PCM\r\n"), SZFN));
  759. // strictly verify that the source format is acceptable for
  760. // this driver
  761. //
  762. if (! pcmIsValidFormat (pwfxSrc))
  763. {
  764. DBGMSG (1, (_T ("%s: src format not valid\r\n"), SZFN));
  765. return ACMERR_NOTPOSSIBLE;
  766. }
  767. // if the destination format tag is restricted, verify that
  768. // it is within our capabilities...
  769. //
  770. // this driver can encode to one of four L&H codecs
  771. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  772. {
  773. switch (pwfxDst->wFormatTag)
  774. {
  775. #ifdef CELP4800
  776. case WAVE_FORMAT_LH_CELP:
  777. #endif
  778. case WAVE_FORMAT_LH_SB8:
  779. case WAVE_FORMAT_LH_SB12:
  780. case WAVE_FORMAT_LH_SB16:
  781. break;
  782. default:
  783. DBGMSG (1, (_T ("%s: not supported dest wFormatTag=%d\r\n"),
  784. SZFN, (UINT) pwfxDst->wFormatTag));
  785. return ACMERR_NOTPOSSIBLE;
  786. }
  787. }
  788. else
  789. {
  790. #ifdef CELP4800
  791. pwfxDst->wFormatTag = WAVE_FORMAT_LH_CELP;
  792. #else
  793. pwfxDst->wFormatTag = WAVE_FORMAT_LH_SB12;
  794. #endif
  795. }
  796. // if the destination channel count is restricted, verify that
  797. // it is within our capabilities...
  798. //
  799. // this driver is not able to change the number of channels
  800. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  801. {
  802. if ((pwfxSrc->nChannels != pwfxDst->nChannels) ||
  803. ((pwfxDst->nChannels < 1) &&
  804. (pwfxDst->nChannels > ACM_DRIVER_MAX_CHANNELS)))
  805. {
  806. DBGMSG (1, (_T ("%s: ERROR src'nChannels=%ld and dest'nChannels=%ld are different\r\n"),
  807. SZFN, (DWORD) pwfxSrc->nChannels, (DWORD) pwfxDst->nChannels));
  808. return ACMERR_NOTPOSSIBLE;
  809. }
  810. }
  811. else
  812. {
  813. pwfxDst->nChannels = pwfxSrc->nChannels;
  814. }
  815. switch (pwfxDst->wFormatTag)
  816. {
  817. #ifdef CELP4800
  818. case WAVE_FORMAT_LH_CELP:
  819. nSamplesPerSec = pid->CELP.CodecInfo.dwSampleRate;
  820. wBitsPerSample = pid->CELP.CodecInfo.wBitsPerSamplePCM;
  821. pwfxDst->nBlockAlign = pid->CELP.CodecInfo.wCodedBufferSize;
  822. pwfxDst->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->CELP.CodecInfo));
  823. pwfxDst->cbSize = 0;
  824. break;
  825. #endif
  826. case WAVE_FORMAT_LH_SB8:
  827. nSamplesPerSec = pid->SB8.CodecInfo.dwSampleRate;
  828. wBitsPerSample = pid->CELP.CodecInfo.wBitsPerSamplePCM;
  829. pwfxDst->nBlockAlign = pid->SB8.CodecInfo.wCodedBufferSize;
  830. pwfxDst->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB8.CodecInfo));
  831. pwfxDst->cbSize = 0;
  832. break;
  833. case WAVE_FORMAT_LH_SB12:
  834. nSamplesPerSec = pid->SB12.CodecInfo.dwSampleRate;
  835. wBitsPerSample = pid->CELP.CodecInfo.wBitsPerSamplePCM;
  836. pwfxDst->nBlockAlign = pid->SB12.CodecInfo.wCodedBufferSize;
  837. pwfxDst->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB12.CodecInfo));
  838. pwfxDst->cbSize = 0;
  839. break;
  840. case WAVE_FORMAT_LH_SB16:
  841. nSamplesPerSec = pid->SB16.CodecInfo.dwSampleRate;
  842. wBitsPerSample = pid->CELP.CodecInfo.wBitsPerSamplePCM;
  843. pwfxDst->nBlockAlign = pid->SB16.CodecInfo.wCodedBufferSize;
  844. pwfxDst->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB16.CodecInfo));
  845. pwfxDst->cbSize = 0;
  846. break;
  847. default:
  848. DBGMSG (1, (_T ("%s: not supported dest wFormatTag=%d\r\n"),
  849. SZFN, (UINT) pwfxDst->wFormatTag));
  850. return ACMERR_NOTPOSSIBLE;
  851. }
  852. // if the destination samples per second is restricted, verify
  853. // that it is within our capabilities...
  854. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  855. {
  856. if (pwfxDst->nSamplesPerSec != nSamplesPerSec)
  857. {
  858. DBGMSG (1, (_T ("%s: ERROR dest'nSamplesPerSec=%ld must be 8000\r\n"),
  859. SZFN, (DWORD) pwfxDst->nSamplesPerSec));
  860. return ACMERR_NOTPOSSIBLE;
  861. }
  862. }
  863. else
  864. {
  865. pwfxDst->nSamplesPerSec = nSamplesPerSec;
  866. }
  867. // if the destination bits per sample is restricted, verify
  868. // that it is within our capabilities...
  869. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  870. {
  871. if (pwfxDst->wBitsPerSample != wBitsPerSample)
  872. {
  873. DBGMSG (1, (_T ("%s: dest wBitsPerSample is not valid\r\n"), SZFN));
  874. return ACMERR_NOTPOSSIBLE;
  875. }
  876. }
  877. else
  878. {
  879. pwfxDst->wBitsPerSample = wBitsPerSample;
  880. }
  881. DBGMSG (1, (_T ("%s: returns no error\r\n"), SZFN));
  882. return MMSYSERR_NOERROR;
  883. #ifdef CELP4800
  884. case WAVE_FORMAT_LH_CELP:
  885. #endif
  886. case WAVE_FORMAT_LH_SB8:
  887. case WAVE_FORMAT_LH_SB12:
  888. case WAVE_FORMAT_LH_SB16:
  889. DBGMSG (1, (_T ("%s: src wFormatTag=0x%X\r\n"), SZFN, (UINT) pwfxSrc->wFormatTag));
  890. // strictly verify that the source format is acceptable for
  891. // this driver
  892. //
  893. if (! lhacmIsValidFormat (pwfxSrc, pid))
  894. {
  895. DBGMSG (1, (_T ("%s: src format not valid\r\n"), SZFN));
  896. return ACMERR_NOTPOSSIBLE;
  897. }
  898. // if the destination format tag is restricted, verify that
  899. // it is within our capabilities...
  900. //
  901. // this driver is only able to decode to PCM
  902. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  903. {
  904. if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM)
  905. {
  906. DBGMSG (1, (_T ("%s: not supported dest wFormatTag=%d\r\n"),
  907. SZFN, (UINT) pwfxDst->wFormatTag));
  908. return ACMERR_NOTPOSSIBLE;
  909. }
  910. }
  911. else
  912. {
  913. pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
  914. }
  915. // if the destination channel count is restricted, verify that
  916. // it is within our capabilities...
  917. //
  918. // this driver is not able to change the number of channels
  919. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  920. {
  921. if ((pwfxSrc->nChannels != pwfxDst->nChannels) ||
  922. ((pwfxDst->nChannels < 1) &&
  923. (pwfxDst->nChannels > ACM_DRIVER_MAX_CHANNELS)))
  924. {
  925. DBGMSG (1, (_T ("%s: ERROR src'nChannels=%ld and dest'nChannels=%ld are different\r\n"),
  926. SZFN, (DWORD) pwfxSrc->nChannels, (DWORD) pwfxDst->nChannels));
  927. return ACMERR_NOTPOSSIBLE;
  928. }
  929. }
  930. else
  931. {
  932. pwfxDst->nChannels = pwfxSrc->nChannels;
  933. }
  934. // if the destination samples per second is restricted, verify
  935. // that it is within our capabilities...
  936. //
  937. // this driver is not able to change the sample rate
  938. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  939. {
  940. if (pwfxDst->nSamplesPerSec != pwfxSrc->nSamplesPerSec)
  941. {
  942. DBGMSG (1, (_T ("%s: ERROR invalid dest'nSamplesPerSec=%ld\r\n"),
  943. SZFN, (DWORD) pwfxDst->nSamplesPerSec));
  944. return ACMERR_NOTPOSSIBLE;
  945. }
  946. }
  947. else
  948. {
  949. pwfxDst->nSamplesPerSec = pwfxSrc->nSamplesPerSec;
  950. }
  951. // if the destination bits per sample is restricted, verify
  952. // that it is within our capabilities...
  953. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  954. {
  955. if (pwfxDst->wBitsPerSample != LH_PCM_BITSPERSAMPLE)
  956. {
  957. DBGMSG (1, (_T ("%s: dest wBitsPerSample is not 16\r\n"), SZFN));
  958. return ACMERR_NOTPOSSIBLE;
  959. }
  960. }
  961. else
  962. {
  963. pwfxDst->wBitsPerSample = pwfxSrc->wBitsPerSample;
  964. }
  965. // at this point, we have filled in all fields except the
  966. // following for our 'suggested' destination format:
  967. //
  968. // nAvgBytesPerSec
  969. // nBlockAlign
  970. // cbSize
  971. pwfxDst->nBlockAlign = PCM_BLOCKALIGNMENT (pwfxDst);
  972. pwfxDst->nAvgBytesPerSec = pwfxDst->nSamplesPerSec *
  973. pwfxDst->nBlockAlign;
  974. // pwfxDst->cbSize = not used;
  975. DBGMSG (1, (_T ("%s: returns no error\r\n"), SZFN));
  976. return MMSYSERR_NOERROR;
  977. }
  978. // can't suggest anything because either the source format is foreign
  979. // or the destination format has restrictions that this ACM driver
  980. // cannot deal with.
  981. DBGMSG (1, (_T ("%s: bad wFormatTag=%d\r\n"), SZFN, (UINT) pwfxSrc->wFormatTag));
  982. return ACMERR_NOTPOSSIBLE;
  983. } // acmdFormatSuggest()
  984. //--------------------------------------------------------------------------;
  985. //
  986. // on ACMDM_FORMATTAG_DETAILS
  987. //
  988. //--------------------------------------------------------------------------;
  989. LRESULT FAR PASCAL acmdFormatTagDetails
  990. (
  991. PINSTANCEDATA pid,
  992. LPACMFORMATTAGDETAILS padft,
  993. DWORD fdwDetails
  994. )
  995. {
  996. UINT uFormatTag;
  997. FUNCTION_ENTRY ("acmdFormatTagDetails")
  998. switch (ACM_FORMATTAGDETAILSF_QUERYMASK & fdwDetails)
  999. {
  1000. case ACM_FORMATTAGDETAILSF_INDEX:
  1001. DBGMSG (1, (_T ("%s: ACM_FORMATTAGDETAILSF_INDEX\r\n"), SZFN));
  1002. // if the index is too large, then they are asking for a
  1003. // non-existant format. return error.
  1004. if (padft->dwFormatTagIndex >= ACM_DRIVER_MAX_FORMAT_TAGS)
  1005. {
  1006. DBGMSG (1, (_T ("%s: ERROR too big dwFormatTagIndex=%ld\r\n"), SZFN, padft->dwFormatTagIndex));
  1007. return ACMERR_NOTPOSSIBLE;
  1008. }
  1009. uFormatTag = gauFormatTagIndexToTag[padft->dwFormatTagIndex];
  1010. break;
  1011. case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
  1012. DBGMSG (1, (_T ("%s: ACM_FORMATTAGDETAILSF_LARGESTSIZE\r\n"), SZFN));
  1013. switch (padft->dwFormatTag)
  1014. {
  1015. case WAVE_FORMAT_UNKNOWN:
  1016. #ifdef CELP4800
  1017. padft->dwFormatTag = WAVE_FORMAT_LH_CELP;
  1018. #else
  1019. padft->dwFormatTag = WAVE_FORMAT_LH_SB12;
  1020. #endif
  1021. #ifdef CELP4800
  1022. case WAVE_FORMAT_LH_CELP:
  1023. #endif
  1024. case WAVE_FORMAT_LH_SB8:
  1025. case WAVE_FORMAT_LH_SB12:
  1026. case WAVE_FORMAT_LH_SB16:
  1027. uFormatTag = padft->dwFormatTag;
  1028. DBGMSG (1, (_T ("%s: dwFormatTag=0x%x\r\n"), SZFN, uFormatTag));
  1029. break;
  1030. case WAVE_FORMAT_PCM:
  1031. DBGMSG (1, (_T ("%s: dwFormatTag=WAVE_FORMAT_PCM\r\n"), SZFN));
  1032. uFormatTag = WAVE_FORMAT_PCM;
  1033. break;
  1034. default:
  1035. DBGMSG (1, (_T ("%s: dwFormatTag=%ld not valid\r\n"), SZFN, padft->dwFormatTag));
  1036. return ACMERR_NOTPOSSIBLE;
  1037. }
  1038. break;
  1039. case ACM_FORMATTAGDETAILSF_FORMATTAG:
  1040. DBGMSG (1, (_T ("%s: ACM_FORMATTAGDETAILSF_FORMATTAG\r\n"), SZFN));
  1041. switch (padft->dwFormatTag)
  1042. {
  1043. #ifdef CELP4800
  1044. case WAVE_FORMAT_LH_CELP:
  1045. #endif
  1046. case WAVE_FORMAT_LH_SB8:
  1047. case WAVE_FORMAT_LH_SB12:
  1048. case WAVE_FORMAT_LH_SB16:
  1049. case WAVE_FORMAT_PCM:
  1050. uFormatTag = padft->dwFormatTag;
  1051. DBGMSG (1, (_T ("%s: dwFormatTag=0x%x\r\n"), SZFN, uFormatTag));
  1052. break;
  1053. default:
  1054. DBGMSG (1, (_T ("%s: dwFormatTag=%ld not valid\r\n"), SZFN, padft->dwFormatTag));
  1055. return ACMERR_NOTPOSSIBLE;
  1056. }
  1057. break;
  1058. // if this ACM driver does not understand a query type, then
  1059. // return 'not supported'
  1060. default:
  1061. DBGMSG (1, (_T ("%s: this detail option is not supported, fdwDetails=0x%lX\r\n"), SZFN, fdwDetails));
  1062. return MMSYSERR_NOTSUPPORTED;
  1063. }
  1064. // ok, let's fill in the structure based on uFormatTag!
  1065. switch (uFormatTag)
  1066. {
  1067. case WAVE_FORMAT_PCM:
  1068. DBGMSG (1, (_T ("%s: uFormatTag=WAVE_FORMAT_PCM\r\n"), SZFN));
  1069. padft->dwFormatTagIndex = IDX_PCM;
  1070. padft->dwFormatTag = WAVE_FORMAT_PCM;
  1071. padft->cbFormatSize = sizeof (PCMWAVEFORMAT);
  1072. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1073. padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_PCM;
  1074. //
  1075. // the ACM is responsible for the PCM format tag name
  1076. //
  1077. padft->szFormatTag[0] = 0;
  1078. break;
  1079. #ifdef CELP4800
  1080. case WAVE_FORMAT_LH_CELP:
  1081. DBGMSG (1, (_T ("%s: uFormatTag=WAVE_FORMAT_LH_CELP\r\n"), SZFN));
  1082. padft->dwFormatTagIndex = IDX_LH_CELP;
  1083. #endif
  1084. /* GOTOs - ugh! */
  1085. Label_LH_common:
  1086. padft->dwFormatTag = uFormatTag;
  1087. padft->cbFormatSize = sizeof (WAVEFORMATEX);
  1088. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1089. #ifdef CELP4800
  1090. padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_LH_CELP;
  1091. #else
  1092. padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_LH_SB16;
  1093. #endif
  1094. LoadStringCodec (pid->hInst, gauTagNameIds[padft->dwFormatTagIndex],
  1095. padft->szFormatTag, SIZEOFACMSTR (padft->szFormatTag));
  1096. break;
  1097. case WAVE_FORMAT_LH_SB8:
  1098. DBGMSG (1, (_T ("%s: uFormatTag=WAVE_FORMAT_LH_SB8\r\n"), SZFN));
  1099. padft->dwFormatTagIndex = IDX_LH_SB8;
  1100. goto Label_LH_common;
  1101. case WAVE_FORMAT_LH_SB12:
  1102. DBGMSG (1, (_T ("%s: uFormatTag=WAVE_FORMAT_LH_SB12\r\n"), SZFN));
  1103. padft->dwFormatTagIndex = IDX_LH_SB12;
  1104. goto Label_LH_common;
  1105. case WAVE_FORMAT_LH_SB16:
  1106. DBGMSG (1, (_T ("%s: uFormatTag=WAVE_FORMAT_LH_SB16\r\n"), SZFN));
  1107. padft->dwFormatTagIndex = IDX_LH_SB16;
  1108. goto Label_LH_common;
  1109. default:
  1110. DBGMSG (1, (_T ("%s: uFormatTag=%d not valid\r\n"), SZFN, uFormatTag));
  1111. return ACMERR_NOTPOSSIBLE;
  1112. }
  1113. // return only the requested info
  1114. //
  1115. // the ACM will guarantee that the ACMFORMATTAGDETAILS structure
  1116. // passed is at least large enough to hold the base information of
  1117. // the details structure
  1118. padft->cbStruct = min (padft->cbStruct, sizeof (*padft));
  1119. return MMSYSERR_NOERROR;
  1120. } // acmdFormatTagDetails()
  1121. //--------------------------------------------------------------------------;
  1122. //
  1123. // on ACMDM_FORMAT_DETAILS
  1124. //
  1125. //--------------------------------------------------------------------------;
  1126. LRESULT FAR PASCAL acmdFormatDetails
  1127. (
  1128. PINSTANCEDATA pid,
  1129. LPACMFORMATDETAILS padf,
  1130. DWORD fdwDetails
  1131. )
  1132. {
  1133. LPWAVEFORMATEX pwfx;
  1134. UINT uFormatIndex;
  1135. UINT u;
  1136. DWORD dwFormatTag;
  1137. FUNCTION_ENTRY ("acmdFormatDetails")
  1138. pwfx = padf->pwfx;
  1139. switch (ACM_FORMATDETAILSF_QUERYMASK & fdwDetails)
  1140. {
  1141. // enumerate by index
  1142. //
  1143. // verify that the format tag is something we know about and
  1144. // return the details on the 'standard format' supported by
  1145. // this driver at the specified index...
  1146. case ACM_FORMATDETAILSF_INDEX:
  1147. DBGMSG (1, (_T ("%s: ACM_FORMATDETAILSF_INDEX\r\n"), SZFN));
  1148. //
  1149. // put some stuff in more accessible variables--note that we
  1150. // bring variable sizes down to a reasonable size for 16 bit
  1151. // code...
  1152. //
  1153. dwFormatTag = padf->dwFormatTag;
  1154. uFormatIndex = padf->dwFormatIndex;
  1155. switch (dwFormatTag)
  1156. {
  1157. case WAVE_FORMAT_PCM:
  1158. DBGMSG (1, (_T ("%s: WAVE_FORMAT_PCM\r\n"), SZFN));
  1159. if (uFormatIndex >= ACM_DRIVER_MAX_FORMATS_PCM)
  1160. {
  1161. DBGMSG (1, (_T ("%s: ERROR too big dwFormatIndex=%ld\n"), SZFN, padf->dwFormatIndex));
  1162. return ACMERR_NOTPOSSIBLE;
  1163. }
  1164. //
  1165. // now fill in the format structure
  1166. //
  1167. pwfx->wFormatTag = WAVE_FORMAT_PCM;
  1168. u = uFormatIndex % ACM_DRIVER_MAX_PCM_SAMPLE_RATES;
  1169. pwfx->nSamplesPerSec = gauPCMFormatIndexToSampleRate[u];
  1170. u = uFormatIndex % ACM_DRIVER_MAX_CHANNELS;
  1171. pwfx->nChannels = u + 1;
  1172. u = uFormatIndex % ACM_DRIVER_MAX_BITSPERSAMPLE_PCM;
  1173. pwfx->wBitsPerSample = gauPCMFormatIndexToBitsPerSample[u];
  1174. pwfx->nBlockAlign = PCM_BLOCKALIGNMENT(pwfx);
  1175. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  1176. //
  1177. // note that the cbSize field is NOT valid for PCM
  1178. // formats
  1179. //
  1180. // pwfx->cbSize = 0;
  1181. break;
  1182. #ifdef CELP4800
  1183. case WAVE_FORMAT_LH_CELP:
  1184. DBGMSG (1, (_T ("%s: WAVE_FORMAT_LH_CELP\r\n"), SZFN));
  1185. if (uFormatIndex >= ACM_DRIVER_MAX_FORMATS_LH_CELP)
  1186. {
  1187. DBGMSG (1, (_T ("%s: too big dwFormatIndex=%ld\r\n"), SZFN, padf->dwFormatIndex));
  1188. return ACMERR_NOTPOSSIBLE;
  1189. }
  1190. pwfx->wFormatTag = WAVE_FORMAT_LH_CELP;
  1191. u = uFormatIndex % ACM_DRIVER_MAX_LH_CELP_SAMPLE_RATES;
  1192. pwfx->nSamplesPerSec = gauLHCELPFormatIndexToSampleRate[u];
  1193. u = uFormatIndex % ACM_DRIVER_MAX_BITSPERSAMPLE_LH_CELP;
  1194. pwfx->wBitsPerSample = gauLHCELPFormatIndexToBitsPerSample[u];
  1195. pwfx->nChannels = ACM_DRIVER_MAX_CHANNELS;
  1196. pwfx->nBlockAlign = pid->CELP.CodecInfo.wCodedBufferSize;
  1197. pwfx->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->CELP.CodecInfo));
  1198. pwfx->cbSize = 0;
  1199. break;
  1200. #endif
  1201. case WAVE_FORMAT_LH_SB8:
  1202. DBGMSG (1, (_T ("%s: WAVE_FORMAT_LH_SB8\r\n"), SZFN));
  1203. if (uFormatIndex >= ACM_DRIVER_MAX_FORMATS_LH_SB8)
  1204. {
  1205. DBGMSG (1, (_T ("%s: too big dwFormatIndex=%ld\r\n"), SZFN, padf->dwFormatIndex));
  1206. return ACMERR_NOTPOSSIBLE;
  1207. }
  1208. pwfx->wFormatTag = WAVE_FORMAT_LH_SB8;
  1209. u = uFormatIndex % ACM_DRIVER_MAX_LH_SB8_SAMPLE_RATES;
  1210. pwfx->nSamplesPerSec = gauLHSB8FormatIndexToSampleRate[u];
  1211. u = uFormatIndex % ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB8;
  1212. pwfx->wBitsPerSample = gauLHSB8FormatIndexToBitsPerSample[u];
  1213. pwfx->nChannels = ACM_DRIVER_MAX_CHANNELS;
  1214. pwfx->nBlockAlign = pid->SB8.CodecInfo.wCodedBufferSize;
  1215. pwfx->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB8.CodecInfo));
  1216. pwfx->cbSize = 0;
  1217. break;
  1218. case WAVE_FORMAT_LH_SB12:
  1219. DBGMSG (1, (_T ("%s: WAVE_FORMAT_LH_SB12\r\n"), SZFN));
  1220. if (uFormatIndex >= ACM_DRIVER_MAX_FORMATS_LH_SB12)
  1221. {
  1222. DBGMSG (1, (_T ("%s: too big dwFormatIndex=%ld\r\n"), SZFN, padf->dwFormatIndex));
  1223. return ACMERR_NOTPOSSIBLE;
  1224. }
  1225. pwfx->wFormatTag = WAVE_FORMAT_LH_SB12;
  1226. u = uFormatIndex % ACM_DRIVER_MAX_LH_SB12_SAMPLE_RATES;
  1227. pwfx->nSamplesPerSec = gauLHSB12FormatIndexToSampleRate[u];
  1228. u = uFormatIndex % ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB12;
  1229. pwfx->wBitsPerSample = gauLHSB12FormatIndexToBitsPerSample[u];
  1230. pwfx->nChannels = ACM_DRIVER_MAX_CHANNELS;
  1231. pwfx->nBlockAlign = pid->SB12.CodecInfo.wCodedBufferSize;
  1232. pwfx->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB12.CodecInfo));
  1233. pwfx->cbSize = 0;
  1234. break;
  1235. case WAVE_FORMAT_LH_SB16:
  1236. DBGMSG (1, (_T ("%s: WAVE_FORMAT_LH_SB16\r\n"), SZFN));
  1237. if (uFormatIndex >= ACM_DRIVER_MAX_FORMATS_LH_SB16)
  1238. {
  1239. DBGMSG (1, (_T ("%s: too big dwFormatIndex=%ld\r\n"), SZFN, padf->dwFormatIndex));
  1240. return ACMERR_NOTPOSSIBLE;
  1241. }
  1242. pwfx->wFormatTag = WAVE_FORMAT_LH_SB16;
  1243. u = uFormatIndex % ACM_DRIVER_MAX_LH_SB16_SAMPLE_RATES;
  1244. pwfx->nSamplesPerSec = gauLHSB16FormatIndexToSampleRate[u];
  1245. u = uFormatIndex % ACM_DRIVER_MAX_BITSPERSAMPLE_LH_SB16;
  1246. pwfx->wBitsPerSample = gauLHSB16FormatIndexToBitsPerSample[u];
  1247. pwfx->nChannels = ACM_DRIVER_MAX_CHANNELS;
  1248. pwfx->nBlockAlign = pid->SB16.CodecInfo.wCodedBufferSize;
  1249. pwfx->nAvgBytesPerSec = _GetAvgBytesPerSec (&(pid->SB16.CodecInfo));
  1250. pwfx->cbSize = 0;
  1251. break;
  1252. default:
  1253. DBGMSG (1, (_T ("%s: unknown dwFormatTag=%ld\r\n"), SZFN, dwFormatTag));
  1254. return ACMERR_NOTPOSSIBLE;
  1255. }
  1256. break;
  1257. case ACM_FORMATDETAILSF_FORMAT:
  1258. DBGMSG (1, (_T ("%s: ACM_FORMATDETAILSF_FORMAT\r\n"), SZFN));
  1259. //
  1260. // return details on specified format
  1261. //
  1262. // the caller normally uses this to verify that the format is
  1263. // supported and to retrieve a string description...
  1264. //
  1265. dwFormatTag = (DWORD) pwfx->wFormatTag;
  1266. switch (dwFormatTag)
  1267. {
  1268. case WAVE_FORMAT_PCM:
  1269. DBGMSG (1, (_T ("%s: WAVE_FORMAT_PCM\r\n"), SZFN));
  1270. if (! pcmIsValidFormat (pwfx))
  1271. {
  1272. DBGMSG (1, (_T ("%s: format not valid\r\n"), SZFN));
  1273. return ACMERR_NOTPOSSIBLE;
  1274. }
  1275. break;
  1276. #ifdef CELP4800
  1277. case WAVE_FORMAT_LH_CELP:
  1278. #endif
  1279. case WAVE_FORMAT_LH_SB8:
  1280. case WAVE_FORMAT_LH_SB12:
  1281. case WAVE_FORMAT_LH_SB16:
  1282. DBGMSG (1, (_T ("%s: WAVE_FORMAT_LH\r\n"), SZFN));
  1283. if (! lhacmIsValidFormat (pwfx, pid))
  1284. {
  1285. DBGMSG (1, (_T ("%s: format not valid\r\n"), SZFN));
  1286. return ACMERR_NOTPOSSIBLE;
  1287. }
  1288. break;
  1289. default:
  1290. DBGMSG (1, (_T ("%s: bad dwFormatTag=%ld\r\n"), SZFN, dwFormatTag));
  1291. return (ACMERR_NOTPOSSIBLE);
  1292. }
  1293. break;
  1294. default:
  1295. //
  1296. // don't know how to do the query type passed--return 'not
  1297. // supported'.
  1298. //
  1299. DBGMSG (1, (_T ("%s: not support this detail option=%ld\r\n"), SZFN, fdwDetails));
  1300. return MMSYSERR_NOTSUPPORTED;
  1301. }
  1302. // return the size of the valid information we are returning
  1303. //
  1304. // the ACM will guarantee that the ACMFORMATDETAILS structure
  1305. // passed is at least large enough to hold the base structure
  1306. //
  1307. // note that we let the ACM create the format string for us since
  1308. // we require no special formatting (and don't want to deal with
  1309. // internationalization issues, etc). simply set the string to
  1310. // a zero length.
  1311. padf->cbStruct = min (padf->cbStruct, sizeof (*padf));
  1312. if (padf->cbStruct == 0)
  1313. padf->cbStruct = sizeof (*padf);
  1314. padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1315. padf->szFormat[0] = '\0';
  1316. #ifdef _DEBUG
  1317. DBGMSG (1, (_T ("%s: %s, %ld Samp/Sec, %u Channels, %u-bit, Align=%u, %ld Bytes/Sec, cbSize=%u\n"),
  1318. SZFN, (WAVE_FORMAT_PCM == pwfx->wFormatTag ? (LPCTSTR) _T ("PCM") : (LPCTSTR) _T ("LH")),
  1319. pwfx->nSamplesPerSec, pwfx->nChannels,
  1320. pwfx->wBitsPerSample, pwfx->nBlockAlign,
  1321. pwfx->nAvgBytesPerSec, pwfx->cbSize));
  1322. #endif
  1323. return MMSYSERR_NOERROR;
  1324. } // acmdFormatDetails()
  1325. //--------------------------------------------------------------------------;
  1326. //
  1327. // on ACMDM_STREAM_OPEN
  1328. //
  1329. // Description:
  1330. // This function handles the ACMDM_STREAM_OPEN message. This message
  1331. // is sent to initiate a new conversion stream. This is usually caused
  1332. // by an application calling acmStreamOpen. If this function is
  1333. // successful, then one or more ACMDM_STREAM_CONVERT messages will be
  1334. // sent to convert individual buffers (user calls acmStreamConvert).
  1335. //
  1336. // Note that an ACM driver will not receive open requests for ASYNC
  1337. // or FILTER operations unless the ACMDRIVERDETAILS_SUPPORTF_ASYNC
  1338. // or ACMDRIVERDETAILS_SUPPORTF_FILTER flags are set in the
  1339. // ACMDRIVERDETAILS structure. There is no need for the driver to
  1340. // check for these requests unless it sets those support bits.
  1341. //
  1342. // If the ACM_STREAMOPENF_QUERY flag is set in the padsi->fdwOpen
  1343. // member, then no resources should be allocated. Just verify that
  1344. // the conversion request is possible by this driver and return the
  1345. // appropriate error (either ACMERR_NOTPOSSIBLE or MMSYSERR_NOERROR).
  1346. // The driver will NOT receive an ACMDM_STREAM_CLOSE for queries.
  1347. //
  1348. // If the ACM_STREAMOPENF_NONREALTIME bit is NOT set, then conversion
  1349. // must be done in 'real-time'. This is a tough one to describe
  1350. // exactly. If the driver may have trouble doing the conversion without
  1351. // breaking up the audio, then a configuration dialog might be used
  1352. // to allow the user to specify whether the real-time conversion
  1353. // request should be succeeded. DO NOT SUCCEED THE CALL UNLESS YOU
  1354. // ACTUALLY CAN DO REAL-TIME CONVERSIONS! There may be another driver
  1355. // installed that can--so if you succeed the call you are hindering
  1356. // the performance of the user's system!
  1357. //
  1358. // Arguments:
  1359. // HLOCAL pid: Pointer to private ACM driver instance structure.
  1360. // This structure is [optionally] allocated during the DRV_OPEN message
  1361. // which is handled by the acmdDriverOpen function.
  1362. //
  1363. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1364. // conversion stream. This structure was allocated by the ACM and
  1365. // filled with the most common instance data needed for conversions.
  1366. // This structure will be passed back to all future stream messages
  1367. // if the open succeeds. The information in this structure will never
  1368. // change during the lifetime of the stream--so it is not necessary
  1369. // to re-verify the information referenced by this structure.
  1370. //
  1371. // Return (LRESULT):
  1372. // The return value is zero (MMSYSERR_NOERROR) if this function
  1373. // succeeds with no errors. The return value is a non-zero error code
  1374. // if the function fails.
  1375. //
  1376. // A driver should return ACMERR_NOTPOSSIBLE if the conversion cannot
  1377. // be performed due to incompatible source and destination formats.
  1378. //
  1379. // A driver should return MMSYSERR_NOTSUPPORTED if the conversion
  1380. // cannot be performed in real-time and the request does not specify
  1381. // the ACM_STREAMOPENF_NONREALTIME flag.
  1382. //
  1383. //--------------------------------------------------------------------------;
  1384. LRESULT FAR PASCAL acmdStreamOpen
  1385. (
  1386. PINSTANCEDATA pid,
  1387. LPACMDRVSTREAMINSTANCE padsi
  1388. )
  1389. {
  1390. LPWAVEFORMATEX pwfxSrc = padsi->pwfxSrc;
  1391. LPWAVEFORMATEX pwfxDst = padsi->pwfxDst;
  1392. PSTREAMINSTANCEDATA psi;
  1393. BOOL fCompress;
  1394. UINT uEncodedFormatTag;
  1395. UINT cbMaxData;
  1396. DWORD dwMaxBitRate;
  1397. PFN_CONVERT pfnConvert = NULL;
  1398. PFN_CLOSE pfnClose = NULL;
  1399. HANDLE hAccess = NULL;
  1400. PCODECDATA pCodecData = NULL;
  1401. FUNCTION_ENTRY ("acmdStreamOpen")
  1402. // Validate that the input and output formats are compatible
  1403. DBGMSG (1, (_T ("%s: wFormatTag: Src=%d, Dst=%d\r\n"), SZFN, (UINT) pwfxSrc->wFormatTag, (UINT) pwfxDst->wFormatTag));
  1404. switch (pwfxSrc->wFormatTag)
  1405. {
  1406. case WAVE_FORMAT_PCM:
  1407. // Source is PCM (we'll be compressing): check it and
  1408. // make sure destination type is LH
  1409. if (! pcmIsValidFormat (pwfxSrc))
  1410. {
  1411. return ACMERR_NOTPOSSIBLE;
  1412. }
  1413. if (! lhacmIsValidFormat (pwfxDst, pid))
  1414. {
  1415. return ACMERR_NOTPOSSIBLE;
  1416. }
  1417. uEncodedFormatTag = pwfxDst->wFormatTag;
  1418. fCompress = TRUE;
  1419. break;
  1420. #ifdef CELP4800
  1421. case WAVE_FORMAT_LH_CELP:
  1422. #endif
  1423. case WAVE_FORMAT_LH_SB8:
  1424. case WAVE_FORMAT_LH_SB12:
  1425. case WAVE_FORMAT_LH_SB16:
  1426. // Source is LH (we'll be decompressing): check it and
  1427. // make sure destination type is PCM
  1428. if (! lhacmIsValidFormat (pwfxSrc, pid))
  1429. {
  1430. return ACMERR_NOTPOSSIBLE;
  1431. }
  1432. if (! pcmIsValidFormat (pwfxDst))
  1433. {
  1434. return ACMERR_NOTPOSSIBLE;
  1435. }
  1436. uEncodedFormatTag = pwfxSrc->wFormatTag;
  1437. fCompress = FALSE;
  1438. break;
  1439. default:
  1440. return ACMERR_NOTPOSSIBLE;
  1441. }
  1442. // For this driver, we must also verify that the nChannels and
  1443. // nSamplesPerSec members are the same between the source and
  1444. // destination formats.
  1445. if (pwfxSrc->nChannels != pwfxDst->nChannels)
  1446. {
  1447. DBGMSG (1, (_T ("%s: bad nChannels: Src=%d, Dst=%d\r\n"), SZFN, (UINT) pwfxSrc->nChannels, (UINT) pwfxDst->nChannels));
  1448. return MMSYSERR_NOTSUPPORTED;
  1449. }
  1450. if (pwfxSrc->nSamplesPerSec != pwfxDst->nSamplesPerSec)
  1451. {
  1452. DBGMSG (1, (_T ("%s: bad nSamplesPerSec: Src=%d, Dst=%d\r\n"), SZFN, (UINT) pwfxSrc->nSamplesPerSec, (UINT) pwfxDst->nSamplesPerSec));
  1453. return MMSYSERR_NOTSUPPORTED;
  1454. }
  1455. // we have determined that the conversion requested is possible by
  1456. // this driver. now check if we are just being queried for support.
  1457. // if this is just a query, then do NOT allocate any instance data
  1458. // or create tables, etc. just succeed the call.
  1459. if (ACM_STREAMOPENF_QUERY & padsi->fdwOpen)
  1460. {
  1461. DBGMSG (1, (_T ("%s: Query ok\r\n"), SZFN));
  1462. return MMSYSERR_NOERROR;
  1463. }
  1464. // we have decided that this driver can handle the conversion stream.
  1465. // so we want to do _AS MUCH WORK AS POSSIBLE_ right now to prepare
  1466. // for converting data. any resource allocation, table building, etc
  1467. // that can be dealt with at this time should be done.
  1468. //
  1469. // THIS IS VERY IMPORTANT! all ACMDM_STREAM_CONVERT messages need to
  1470. // be handled as quickly as possible.
  1471. cbMaxData = 0;
  1472. dwMaxBitRate = 0;
  1473. switch (uEncodedFormatTag)
  1474. {
  1475. #ifdef CELP4800
  1476. case WAVE_FORMAT_LH_CELP:
  1477. #endif
  1478. case WAVE_FORMAT_LH_SB8:
  1479. case WAVE_FORMAT_LH_SB12:
  1480. case WAVE_FORMAT_LH_SB16:
  1481. #ifdef CELP4800
  1482. if (uEncodedFormatTag == WAVE_FORMAT_LH_CELP)
  1483. {
  1484. dwMaxBitRate = 4800;
  1485. pCodecData = &(pid->CELP);
  1486. }
  1487. else
  1488. #endif
  1489. if (uEncodedFormatTag == WAVE_FORMAT_LH_SB8)
  1490. {
  1491. dwMaxBitRate = 8000;
  1492. pCodecData = &(pid->SB8);
  1493. }
  1494. else if (uEncodedFormatTag == WAVE_FORMAT_LH_SB12)
  1495. {
  1496. dwMaxBitRate = 12000;
  1497. pCodecData = &(pid->SB12);
  1498. }
  1499. else if (uEncodedFormatTag == WAVE_FORMAT_LH_SB16)
  1500. {
  1501. dwMaxBitRate = 16000;
  1502. pCodecData = &(pid->SB16);
  1503. }
  1504. if (fCompress)
  1505. {
  1506. hAccess = MSLHSB_Open_Coder (dwMaxBitRate);
  1507. pfnConvert = MSLHSB_Encode;
  1508. pfnClose = MSLHSB_Close_Coder;
  1509. }
  1510. else
  1511. {
  1512. hAccess = MSLHSB_Open_Decoder (dwMaxBitRate);
  1513. pfnConvert = MSLHSB_Decode;
  1514. pfnClose = MSLHSB_Close_Decoder;
  1515. cbMaxData = pCodecData->CodecInfo.wCodedBufferSize;
  1516. }
  1517. break;
  1518. }
  1519. if (hAccess == NULL)
  1520. {
  1521. if (pfnClose) (*pfnClose) (hAccess);
  1522. DBGMSG (1, (_T ("%s: open failed, hAccess=0\r\n"), SZFN));
  1523. return ACMERR_NOTPOSSIBLE;
  1524. }
  1525. psi = (PSTREAMINSTANCEDATA) LocalAlloc (LPTR, sizeof (STREAMINSTANCEDATA) + cbMaxData);
  1526. if (psi == NULL)
  1527. {
  1528. DBGMSG (1, (_T ("%s: LocalAlloc failed\r\n"), SZFN));
  1529. if (pfnClose) (*pfnClose) (hAccess);
  1530. return MMSYSERR_NOMEM;
  1531. }
  1532. // fill out our instance structure
  1533. psi->pfnConvert = pfnConvert;
  1534. psi->pfnClose = pfnClose;
  1535. psi->hAccess = hAccess;
  1536. psi->pCodecData = pCodecData;
  1537. psi->fCompress = fCompress;
  1538. psi->dwMaxBitRate = dwMaxBitRate;
  1539. psi->fInit = TRUE;
  1540. // fill in our instance data--this will be passed back to all stream
  1541. // messages in the ACMDRVSTREAMINSTANCE structure. it is entirely
  1542. // up to the driver what gets stored (and maintained) in the
  1543. // fdwDriver and dwDriver members.
  1544. //
  1545. padsi->fdwDriver = 0;
  1546. padsi->dwDriver = (DWORD_PTR) psi;
  1547. return MMSYSERR_NOERROR;
  1548. } // acmdStreamOpen()
  1549. //--------------------------------------------------------------------------;
  1550. //
  1551. // on ACMDM_STREAM_CLOSE
  1552. //
  1553. //--------------------------------------------------------------------------;
  1554. LRESULT FAR PASCAL acmdStreamClose
  1555. (
  1556. PINSTANCEDATA pid,
  1557. LPACMDRVSTREAMINSTANCE padsi
  1558. )
  1559. {
  1560. PSTREAMINSTANCEDATA psi;
  1561. FUNCTION_ENTRY ("acmdStreamClose")
  1562. //
  1563. // the driver should clean up all privately allocated resources that
  1564. // were created for maintaining the stream instance. if no resources
  1565. // were allocated, then simply succeed.
  1566. //
  1567. // in the case of this driver, we need to free the stream instance
  1568. // structure that we allocated during acmdStreamOpen.
  1569. //
  1570. psi = (PSTREAMINSTANCEDATA) padsi->dwDriver;
  1571. if (psi)
  1572. {
  1573. if (psi->fInit && psi->hAccess && psi->pfnClose)
  1574. {
  1575. (*(psi->pfnClose)) (psi->hAccess);
  1576. LocalFree ((HLOCAL) psi);
  1577. }
  1578. } // if (psi)
  1579. return MMSYSERR_NOERROR;
  1580. } // acmdStreamClose()
  1581. //--------------------------------------------------------------------------;
  1582. //
  1583. // LRESULT FAR PASCAL acmdStreamSize
  1584. //
  1585. // Description:
  1586. // This function handles the ACMDM_STREAM_SIZE message. The purpose
  1587. // of this function is to provide the _largest size in bytes_ that
  1588. // the source or destination buffer needs to be given the input and
  1589. // output formats and the size in bytes of the source or destination
  1590. // data buffer.
  1591. //
  1592. // In other words: how big does my destination buffer need to be to
  1593. // hold the converted data? (ACM_STREAMSIZEF_SOURCE)
  1594. //
  1595. // Or: how big can my source buffer be given the destination buffer?
  1596. // (ACM_STREAMSIZEF_DESTINATION)
  1597. //
  1598. // Arguments:
  1599. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1600. // conversion stream. This structure was allocated by the ACM and
  1601. // filled with the most common instance data needed for conversions.
  1602. // The information in this structure is exactly the same as it was
  1603. // during the ACMDM_STREAM_OPEN message--so it is not necessary
  1604. // to re-verify the information referenced by this structure.
  1605. //
  1606. // LPACMDRVSTREAMSIZE padss: Specifies a pointer to the ACMDRVSTREAMSIZE
  1607. // structure that defines the conversion stream size query attributes.
  1608. //
  1609. // Return (LRESULT):
  1610. // The return value is zero (MMSYSERR_NOERROR) if this function
  1611. // succeeds with no errors. The return value is a non-zero error code
  1612. // if the function fails.
  1613. //
  1614. // An ACM driver should return MMSYSERR_NOTSUPPORTED if a query type
  1615. // is requested that the driver does not understand. Note that a driver
  1616. // must support both the ACM_STREAMSIZEF_DESTINATION and
  1617. // ACM_STREAMSIZEF_SOURCE queries.
  1618. //
  1619. // If the conversion would be 'out of range' given the input arguments,
  1620. // then ACMERR_NOTPOSSIBLE should be returned.
  1621. //
  1622. //--------------------------------------------------------------------------;
  1623. // #define GetBytesPerBlock(nSamplesPerSec, wBitsPerSample) (RT24_SAMPLESPERBLOCK8 * (wBitsPerSample) >> 3)
  1624. LRESULT FAR PASCAL acmdStreamSize
  1625. (
  1626. LPACMDRVSTREAMINSTANCE padsi,
  1627. LPACMDRVSTREAMSIZE padss
  1628. )
  1629. {
  1630. LPWAVEFORMATEX pwfxSrc;
  1631. LPWAVEFORMATEX pwfxDst;
  1632. DWORD cBlocks;
  1633. DWORD cbSrcLength;
  1634. DWORD cbDstLength;
  1635. WORD wPCMBufferSize;
  1636. WORD wCodedBufferSize;
  1637. PSTREAMINSTANCEDATA psi;
  1638. FUNCTION_ENTRY ("acmdStreamSize")
  1639. psi = (PSTREAMINSTANCEDATA) padsi->dwDriver;
  1640. if (psi == NULL) return ACMERR_NOTPOSSIBLE;
  1641. wPCMBufferSize = psi->pCodecData->CodecInfo.wPCMBufferSize;
  1642. wCodedBufferSize = psi->pCodecData->CodecInfo.wCodedBufferSize;
  1643. cbSrcLength = padss->cbSrcLength;
  1644. cbDstLength = padss->cbDstLength;
  1645. pwfxSrc = padsi->pwfxSrc;
  1646. pwfxDst = padsi->pwfxDst;
  1647. switch (ACM_STREAMSIZEF_QUERYMASK & padss->fdwSize)
  1648. {
  1649. case ACM_STREAMSIZEF_SOURCE:
  1650. if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
  1651. {
  1652. switch (pwfxDst->wFormatTag)
  1653. {
  1654. #ifdef CELP4800
  1655. case WAVE_FORMAT_LH_CELP:
  1656. // src pcm -> dst lh celp
  1657. #endif
  1658. case WAVE_FORMAT_LH_SB8:
  1659. // src pcm -> dst lh sb8
  1660. case WAVE_FORMAT_LH_SB12:
  1661. // src pcm -> dst lh sb12
  1662. case WAVE_FORMAT_LH_SB16:
  1663. // src pcm -> dst lh sb16
  1664. cBlocks = cbSrcLength / wPCMBufferSize;
  1665. if (cBlocks == 0) return ACMERR_NOTPOSSIBLE;
  1666. if (cBlocks * wPCMBufferSize < cbSrcLength) cBlocks++;
  1667. padss->cbDstLength = cBlocks * wCodedBufferSize;
  1668. break;
  1669. }
  1670. }
  1671. else
  1672. {
  1673. switch (pwfxSrc->wFormatTag)
  1674. {
  1675. #ifdef CELP4800
  1676. case WAVE_FORMAT_LH_CELP:
  1677. // src lh celp -> dst pcm
  1678. cBlocks = cbSrcLength / wCodedBufferSize;
  1679. if (cBlocks == 0) return ACMERR_NOTPOSSIBLE;
  1680. if (cBlocks * wCodedBufferSize < cbSrcLength) cBlocks++;
  1681. padss->cbDstLength = cBlocks * wPCMBufferSize;
  1682. break;
  1683. #endif
  1684. case WAVE_FORMAT_LH_SB8:
  1685. // src lh sb8 -> dst pcm
  1686. case WAVE_FORMAT_LH_SB12:
  1687. // src lh sb12 -> dst pcm
  1688. case WAVE_FORMAT_LH_SB16:
  1689. // src lh sb16 -> dst pcm
  1690. padss->cbDstLength = cbSrcLength * wPCMBufferSize;
  1691. break;
  1692. }
  1693. }
  1694. return MMSYSERR_NOERROR;
  1695. case ACM_STREAMSIZEF_DESTINATION:
  1696. if (pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
  1697. {
  1698. switch (pwfxSrc->wFormatTag)
  1699. {
  1700. #ifdef CELP4800
  1701. case WAVE_FORMAT_LH_CELP:
  1702. // src lh celp <- dst pcm
  1703. #endif
  1704. case WAVE_FORMAT_LH_SB8:
  1705. // src lh sb8 <- dst pcm
  1706. case WAVE_FORMAT_LH_SB12:
  1707. // src lh sb12 <- dst pcm
  1708. case WAVE_FORMAT_LH_SB16:
  1709. // src lh sb16 <- dst pcm
  1710. cBlocks = cbDstLength / wPCMBufferSize;
  1711. if (cBlocks == 0) return ACMERR_NOTPOSSIBLE;
  1712. padss->cbSrcLength = cBlocks * wCodedBufferSize;
  1713. break;
  1714. }
  1715. }
  1716. else
  1717. {
  1718. switch (pwfxDst->wFormatTag)
  1719. {
  1720. #ifdef NEW_ANSWER
  1721. #ifdef CELP4800
  1722. case WAVE_FORMAT_LH_CELP:
  1723. // src pcm <- dst lh celp
  1724. #endif
  1725. case WAVE_FORMAT_LH_SB8:
  1726. // src pcm <- dst lh sb8
  1727. case WAVE_FORMAT_LH_SB12:
  1728. // src pcm <- dst lh sb12
  1729. case WAVE_FORMAT_LH_SB16:
  1730. // src pcm <- dst lh sb16
  1731. cBlocks = cbDstLength / wCodedBufferSize;
  1732. if (cBlocks == 0) return ACMERR_NOTPOSSIBLE;
  1733. padss->cbSrcLength = cBlocks * wPCMBufferSize;
  1734. break;
  1735. #else
  1736. #ifdef CELP4800
  1737. case WAVE_FORMAT_LH_CELP:
  1738. // src pcm <- dst lh celp
  1739. cBlocks = cbDstLength / wCodedBufferSize;
  1740. if (cBlocks == 0) return ACMERR_NOTPOSSIBLE;
  1741. padss->cbSrcLength = cBlocks * wPCMBufferSize;
  1742. break;
  1743. #endif
  1744. case WAVE_FORMAT_LH_SB8:
  1745. // src pcm <- dst lh sb8
  1746. case WAVE_FORMAT_LH_SB12:
  1747. // src pcm <- dst lh sb12
  1748. case WAVE_FORMAT_LH_SB16:
  1749. // src pcm <- dst lh sb16
  1750. padss->cbSrcLength = cbDstLength * wPCMBufferSize;
  1751. break;
  1752. #endif
  1753. }
  1754. }
  1755. return MMSYSERR_NOERROR;
  1756. } // switch()
  1757. return MMSYSERR_NOTSUPPORTED;
  1758. } // acmdStreamSize()
  1759. //--------------------------------------------------------------------------;
  1760. //
  1761. // LRESULT FAR PASCAL acmdStreamConvert
  1762. //
  1763. // Description:
  1764. // This function handles the ACMDM_STREAM_CONVERT message. This is the
  1765. // whole purpose of writing an ACM driver--to convert data. This message
  1766. // is sent after a stream has been opened (the driver receives and
  1767. // succeeds the ACMDM_STREAM_OPEN message).
  1768. //
  1769. // Arguments:
  1770. // HLOCAL pid: Pointer to private ACM driver instance structure.
  1771. // This structure is [optionally] allocated during the DRV_OPEN message
  1772. // which is handled by the acmdDriverOpen function.
  1773. //
  1774. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1775. // conversion stream. This structure was allocated by the ACM and
  1776. // filled with the most common instance data needed for conversions.
  1777. // The information in this structure is exactly the same as it was
  1778. // during the ACMDM_STREAM_OPEN message--so it is not necessary
  1779. // to re-verify the information referenced by this structure.
  1780. //
  1781. // LPACMDRVSTREAMHEADER padsh: Pointer to stream header structure
  1782. // that defines the source data and destination buffer to convert.
  1783. //
  1784. // Return (LRESULT):
  1785. // The return value is zero (MMSYSERR_NOERROR) if this function
  1786. // succeeds with no errors. The return value is a non-zero error code
  1787. // if the function fails.
  1788. //
  1789. //--------------------------------------------------------------------------;
  1790. // We want to use as little stack as possible,
  1791. // So let's make all our local variables statics
  1792. LRESULT FAR PASCAL acmdStreamConvert
  1793. (
  1794. PINSTANCEDATA pid,
  1795. LPACMDRVSTREAMINSTANCE padsi,
  1796. LPACMDRVSTREAMHEADER padsh
  1797. )
  1798. {
  1799. LH_ERRCODE lherr = LH_SUCCESS;
  1800. DWORD dwInBufSize, dwOutBufSize;
  1801. PBYTE pbSrc, pbDst, pData;
  1802. DWORD dwPCMBufferSize, dwCodedBufferSize;
  1803. PSTREAMINSTANCEDATA psi;
  1804. FUNCTION_ENTRY ("acmdStreamConvert")
  1805. // this is a must
  1806. pbDst = padsh->pbDst;
  1807. pbSrc = padsh->pbSrc;
  1808. // zero is a *must*
  1809. padsh->cbSrcLengthUsed = 0;
  1810. padsh->cbDstLengthUsed = 0;
  1811. psi = (PSTREAMINSTANCEDATA) padsi->dwDriver;
  1812. if (psi == NULL) return ACMERR_NOTPOSSIBLE;
  1813. dwPCMBufferSize = (DWORD) psi->pCodecData->CodecInfo.wPCMBufferSize;
  1814. dwCodedBufferSize = (DWORD) psi->pCodecData->CodecInfo.wCodedBufferSize;
  1815. dwInBufSize = (DWORD) padsh->cbSrcLength;
  1816. dwOutBufSize = (DWORD) padsh->cbDstLength;
  1817. DBGMSG (1, (_T ("%s: prior: dwInBufSize=0x%lX, dwOutBufSize=0x%lX\r\n"),
  1818. SZFN, dwInBufSize, dwOutBufSize));
  1819. /////////////////////////////////////////////
  1820. //
  1821. // ENCODING
  1822. //
  1823. if (psi->fCompress)
  1824. {
  1825. while (dwOutBufSize >= dwCodedBufferSize
  1826. &&
  1827. dwInBufSize >= dwPCMBufferSize)
  1828. {
  1829. // ignore the data the codec cannot handle
  1830. // if (dwInBufSize > dwPCMBufferSize) dwInBufSize = dwPCMBufferSize;
  1831. dwInBufSize = dwPCMBufferSize;
  1832. // L&H codecs can only accept word
  1833. if (dwOutBufSize > 0x0FFF0UL) dwOutBufSize = 0x0FFF0UL;
  1834. // encode it
  1835. lherr = (*(psi->pfnConvert)) (psi->hAccess,
  1836. pbSrc, (PWORD) &dwInBufSize,
  1837. pbDst, (PWORD) &dwOutBufSize);
  1838. DBGMSG (1, (_T ("%s: post: dwInBufSize=0x%lX, dwOutBufSize=0x%lX\r\n"),
  1839. SZFN, dwInBufSize, dwOutBufSize));
  1840. if (lherr != LH_SUCCESS)
  1841. {
  1842. DBGMSG (1, (_T ("%s: LH*_**_Encode failed lherr=%ld\r\n"), SZFN, (long) lherr));
  1843. return MMSYSERR_NOTSUPPORTED;
  1844. }
  1845. // return the info about the amount of data used and created
  1846. padsh->cbSrcLengthUsed += dwInBufSize;
  1847. padsh->cbDstLengthUsed += dwOutBufSize;
  1848. // re-compute the buffer sizes
  1849. dwOutBufSize = (DWORD) (padsh->cbDstLength - padsh->cbDstLengthUsed);
  1850. dwInBufSize = (DWORD) (padsh->cbSrcLength - padsh->cbSrcLengthUsed);
  1851. // re-compute the buffer pointers
  1852. pbSrc = padsh->pbSrc + padsh->cbSrcLengthUsed;
  1853. pbDst = padsh->pbDst + padsh->cbDstLengthUsed;
  1854. }
  1855. goto MyExit; // spit out debug message
  1856. }
  1857. /////////////////////////////////////////////
  1858. //
  1859. // DECODING celp
  1860. //
  1861. #ifdef CELP4800
  1862. if (psi->pCodecData->wFormatTag == WAVE_FORMAT_LH_CELP)
  1863. {
  1864. while (dwOutBufSize >= dwPCMBufferSize
  1865. &&
  1866. dwInBufSize >= dwCodedBufferSize)
  1867. {
  1868. // ignore the data that the codec cannot handle
  1869. // if (dwInBufSize > dwCodedBufferSize) dwInBufSize = dwCodedBufferSize;
  1870. dwInBufSize = dwCodedBufferSize;
  1871. // L&H codecs can only accept word
  1872. if (dwOutBufSize > 0x0FFF0UL) dwOutBufSize = 0x0FFF0UL;
  1873. // decode it
  1874. lherr = (*(psi->pfnConvert)) (psi->hAccess,
  1875. pbSrc, (PWORD) &dwInBufSize,
  1876. pbDst, (PWORD) &dwOutBufSize);
  1877. DBGMSG (1, (_T ("%s: post: dwInBufSize=0x%lX, dwOutBufSize=0x%lX\r\n"),
  1878. SZFN, dwInBufSize, dwOutBufSize));
  1879. if (lherr != LH_SUCCESS)
  1880. {
  1881. DBGMSG (1, (_T ("%s: LH*_**_Decode failed lherr=%ld\r\n"), SZFN, (long) lherr));
  1882. return MMSYSERR_NOTSUPPORTED;
  1883. }
  1884. // return the info about the amount of data used and created
  1885. padsh->cbSrcLengthUsed += dwInBufSize;
  1886. padsh->cbDstLengthUsed += dwOutBufSize;
  1887. // re-compute the buffer sizes
  1888. dwOutBufSize = (DWORD) (padsh->cbDstLength - padsh->cbDstLengthUsed);
  1889. dwInBufSize = (DWORD) (padsh->cbSrcLength - padsh->cbSrcLengthUsed);
  1890. // re-compute the buffer pointers
  1891. pbSrc = padsh->pbSrc + padsh->cbSrcLengthUsed;
  1892. pbDst = padsh->pbDst + padsh->cbDstLengthUsed;
  1893. }
  1894. goto MyExit; // spit out debug message
  1895. }
  1896. #endif
  1897. /////////////////////////////////////////////
  1898. //
  1899. // DECODING subbands
  1900. //
  1901. if (pid->wPacketData != LH_PACKET_DATA_FRAMED)
  1902. {
  1903. //
  1904. // general application, such as sndrec32.exe and audcmp.exe
  1905. //
  1906. pData = &(psi->Data[0]); // use local constant
  1907. while (dwOutBufSize >= dwPCMBufferSize
  1908. &&
  1909. dwInBufSize + psi->cbData >= dwCodedBufferSize)
  1910. {
  1911. DBGMSG (1, (_T ("%s: cbData=0x%X\r\n"), SZFN, psi->cbData));
  1912. // fill in the internal buffer as possible
  1913. if (psi->cbData < dwCodedBufferSize)
  1914. {
  1915. // buffer the coded data
  1916. dwInBufSize = dwCodedBufferSize - (DWORD) psi->cbData;
  1917. CopyMemory (&(psi->Data[psi->cbData]), pbSrc, dwInBufSize);
  1918. psi->cbData = (WORD) dwCodedBufferSize;
  1919. padsh->cbSrcLengthUsed += dwInBufSize;
  1920. }
  1921. // reset input buffer size
  1922. dwInBufSize = dwCodedBufferSize;
  1923. // L&H codecs can only accept word
  1924. if (dwOutBufSize > 0x0FFF0UL) dwOutBufSize = 0x0FFF0UL;
  1925. // decode it
  1926. lherr = (*(psi->pfnConvert)) (psi->hAccess,
  1927. pData, (PWORD) &dwInBufSize,
  1928. pbDst, (PWORD) &dwOutBufSize);
  1929. DBGMSG (1, (_T ("%s: post: dwInBufSize=0x%lX, dwOutBufSize=0x%lX\r\n"),
  1930. SZFN, dwInBufSize, dwOutBufSize));
  1931. if (lherr != LH_SUCCESS)
  1932. {
  1933. DBGMSG (1, (_T ("%s: LH*_**_Decode failed lherr=%ld\r\n"), SZFN, (long) lherr));
  1934. return MMSYSERR_NOTSUPPORTED;
  1935. }
  1936. // update the amount of the remaining data
  1937. psi->cbData -= (WORD) dwInBufSize;
  1938. // move the remaining data to the beginning of the internal buffer
  1939. // I should have used MoveMemory, but it is an MSVC runtime call.
  1940. // Use CopyMemory instead, which should be ok because the overlapping
  1941. // portion is copied before being overwritten.
  1942. if (psi->cbData)
  1943. {
  1944. CopyMemory (pData, &(psi->Data[dwInBufSize]), psi->cbData);
  1945. }
  1946. // return the info about the amount of data used and created
  1947. padsh->cbDstLengthUsed += dwOutBufSize;
  1948. // note that cbSrcLengthUsed has been updated already!!!
  1949. // re-compute the buffer sizes
  1950. dwOutBufSize = (DWORD) (padsh->cbDstLength - padsh->cbDstLengthUsed);
  1951. dwInBufSize = (DWORD) (padsh->cbSrcLength - padsh->cbSrcLengthUsed);
  1952. // re-compute the buffer pointers
  1953. pbSrc = padsh->pbSrc + padsh->cbSrcLengthUsed;
  1954. pbDst = padsh->pbDst + padsh->cbDstLengthUsed;
  1955. }
  1956. // accomodate the final left-over bytes
  1957. if (dwInBufSize + psi->cbData < dwCodedBufferSize)
  1958. {
  1959. CopyMemory (&(psi->Data[psi->cbData]), pbSrc, dwInBufSize);
  1960. psi->cbData += (WORD) dwInBufSize;
  1961. padsh->cbSrcLengthUsed += dwInBufSize;
  1962. }
  1963. }
  1964. else
  1965. {
  1966. //
  1967. // special case: datapump's subband packets
  1968. //
  1969. while (dwOutBufSize >= dwPCMBufferSize)
  1970. {
  1971. // hack the input size to be dwCodedBufferSize as required by L&H API
  1972. dwInBufSize = dwCodedBufferSize;
  1973. // L&H codecs can only accept word
  1974. if (dwOutBufSize > 0x0FFF0UL) dwOutBufSize = 0x0FFF0UL;
  1975. DBGMSG (1, (_T ("%s: calling: dwInBufSize=0x%lX, dwOutBufSize=0x%lX\r\n"),
  1976. SZFN, dwInBufSize, dwOutBufSize));
  1977. // decode it
  1978. lherr = (*(psi->pfnConvert)) (psi->hAccess,
  1979. pbSrc, (PWORD) &dwInBufSize,
  1980. pbDst, (PWORD) &dwOutBufSize);
  1981. DBGMSG (1, (_T ("%s: post: dwInBufSize=0x%X, dwOutBufSize=0x%X\r\n"),
  1982. SZFN, dwInBufSize, dwOutBufSize));
  1983. if (lherr != LH_SUCCESS)
  1984. {
  1985. DBGMSG (1, (_T ("%s: LH*_**_Decode failed lherr=%ld\r\n"), SZFN, (long) lherr));
  1986. return MMSYSERR_NOTSUPPORTED;
  1987. }
  1988. // return the info about the amount of data used and created
  1989. padsh->cbSrcLengthUsed += dwInBufSize;
  1990. padsh->cbDstLengthUsed += dwOutBufSize;
  1991. // re-compute the buffer size
  1992. dwOutBufSize = (DWORD) (padsh->cbDstLength - padsh->cbDstLengthUsed);
  1993. // re-compute the buffer pointers
  1994. pbSrc = padsh->pbSrc + padsh->cbSrcLengthUsed;
  1995. pbDst = padsh->pbDst + padsh->cbDstLengthUsed;
  1996. }
  1997. }
  1998. MyExit:
  1999. DBGMSG (1, (_T ("%s: exit: cbSrcLengthUsed=0x%lX, cbDstLengthUsed=0x%lX\r\n"),
  2000. SZFN, (DWORD) padsh->cbSrcLengthUsed, (DWORD) padsh->cbDstLengthUsed));
  2001. return MMSYSERR_NOERROR;
  2002. }
  2003. //--------------------------------------------------------------------------;
  2004. //
  2005. // LRESULT FAR PASCAL DriverProc
  2006. //
  2007. // Description:
  2008. //
  2009. //
  2010. // Arguments:
  2011. // DWORD dwId: For most messages, dwId is the DWORD value that
  2012. // the driver returns in response to a DRV_OPEN message. Each time
  2013. // the driver is opened, through the OpenDriver API, the driver
  2014. // receives a DRV_OPEN message and can return an arbitrary, non-zero
  2015. // value. The installable driver interface saves this value and returns
  2016. // a unique driver handle to the application. Whenever the application
  2017. // sends a message to the driver using the driver handle, the interface
  2018. // routes the message to this entry point and passes the corresponding
  2019. // dwId. This mechanism allows the driver to use the same or different
  2020. // identifiers for multiple opens but ensures that driver handles are
  2021. // unique at the application interface layer.
  2022. //
  2023. // The following messages are not related to a particular open instance
  2024. // of the driver. For these messages, the dwId will always be zero.
  2025. //
  2026. // DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN
  2027. //
  2028. // HDRVR hdrvr: This is the handle returned to the application
  2029. // by the driver interface.
  2030. //
  2031. // UINT uMsg: The requested action to be performed. Message
  2032. // values below DRV_RESERVED are used for globally defined messages.
  2033. // Message values from DRV_RESERVED to DRV_USER are used for defined
  2034. // driver protocols. Messages above DRV_USER are used for driver
  2035. // specific messages.
  2036. //
  2037. // LPARAM lParam1: Data for this message. Defined separately for
  2038. // each message.
  2039. //
  2040. // LPARAM lParam2: Data for this message. Defined separately for
  2041. // each message.
  2042. //
  2043. // Return (LRESULT):
  2044. // Defined separately for each message.
  2045. //
  2046. //--------------------------------------------------------------------------;
  2047. LRESULT CALLBACK DriverProc
  2048. (
  2049. DWORD_PTR dwId,
  2050. HDRVR hdrvr,
  2051. UINT uMsg,
  2052. LPARAM lParam1,
  2053. LPARAM lParam2
  2054. )
  2055. {
  2056. PINSTANCEDATA pid;
  2057. LRESULT dplr;
  2058. FUNCTION_ENTRY ("DriverProc")
  2059. pid = (PINSTANCEDATA)dwId;
  2060. switch (uMsg)
  2061. {
  2062. case DRV_LOAD:
  2063. DBGMSG (1, (_T ("%s: DRV_LOAD\r\n"), SZFN));
  2064. return 1L;
  2065. case DRV_FREE:
  2066. DBGMSG (1, (_T ("%s: DRV_FREE\r\n"), SZFN));
  2067. return 1L; // not that it matters since ACM does not check this return value
  2068. case DRV_OPEN:
  2069. DBGMSG (1, (_T ("%s: DRV_OPEN\r\n"), SZFN));
  2070. return acmdDriverOpen (hdrvr, (LPACMDRVOPENDESC)lParam2);
  2071. case DRV_CLOSE:
  2072. DBGMSG (1, (_T ("%s: DRV_CLOSE\r\n"), SZFN));
  2073. dplr = acmdDriverClose (pid);
  2074. return dplr;
  2075. case DRV_INSTALL:
  2076. DBGMSG (1, (_T ("%s: DRV_INSTALL\r\n"), SZFN));
  2077. return ((LRESULT)DRVCNF_RESTART);
  2078. case DRV_REMOVE:
  2079. DBGMSG (1, (_T ("%s: DRV_REMOVE\r\n"), SZFN));
  2080. return ((LRESULT)DRVCNF_RESTART);
  2081. case DRV_ENABLE:
  2082. DBGMSG (1, (_T ("%s: DRV_ENABLE\r\n"), SZFN));
  2083. return 1L;
  2084. case DRV_DISABLE:
  2085. DBGMSG (1, (_T ("%s: DRV_DISABLE\r\n"), SZFN));
  2086. return 1L;
  2087. case DRV_QUERYCONFIGURE: // Does this driver support configuration?
  2088. DBGMSG (1, (_T ("%s: DRV_QUERYCONFIGURE\r\n"), SZFN));
  2089. lParam1 = -1L;
  2090. lParam2 = 0L;
  2091. // fall through
  2092. case DRV_CONFIGURE:
  2093. DBGMSG (1, (_T ("%s: DRV_CONFIGURE\r\n"), SZFN));
  2094. dplr = acmdDriverConfigure(pid, (HWND)lParam1, (LPDRVCONFIGINFO)lParam2);
  2095. return dplr;
  2096. case ACMDM_DRIVER_DETAILS:
  2097. DBGMSG (1, (_T ("%s: ACMDM_DRIVER_DETAILS\r\n"), SZFN));
  2098. dplr = acmdDriverDetails(pid, (LPACMDRIVERDETAILS)lParam1);
  2099. return dplr;
  2100. case ACMDM_DRIVER_ABOUT:
  2101. DBGMSG (1, (_T ("%s: ACMDM_DRIVER_ABOUT\r\n"), SZFN));
  2102. dplr = acmdDriverAbout(pid, (HWND)lParam1);
  2103. return dplr;
  2104. case ACMDM_FORMAT_SUGGEST:
  2105. DBGMSG (1, (_T ("%s: ACMDM_FORMAT_SUGGEST\r\n"), SZFN));
  2106. dplr = acmdFormatSuggest(pid, (LPACMDRVFORMATSUGGEST)lParam1);
  2107. return dplr;
  2108. case ACMDM_FORMATTAG_DETAILS:
  2109. DBGMSG (1, (_T ("%s: ACMDM_FORMATTAG_DETAILS\r\n"), SZFN));
  2110. dplr = acmdFormatTagDetails(pid, (LPACMFORMATTAGDETAILS)lParam1, lParam2);
  2111. return dplr;
  2112. case ACMDM_FORMAT_DETAILS:
  2113. DBGMSG (1, (_T ("%s: ACMDM_FORMAT_DETAILS\r\n"), SZFN));
  2114. dplr = acmdFormatDetails(pid, (LPACMFORMATDETAILS)lParam1, lParam2);
  2115. return dplr;
  2116. case ACMDM_STREAM_OPEN:
  2117. DBGMSG (1, (_T ("%s: ACMDM_STREAM_OPEN\r\n"), SZFN));
  2118. dplr = acmdStreamOpen(pid, (LPACMDRVSTREAMINSTANCE)lParam1);
  2119. return dplr;
  2120. case ACMDM_STREAM_CLOSE:
  2121. DBGMSG (1, (_T ("%s: ACMDM_STREAM_CLOSE\r\n"), SZFN));
  2122. return acmdStreamClose(pid, (LPACMDRVSTREAMINSTANCE)lParam1);
  2123. case ACMDM_STREAM_SIZE:
  2124. DBGMSG (1, (_T ("%s: ACMDM_STREAM_SIZE\r\n"), SZFN));
  2125. return acmdStreamSize((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMSIZE)lParam2);
  2126. case ACMDM_STREAM_CONVERT:
  2127. DBGMSG (1, (_T ("%s: ACMDM_STREAM_CONVERT\r\n"), SZFN));
  2128. dplr = acmdStreamConvert(pid, (LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMHEADER)lParam2);
  2129. return dplr;
  2130. case ACMDM_STREAM_PREPARE:
  2131. DBGMSG (1, (_T ("%s: ACMDM_STREAM_PREPARE\r\n"), SZFN));
  2132. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2133. case ACMDM_STREAM_UNPREPARE:
  2134. DBGMSG (1, (_T ("%s: ACMDM_STREAM_UNPREPARE\r\n"), SZFN));
  2135. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2136. #if defined (_DEBUG) && 0
  2137. // Trap some extra known messages so our debug output can show them
  2138. case ACMDM_STREAM_RESET:
  2139. DBGMSG (1, (_T ("%s: ACMDM_STREAM_RESET\r\n"), SZFN));
  2140. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2141. case ACMDM_DRIVER_NOTIFY:
  2142. DBGMSG (1, (_T ("%s: ACMDM_DRIVER_NOTIFY\r\n"), SZFN));
  2143. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2144. case DRV_EXITSESSION:
  2145. DBGMSG (1, (_T ("%s: DRV_EXITSESSION\r\n"), SZFN));
  2146. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2147. case DRV_EXITAPPLICATION:
  2148. DBGMSG (1, (_T ("%s: DRV_EXITAPPLICATION\r\n"), SZFN));
  2149. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2150. case DRV_POWER:
  2151. DBGMSG (1, (_T ("%s: DRV_POWER\r\n"), SZFN));
  2152. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2153. #endif
  2154. }
  2155. // if we are executing the following code, then this ACM driver does not
  2156. // handle the message that was sent. there are two ranges of messages
  2157. // we need to deal with:
  2158. //
  2159. // o ACM specific driver messages: if an ACM driver does not answer a
  2160. // message sent in the ACM driver message range, then it must
  2161. // return MMSYSERR_NOTSUPPORTED. this applies to the 'user'
  2162. // range as well (for consistency).
  2163. //
  2164. // o other installable driver messages: if an ACM driver does not
  2165. // answer a message that is NOT in the ACM driver message range,
  2166. // then it must call DefDriverProc and return that result.
  2167. // the exception to this is ACM driver procedures installed as
  2168. // ACM_DRIVERADDF_FUNCTION through acmDriverAdd. in this case,
  2169. // the driver procedure should conform to the ACMDRIVERPROC
  2170. // prototype and also return zero instead of calling DefDriverProc.
  2171. if (uMsg == ACMDM_LH_DATA_PACKAGING)
  2172. {
  2173. if (pid)
  2174. {
  2175. pid->wPacketData = (WORD) lParam1;
  2176. }
  2177. }
  2178. else
  2179. {
  2180. //DBGMSG (1, (_T ("%s: bad uMsg=%d\r\n"), uMsg));
  2181. return MMSYSERR_NOTSUPPORTED;
  2182. }
  2183. return DefDriverProc (dwId, hdrvr, uMsg, lParam1, lParam2);
  2184. } // DriverProc()
  2185. #ifdef _DEBUG
  2186. // CurtSm hack ... don't spew all the time
  2187. UINT DebugLH = 0;
  2188. void FAR CDECL MyDbgPrintf ( LPTSTR lpszFormat, ... )
  2189. {
  2190. static TCHAR buf[1024];
  2191. va_list arglist;
  2192. if (!DebugLH)
  2193. return;
  2194. va_start(arglist, lpszFormat);
  2195. wvsprintf ((LPTSTR) buf, (LPCSTR)lpszFormat,
  2196. #if 0
  2197. (LPSTR) (((LPBYTE) &lpszFormat) + sizeof (lpszFormat)));
  2198. #else
  2199. arglist);
  2200. #endif
  2201. OutputDebugString ((LPTSTR) buf);
  2202. }
  2203. #endif //...def _DEBUG
  2204.