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.

2556 lines
78 KiB

  1. //==========================================================================;
  2. //
  3. // codec.c
  4. //
  5. // Copyright (c) 1992-1999 Microsoft Corporation
  6. //
  7. // Description:
  8. //
  9. //
  10. // History:
  11. //
  12. //==========================================================================;
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #include <mmsystem.h>
  16. #include <mmddk.h>
  17. #include <mmreg.h>
  18. #include <ctype.h>
  19. #include <msacm.h>
  20. #include <msacmdrv.h>
  21. #include "codec.h"
  22. #include "msadpcm.h"
  23. #include "debug.h"
  24. #define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0]))
  25. const UINT gauFormatTagIndexToTag[] =
  26. {
  27. WAVE_FORMAT_PCM,
  28. WAVE_FORMAT_ADPCM
  29. };
  30. #define CODEC_MAX_FORMAT_TAGS SIZEOF_ARRAY(gauFormatTagIndexToTag)
  31. #define CODEC_MAX_FILTER_TAGS 0
  32. //
  33. // array of sample rates supported
  34. //
  35. //
  36. const UINT gauFormatIndexToSampleRate[] =
  37. {
  38. 8000,
  39. 11025,
  40. 22050,
  41. 44100
  42. };
  43. #define CODEC_MAX_SAMPLE_RATES SIZEOF_ARRAY(gauFormatIndexToSampleRate)
  44. //
  45. // array of bits per sample supported
  46. //
  47. //
  48. const UINT gauFormatIndexToBitsPerSample[] =
  49. {
  50. 8,
  51. 16
  52. };
  53. #define CODEC_MAX_BITSPERSAMPLE_PCM SIZEOF_ARRAY(gauFormatIndexToBitsPerSample)
  54. #define CODEC_MAX_BITSPERSAMPLE_ADPCM 1
  55. #define CODEC_MAX_CHANNELS MSADPCM_MAX_CHANNELS
  56. //
  57. // number of formats we enumerate per channels is number of sample rates
  58. // times number of channels times number of
  59. // (bits per sample) types.
  60. //
  61. #define CODEC_MAX_FORMATS_PCM (CODEC_MAX_SAMPLE_RATES * \
  62. CODEC_MAX_CHANNELS * \
  63. CODEC_MAX_BITSPERSAMPLE_PCM)
  64. #define CODEC_MAX_FORMATS_ADPCM (CODEC_MAX_SAMPLE_RATES * \
  65. CODEC_MAX_CHANNELS * \
  66. CODEC_MAX_BITSPERSAMPLE_ADPCM)
  67. //==========================================================================;
  68. //
  69. //
  70. //
  71. //
  72. //==========================================================================;
  73. //--------------------------------------------------------------------------;
  74. //
  75. // int LoadStringCodec
  76. //
  77. // Description:
  78. // This function should be used by all codecs to load resource strings
  79. // which will be passed back to the ACM. It works correctly for all
  80. // platforms, as follows:
  81. //
  82. // Win16: Compiled to LoadString to load ANSI strings.
  83. //
  84. // Win32: The 32-bit ACM always expects Unicode strings. Therefore,
  85. // when UNICODE is defined, this function is compiled to
  86. // LoadStringW to load a Unicode string. When UNICODE is
  87. // not defined, this function loads an ANSI string, converts
  88. // it to Unicode, and returns the Unicode string to the
  89. // codec.
  90. //
  91. // Note that you may use LoadString for other strings (strings which
  92. // will not be passed back to the ACM), because these strings will
  93. // always be consistent with the definition of UNICODE.
  94. //
  95. // Arguments:
  96. // Same as LoadString, except that it expects an LPSTR for Win16 and a
  97. // LPWSTR for Win32.
  98. //
  99. // Return (int):
  100. // Same as LoadString.
  101. //
  102. //--------------------------------------------------------------------------;
  103. #ifndef WIN32
  104. #define LoadStringCodec LoadString
  105. #else
  106. #ifdef UNICODE
  107. #define LoadStringCodec LoadStringW
  108. #else
  109. int FNGLOBAL LoadStringCodec
  110. (
  111. HINSTANCE hinst,
  112. UINT uID,
  113. LPWSTR lpwstr,
  114. int cch)
  115. {
  116. LPSTR lpstr;
  117. int iReturn;
  118. lpstr = (LPSTR)GlobalAlloc(GPTR, cch);
  119. if (NULL == lpstr)
  120. {
  121. return 0;
  122. }
  123. iReturn = LoadStringA(hinst, uID, lpstr, cch);
  124. if (0 == iReturn)
  125. {
  126. if (0 != cch)
  127. {
  128. lpwstr[0] = '\0';
  129. }
  130. }
  131. else
  132. {
  133. MultiByteToWideChar( GetACP(), 0, lpstr, cch, lpwstr, cch );
  134. }
  135. GlobalFree((HGLOBAL)lpstr);
  136. return iReturn;
  137. }
  138. #endif // UNICODE
  139. #endif // WIN32
  140. //==========================================================================;
  141. //
  142. //
  143. //
  144. //
  145. //==========================================================================;
  146. //--------------------------------------------------------------------------;
  147. //
  148. // BOOL pcmIsValidFormat
  149. //
  150. // Description:
  151. // This function verifies that a wave format header is a valid PCM
  152. // header that our PCM converter can deal with.
  153. //
  154. // Arguments:
  155. // LPWAVEFORMATEX pwfx: Pointer to format header to verify.
  156. //
  157. // Return (BOOL):
  158. // The return value is non-zero if the format header looks valid. A
  159. // zero return means the header is not valid.
  160. //
  161. // History:
  162. // 11/21/92 cjp [curtisp]
  163. //
  164. //--------------------------------------------------------------------------;
  165. BOOL FNLOCAL pcmIsValidFormat
  166. (
  167. LPWAVEFORMATEX pwfx
  168. )
  169. {
  170. UINT uBlockAlign;
  171. if (!pwfx)
  172. return (FALSE);
  173. if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
  174. return (FALSE);
  175. if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
  176. return (FALSE);
  177. if ((pwfx->nChannels < 1) || (pwfx->nChannels > MSADPCM_MAX_CHANNELS))
  178. return (FALSE);
  179. //
  180. // now verify that the block alignment is correct..
  181. //
  182. uBlockAlign = PCM_BLOCKALIGNMENT(pwfx);
  183. if (uBlockAlign != (UINT)pwfx->nBlockAlign)
  184. return (FALSE);
  185. //
  186. // finally, verify that avg bytes per second is correct
  187. //
  188. if ((pwfx->nSamplesPerSec * uBlockAlign) != pwfx->nAvgBytesPerSec)
  189. return (FALSE);
  190. return (TRUE);
  191. } // pcmIsValidFormat()
  192. //--------------------------------------------------------------------------;
  193. //
  194. // WORD adpcmBlockAlign
  195. //
  196. // Description:
  197. // This function computes the standard block alignment that should
  198. // be used given the WAVEFORMATEX structure.
  199. //
  200. // NOTE! It is _assumed_ that the format is a valid MS-ADPCM format
  201. // and that the following fields in the format structure are valid:
  202. //
  203. // nChannels
  204. // nSamplesPerSec
  205. //
  206. // Arguments:
  207. // LPWAVEFORMATEX pwfx:
  208. //
  209. // Return (WORD):
  210. // The return value is the block alignment that should be placed in
  211. // the pwfx->nBlockAlign field.
  212. //
  213. // History:
  214. // 06/13/93 cjp [curtisp]
  215. //
  216. //--------------------------------------------------------------------------;
  217. WORD FNLOCAL adpcmBlockAlign
  218. (
  219. LPWAVEFORMATEX pwfx
  220. )
  221. {
  222. UINT uBlockAlign;
  223. UINT uChannelShift;
  224. //
  225. //
  226. //
  227. uChannelShift = pwfx->nChannels >> 1;
  228. uBlockAlign = 256 << uChannelShift;
  229. //
  230. // choose a block alignment that makes sense for the sample rate
  231. // that the original PCM data is. basically, this needs to be
  232. // some reasonable number to allow efficient streaming, etc.
  233. //
  234. // don't let block alignment get too small...
  235. //
  236. if (pwfx->nSamplesPerSec > 11025)
  237. {
  238. uBlockAlign *= (UINT)(pwfx->nSamplesPerSec / 11000);
  239. }
  240. return (WORD)(uBlockAlign);
  241. } // adpcmBlockAlign()
  242. //--------------------------------------------------------------------------;
  243. //
  244. // WORD adpcmSamplesPerBlock
  245. //
  246. // Description:
  247. // This function computes the Samples Per Block that should be used
  248. // given the WAVEFORMATEX structure.
  249. //
  250. // NOTE! It is _assumed_ that the format is a valid MS-ADPCM format
  251. // and that the following fields in the format structure are valid:
  252. //
  253. // nChannels = must be 1 or 2!
  254. // nSamplesPerSec
  255. // nBlockAlign
  256. //
  257. // Arguments:
  258. // LPWAVEFORMATEX pwfx:
  259. //
  260. // Return (DWORD):
  261. // The return value is the average bytes per second that should be
  262. // placed in the pwfx->nAvgBytesPerSec field.
  263. //
  264. // History:
  265. // 06/13/93 cjp [curtisp]
  266. //
  267. //--------------------------------------------------------------------------;
  268. WORD FNLOCAL adpcmSamplesPerBlock
  269. (
  270. LPWAVEFORMATEX pwfx
  271. )
  272. {
  273. UINT uSamplesPerBlock;
  274. UINT uChannelShift;
  275. UINT uHeaderBytes;
  276. UINT uBitsPerSample;
  277. //
  278. //
  279. //
  280. uChannelShift = pwfx->nChannels >> 1;
  281. uHeaderBytes = 7 << uChannelShift;
  282. uBitsPerSample = MSADPCM_BITS_PER_SAMPLE << uChannelShift;
  283. //
  284. //
  285. //
  286. uSamplesPerBlock = (pwfx->nBlockAlign - uHeaderBytes) * 8;
  287. uSamplesPerBlock /= uBitsPerSample;
  288. uSamplesPerBlock += 2;
  289. return (WORD)(uSamplesPerBlock);
  290. } // adpcmSamplesPerBlock()
  291. //--------------------------------------------------------------------------;
  292. //
  293. // UINT adpcmAvgBytesPerSec
  294. //
  295. // Description:
  296. // This function computes the Average Bytes Per Second that should
  297. // be used given the WAVEFORMATEX structure.
  298. //
  299. // NOTE! It is _assumed_ that the format is a valid MS-ADPCM format
  300. // and that the following fields in the format structure are valid:
  301. //
  302. // nChannels = must be 1 or 2!
  303. // nSamplesPerSec
  304. // nBlockAlign
  305. //
  306. // Arguments:
  307. // LPWAVEFORMATEX pwfx:
  308. //
  309. // Return (DWORD):
  310. // The return value is the average bytes per second that should be
  311. // placed in the pwfx->nAvgBytesPerSec field.
  312. //
  313. // History:
  314. // 06/13/93 cjp [curtisp]
  315. //
  316. //--------------------------------------------------------------------------;
  317. DWORD FNLOCAL adpcmAvgBytesPerSec
  318. (
  319. LPWAVEFORMATEX pwfx
  320. )
  321. {
  322. DWORD dwAvgBytesPerSec;
  323. UINT uSamplesPerBlock;
  324. //
  325. //
  326. //
  327. uSamplesPerBlock = adpcmSamplesPerBlock(pwfx);
  328. //
  329. // compute bytes per second including header bytes
  330. //
  331. dwAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) /
  332. uSamplesPerBlock;
  333. return (dwAvgBytesPerSec);
  334. } // adpcmAvgBytesPerSec()
  335. //--------------------------------------------------------------------------;
  336. //
  337. // BOOL adpcmIsValidFormat
  338. //
  339. // Description:
  340. //
  341. //
  342. // Arguments:
  343. //
  344. //
  345. // Return (BOOL FNLOCAL):
  346. //
  347. //
  348. // History:
  349. // 1/26/93 cjp [curtisp]
  350. //
  351. //--------------------------------------------------------------------------;
  352. BOOL FNLOCAL adpcmIsValidFormat
  353. (
  354. LPWAVEFORMATEX pwfx
  355. )
  356. {
  357. LPADPCMWAVEFORMAT pwfADPCM = (LPADPCMWAVEFORMAT)pwfx;
  358. if (!pwfx)
  359. return (FALSE);
  360. if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM)
  361. return (FALSE);
  362. //
  363. // check wBitsPerSample
  364. //
  365. if (pwfx->wBitsPerSample != MSADPCM_BITS_PER_SAMPLE)
  366. return (FALSE);
  367. //
  368. // check channels
  369. //
  370. if ((pwfx->nChannels < 1) || (pwfx->nChannels > MSADPCM_MAX_CHANNELS))
  371. return (FALSE);
  372. //
  373. // verify that there is at least enough space specified in cbSize
  374. // for the extra info for the ADPCM header...
  375. //
  376. if (pwfx->cbSize < MSADPCM_WFX_EXTRA_BYTES)
  377. return (FALSE);
  378. //
  379. // Verifying nBlockAlign and wSamplesPerBlock are consistent.
  380. //
  381. if ( (pwfADPCM->wSamplesPerBlock != adpcmSamplesPerBlock(pwfx)) )
  382. return FALSE;
  383. return (TRUE);
  384. } // adpcmIsValidFormat()
  385. //--------------------------------------------------------------------------;
  386. //
  387. // BOOL adpcmIsMagicFormat
  388. //
  389. // Description:
  390. //
  391. //
  392. // Arguments:
  393. //
  394. //
  395. // Return (BOOL FNLOCAL):
  396. //
  397. //
  398. // History:
  399. // 1/27/93 cjp [curtisp]
  400. //
  401. //--------------------------------------------------------------------------;
  402. BOOL FNLOCAL adpcmIsMagicFormat
  403. (
  404. LPADPCMWAVEFORMAT pwfADPCM
  405. )
  406. {
  407. UINT u;
  408. //
  409. // verify that there is at least enough space specified in cbSize
  410. // for the extra info for the ADPCM header...
  411. //
  412. if (pwfADPCM->wfx.cbSize < MSADPCM_WFX_EXTRA_BYTES)
  413. return (FALSE);
  414. //
  415. // check coef's to see if it is Microsoft's standard ADPCM
  416. //
  417. if (pwfADPCM->wNumCoef != MSADPCM_MAX_COEFFICIENTS)
  418. return (FALSE);
  419. for (u = 0; u < MSADPCM_MAX_COEFFICIENTS; u++)
  420. {
  421. if (pwfADPCM->aCoef[u].iCoef1 != gaiCoef1[u])
  422. return (FALSE);
  423. if (pwfADPCM->aCoef[u].iCoef2 != gaiCoef2[u])
  424. return (FALSE);
  425. }
  426. return (TRUE);
  427. } // adpcmIsMagicFormat()
  428. //==========================================================================;
  429. //
  430. //
  431. //
  432. //
  433. //==========================================================================;
  434. //--------------------------------------------------------------------------;
  435. //
  436. // BOOL adpcmCopyCoefficients
  437. //
  438. // Description:
  439. //
  440. //
  441. // Arguments:
  442. // LPADPCMWAVEFORMAT pwfadpcm:
  443. //
  444. // Return (BOOL):
  445. //
  446. // History:
  447. // 06/13/93 cjp [curtisp]
  448. //
  449. //--------------------------------------------------------------------------;
  450. BOOL FNLOCAL adpcmCopyCoefficients
  451. (
  452. LPADPCMWAVEFORMAT pwfadpcm
  453. )
  454. {
  455. UINT u;
  456. pwfadpcm->wNumCoef = MSADPCM_MAX_COEFFICIENTS;
  457. for (u = 0; u < MSADPCM_MAX_COEFFICIENTS; u++)
  458. {
  459. pwfadpcm->aCoef[u].iCoef1 = (short)gaiCoef1[u];
  460. pwfadpcm->aCoef[u].iCoef2 = (short)gaiCoef2[u];
  461. }
  462. return (TRUE);
  463. } // adpcmCopyCoefficients()
  464. //==========================================================================;
  465. //
  466. //
  467. //
  468. //
  469. //==========================================================================;
  470. //--------------------------------------------------------------------------;
  471. //
  472. // LRESULT acmdDriverOpen
  473. //
  474. // Description:
  475. // This function is used to handle the DRV_OPEN message for the ACM
  476. // driver. The driver is 'opened' for many reasons with the most common
  477. // being in preperation for conversion work. It is very important that
  478. // the driver be able to correctly handle multiple open driver
  479. // instances.
  480. //
  481. // Read the comments for this function carefully!
  482. //
  483. // Note that multiple _streams_ can (and will) be opened on a single
  484. // open _driver instance_. Do not store/create instance data that must
  485. // be unique for each stream in this function. See the acmdStreamOpen
  486. // function for information on conversion streams.
  487. //
  488. // Arguments:
  489. // HDRVR hdrvr: Driver handle that will be returned to caller of the
  490. // OpenDriver function. Normally, this will be the ACM--but this is
  491. // not guaranteed. For example, if an ACM driver is implemented within
  492. // a waveform driver, then the driver will be opened by both MMSYSTEM
  493. // and the ACM.
  494. //
  495. // LPACMDRVOPENDESC paod: Open description defining how the ACM driver
  496. // is being opened. This argument may be NULL--see the comments below
  497. // for more information.
  498. //
  499. // Return (LRESULT):
  500. // The return value is non-zero if the open is successful. A zero
  501. // return signifies that the driver cannot be opened.
  502. //
  503. //--------------------------------------------------------------------------;
  504. LRESULT FNLOCAL acmdDriverOpen
  505. (
  506. HDRVR hdrvr,
  507. LPACMDRVOPENDESC paod
  508. )
  509. {
  510. PCODECINST pci;
  511. //
  512. // the [optional] open description that is passed to this driver can
  513. // be from multiple 'managers.' for example, AVI looks for installable
  514. // drivers that are tagged with 'vidc' and 'vcap'. we need to verify
  515. // that we are being opened as an Audio Compression Manager driver.
  516. //
  517. // if paod is NULL, then the driver is being opened for some purpose
  518. // other than converting (that is, there will be no stream open
  519. // requests for this instance of being opened). the most common case
  520. // of this is the Control Panel's Drivers option checking for config
  521. // support (DRV_[QUERY]CONFIGURE).
  522. //
  523. // we want to succeed this open, but be able to know that this
  524. // open instance is bogus for creating streams. for this purpose we
  525. // leave most of the members of our instance structure that we
  526. // allocate below as zero...
  527. //
  528. if (NULL != paod)
  529. {
  530. //
  531. // refuse to open if we are not being opened as an ACM driver.
  532. // note that we do NOT modify the value of paod->dwError in this
  533. // case.
  534. //
  535. if (ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC != paod->fccType)
  536. {
  537. return (0L);
  538. }
  539. }
  540. //
  541. // we are being opened as an installable driver--we can allocate some
  542. // instance data to be returned in dwId argument of the DriverProc;
  543. // or simply return non-zero to succeed the open.
  544. //
  545. // this driver allocates a small instance structure. note that we
  546. // rely on allocating the memory as zero-initialized!
  547. //
  548. pci = (PCODECINST)LocalAlloc(LPTR, sizeof(*pci));
  549. if (NULL == pci)
  550. {
  551. //
  552. // if this open attempt was as an ACM driver, then return the
  553. // reason we are failing in the open description structure..
  554. //
  555. if (NULL != paod)
  556. {
  557. paod->dwError = MMSYSERR_NOMEM;
  558. }
  559. //
  560. // fail to open
  561. //
  562. return (0L);
  563. }
  564. //
  565. // fill in our instance structure... note that this instance data
  566. // can be anything that the ACM driver wishes to maintain the
  567. // open driver instance. this data should not contain any information
  568. // that must be maintained per open stream since multiple streams
  569. // can be opened on a single driver instance.
  570. //
  571. // also note that we do _not_ check the version of the ACM opening
  572. // us (paod->dwVersion) to see if it is at least new enough to work
  573. // with this driver (for example, if this driver required Version 3.0
  574. // of the ACM and a Version 2.0 installation tried to open us). the
  575. // reason we do not fail is to allow the ACM to get the driver details
  576. // which contains the version of the ACM that is _required_ by this
  577. // driver. the ACM will examine that value (in padd->vdwACM) and
  578. // do the right thing for this driver... like not load it and inform
  579. // the user of the problem.
  580. //
  581. pci->hdrvr = hdrvr;
  582. pci->hinst = GetDriverModuleHandle(hdrvr); // Module handle.
  583. if (NULL != paod)
  584. {
  585. pci->DriverProc = NULL;
  586. pci->fccType = paod->fccType;
  587. pci->vdwACM = paod->dwVersion;
  588. pci->dwFlags = paod->dwFlags;
  589. paod->dwError = MMSYSERR_NOERROR;
  590. }
  591. //
  592. // non-zero return is success for DRV_OPEN
  593. //
  594. return ((LRESULT)pci);
  595. } // acmdDriverOpen()
  596. //--------------------------------------------------------------------------;
  597. //
  598. // LRESULT acmdDriverClose
  599. //
  600. // Description:
  601. // This function handles the DRV_CLOSE message for the codec. The
  602. // codec receives a DRV_CLOSE message for each succeeded DRV_OPEN
  603. // message (see acmdDriverOpen).
  604. //
  605. // Arguments:
  606. // PCODECINST pci: Pointer to private codec instance structure.
  607. //
  608. // Return (LRESULT):
  609. // The return value is non-zero if the open instance can be closed.
  610. // A zero return signifies that the codec instance could not be
  611. // closed.
  612. //
  613. // NOTE! It is _strongly_ recommended that the codec never fail to
  614. // close.
  615. //
  616. // History:
  617. // 11/28/92 cjp [curtisp]
  618. //
  619. //--------------------------------------------------------------------------;
  620. LRESULT FNLOCAL acmdDriverClose
  621. (
  622. PCODECINST pci
  623. )
  624. {
  625. //
  626. // check to see if we allocated instance data. if we did not, then
  627. // immediately succeed.
  628. //
  629. if (pci != NULL)
  630. {
  631. //
  632. // close down the conversion instance. this codec simply needs
  633. // to free the instance data structure...
  634. //
  635. LocalFree((HLOCAL)pci);
  636. }
  637. //
  638. // non-zero return is success for DRV_CLOSE
  639. //
  640. return (1L);
  641. } // acmdDriverClose()
  642. //--------------------------------------------------------------------------;
  643. //
  644. // LRESULT acmdDriverConfigure
  645. //
  646. // Description:
  647. // This function is called to handle the DRV_[QUERY]CONFIGURE messages.
  648. // These messages are for 'hardware configuration' support of the
  649. // codec. That is, a dialog should be displayed to configure ports,
  650. // IRQ's, memory mappings, etc if it needs to.
  651. //
  652. // The most common way that these messages are generated under Win 3.1
  653. // and NT Product 1 is from the Control Panel's Drivers option. Other
  654. // sources may generate these messages in future versions of Windows.
  655. //
  656. // Arguments:
  657. // PCODECINST pci: Pointer to private codec instance structure.
  658. //
  659. // HWND hwnd: Handle to parent window to use when displaying hardware
  660. // configuration dialog box. A codec is _required_ to display a modal
  661. // dialog box using this hwnd argument as the parent. This argument
  662. // may be (HWND)-1 which tells the codec that it is only being
  663. // queried for configuration support.
  664. //
  665. // LPDRVCONFIGINFO pdci: Pointer to optional DRVCONFIGINFO structure.
  666. // If this argument is NULL, then the codec should invent its own
  667. // storage location.
  668. //
  669. // Return (LRESULT):
  670. // A non-zero return values specifies that either configuration is
  671. // supported or that the dialog was successfully displayed and
  672. // dismissed. A zero return indicates either configuration is not
  673. // supported or some other failure.
  674. //
  675. // History:
  676. // 1/25/93 cjp [curtisp]
  677. //
  678. //--------------------------------------------------------------------------;
  679. LRESULT FNLOCAL acmdDriverConfigure
  680. (
  681. PCODECINST pci,
  682. HWND hwnd,
  683. LPDRVCONFIGINFO pdci
  684. )
  685. {
  686. //
  687. // first check to see if we are only being queried for hardware
  688. // configuration support. if hwnd == (HWND)-1 then we are being
  689. // queried and should return zero for 'not supported' and non-zero
  690. // for 'supported'.
  691. //
  692. if (hwnd == (HWND)-1)
  693. {
  694. //
  695. // this codec does not support hardware configuration so return
  696. // zero...
  697. //
  698. return (0L);
  699. }
  700. //
  701. // we are being asked to bring up our hardware configuration dialog.
  702. // if this codec can bring up a dialog box, then after the dialog
  703. // is dismissed we return non-zero. if we are not able to display a
  704. // dialog, then return zero.
  705. //
  706. return (0L);
  707. } // acmdDriverConfigure()
  708. //--------------------------------------------------------------------------;
  709. //
  710. // LRESULT acmdDriverDetails
  711. //
  712. // Description:
  713. // This function handles the ACMDM_DRIVER_DETAILS message. The codec
  714. // is responsible for filling in the ACMDRIVERDETAILS structure with
  715. // various information.
  716. //
  717. // NOTE! It is *VERY* important that you fill in your ACMDRIVERDETAILS
  718. // structure correctly. The ACM and applications must be able to
  719. // rely on this information.
  720. //
  721. // WARNING! The _reserved_ bits of any fields of the ACMDRIVERDETAILS
  722. // structure are _exactly that_: RESERVED. Do NOT use any extra
  723. // flag bits, etc. for custom information. The proper way to add
  724. // custom capabilities to your codec is this:
  725. //
  726. // o define a new message in the ACMDM_USER range.
  727. //
  728. // o an application that wishes to use one of these extra features
  729. // should then:
  730. //
  731. // o open the codec with acmConverterOpen.
  732. //
  733. // o check for the proper uMid and uPid using acmConverterInfo
  734. //
  735. // o send the 'user defined' message with acmConverterMessage
  736. // to retrieve additional information, etc.
  737. //
  738. // o close the codec with acmConverterClose.
  739. //
  740. // Arguments:
  741. // PCODECINST pci: Pointer to private codec instance structure.
  742. //
  743. // LPACMDRIVERDETAILS padd: Pointer to ACMDRIVERDETAILS structure to fill in
  744. // for caller. This structure may be larger or smaller than the
  745. // current definition of ACMDRIVERDETAILS--cbStruct specifies the valid
  746. // size.
  747. //
  748. // Return (LRESULT):
  749. // The return value is zero (MMSYSERR_NOERROR) for success. A non-zero
  750. // return signifies an error which is either an MMSYSERR_* or an
  751. // ACMERR_*.
  752. //
  753. // Note that this function should never fail. There are two possible
  754. // error conditions:
  755. //
  756. // o if padd is NULL or an invalid pointer.
  757. //
  758. // o if cbStruct is less than four; in this case, there is not enough
  759. // room to return the number of bytes filled in.
  760. //
  761. // Because these two error conditions are easily defined, the ACM
  762. // will catch these errors. The codec does not need to check for these
  763. // conditions.
  764. //
  765. // History:
  766. // 1/23/93 cjp [curtisp]
  767. //
  768. //--------------------------------------------------------------------------;
  769. LRESULT FNLOCAL acmdDriverDetails
  770. (
  771. PCODECINST pci,
  772. LPACMDRIVERDETAILS padd
  773. )
  774. {
  775. ACMDRIVERDETAILS add;
  776. DWORD cbStruct;
  777. //
  778. // it is easiest to fill in a temporary structure with valid info
  779. // and then copy the requested number of bytes to the destination
  780. // buffer.
  781. //
  782. cbStruct = min(padd->cbStruct, sizeof(ACMDRIVERDETAILS));
  783. add.cbStruct = cbStruct;
  784. //
  785. // for the current implementation of an ACM codec, the fccType and
  786. // fccComp members *MUST* always be ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC ('audc')
  787. // and ACMDRIVERDETAILS_FCCCOMP_UNDEFINED (0) respectively.
  788. //
  789. add.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
  790. add.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
  791. //
  792. // the manufacturer id (uMid) and product id (uPid) must be filled
  793. // in with your company's _registered_ id's. for more information
  794. // on these id's and how to get them registered contact Microsoft
  795. // and get the Multimedia Developer Registration Kit:
  796. //
  797. // Microsoft Corporation
  798. // Multimedia Systems Group
  799. // Product Marketing
  800. // One Microsoft Way
  801. // Redmond, WA 98052-6399
  802. //
  803. // Phone: 800-227-4679 x11771
  804. //
  805. // note that during the development phase or your codec, you may
  806. // use the reserved value of '0' for both uMid and uPid.
  807. //
  808. add.wMid = MM_MICROSOFT;
  809. add.wPid = MM_MSFT_ACM_MSADPCM;
  810. //
  811. // the vdwACM and vdwDriver members contain version information for
  812. // the driver.
  813. //
  814. // vdwACM must contain the version of the *ACM* that the codec was
  815. // designed for.
  816. //
  817. // vdwDriver is the version of the driver.
  818. //
  819. add.vdwACM = VERSION_MSACM;
  820. add.vdwDriver = VERSION_CODEC;
  821. //
  822. // the following flags are used to specify the type of conversion(s)
  823. // that the converter/codec/filter supports. these are placed in the
  824. // fdwSupport field of the ACMDRIVERDETAILS structure. note that a converter
  825. // can support one or more of these flags in any combination.
  826. //
  827. // ACMDRIVERDETAILS_SUPPORTF_CODEC: this flag is set if the converter supports
  828. // conversions from one format tag to another format tag. for example,
  829. // if a converter compresses WAVE_FORMAT_PCM to WAVE_FORMAT_ADPCM, then
  830. // this bit should be set.
  831. //
  832. // ACMDRIVERDETAILS_SUPPORTF_CONVERTER: this flags is set if the converter
  833. // supports conversions on the same format tag. as an example, the PCM
  834. // converter that is built into the ACM sets this bit (and only this
  835. // bit) because it converts only PCM formats (bits, sample rate).
  836. //
  837. // ACMDRIVERDETAILS_SUPPORTF_FILTER: this flag is set if the converter supports
  838. // 'in place' transformations on a single format tag without changing
  839. // the size of the resulting data. for example, a converter that changed
  840. // the 'volume' of PCM data would set this bit. note that this is a
  841. // _destructive_ action--but it saves memory, etc.
  842. //
  843. // this converter only supports compression and decompression.
  844. //
  845. add.fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  846. //
  847. // Return the number of format tags this converter supports
  848. // (In the case of PCM only this is 1)
  849. //
  850. add.cFormatTags = CODEC_MAX_FORMAT_TAGS;
  851. //
  852. // Return the number of filter tags this converter supports
  853. // (In the case of a codec (only) it is 0)
  854. //
  855. add.cFilterTags = CODEC_MAX_FILTER_TAGS;
  856. //
  857. // the remaining members in the ACMDRIVERDETAILS structure are sometimes
  858. // not needed. because of this we make a quick check to see if we
  859. // should go through the effort of filling in these members.
  860. //
  861. if (FIELD_OFFSET(ACMDRIVERDETAILS, hicon) < cbStruct)
  862. {
  863. //
  864. // this codec has no custom icon
  865. //
  866. add.hicon = NULL;
  867. LoadStringCodec(pci->hinst, IDS_CODEC_SHORTNAME, add.szShortName, SIZEOFACMSTR(add.szShortName));
  868. LoadStringCodec(pci->hinst, IDS_CODEC_LONGNAME, add.szLongName, SIZEOFACMSTR(add.szLongName));
  869. if (FIELD_OFFSET(ACMDRIVERDETAILS, szCopyright) < cbStruct)
  870. {
  871. LoadStringCodec(pci->hinst, IDS_CODEC_COPYRIGHT, add.szCopyright, SIZEOFACMSTR(add.szCopyright));
  872. LoadStringCodec(pci->hinst, IDS_CODEC_LICENSING, add.szLicensing, SIZEOFACMSTR(add.szLicensing));
  873. LoadStringCodec(pci->hinst, IDS_CODEC_FEATURES, add.szFeatures, SIZEOFACMSTR(add.szFeatures));
  874. }
  875. }
  876. //
  877. // now copy the correct number of bytes to the caller's buffer
  878. //
  879. _fmemcpy(padd, &add, (UINT)add.cbStruct);
  880. //
  881. // success!
  882. //
  883. return (MMSYSERR_NOERROR);
  884. } // acmdDriverDetails()
  885. //--------------------------------------------------------------------------;
  886. //
  887. // LRESULT acmdDriverAbout
  888. //
  889. // Description:
  890. // This function is called to handle the ACMDM_DRIVER_ABOUT message.
  891. // A codec has the option of displaying its own 'about box' or letting
  892. // the ACM display one for it.
  893. //
  894. // Arguments:
  895. // PCODECINST pci: Pointer to private codec instance structure.
  896. //
  897. // HWND hwnd: Handle to parent window to use when displaying custom
  898. // about box. If a codec displays its own dialog, it is _required_
  899. // to display a modal dialog box using this hwnd argument as the
  900. // parent.
  901. //
  902. // Return (LRESULT):
  903. // The return value is MMSYSERR_NOTSUPPORTED if the ACM should display
  904. // a generic about box using the information contained in the codec
  905. // capabilities structure.
  906. //
  907. // If the codec chooses to display its own dialog box, then after
  908. // the dialog is dismissed by the user, MMSYSERR_NOERROR should be
  909. // returned.
  910. //
  911. // History:
  912. // 1/24/93 cjp [curtisp]
  913. //
  914. //--------------------------------------------------------------------------;
  915. LRESULT FNLOCAL acmdDriverAbout
  916. (
  917. PCODECINST pci,
  918. HWND hwnd
  919. )
  920. {
  921. //
  922. // this codec does not need any special dialog, so tell the ACM to
  923. // display one for us. note that this is the _recommended_ method
  924. // for consistency and simplicity of codecs. why write code when
  925. // you don't have to?
  926. //
  927. return (MMSYSERR_NOTSUPPORTED);
  928. } // acmdDriverAbout()
  929. //==========================================================================;
  930. //
  931. //
  932. //
  933. //
  934. //==========================================================================;
  935. //--------------------------------------------------------------------------;
  936. //
  937. // LRESULT acmdFormatSuggest
  938. //
  939. // Description:
  940. // This function handles the ACMDM_FORMAT_SUGGEST message. The purpose
  941. // of this function is to provide a way for the ACM (wave mapper) or
  942. // an application to quickly get a destination format that this codec
  943. // can convert the source format to. The 'suggested' format should
  944. // be as close to a common format as possible.
  945. //
  946. // Another way to think about this message is: what format would this
  947. // codec like to convert the source format to?
  948. //
  949. // Arguments:
  950. // PCODECINST pci: Pointer to private codec instance structure.
  951. //
  952. // LPACMDRVFORMATSUGGEST padfs: Pointer to ACMDRVFORMATSUGGEST structure.
  953. //
  954. // Return (LRESULT):
  955. // The return value is zero (MMSYSERR_NOERROR) if this function
  956. // succeeds with no errors. The return value is a non-zero ACMERR_*
  957. // or MMSYSERR_* if the function fails.
  958. //
  959. // History:
  960. // 11/28/92 cjp [curtisp]
  961. //
  962. //--------------------------------------------------------------------------;
  963. LRESULT FNLOCAL acmdFormatSuggest
  964. (
  965. PCODECINST pci,
  966. LPACMDRVFORMATSUGGEST padfs
  967. )
  968. {
  969. LPWAVEFORMATEX pwfxSrc;
  970. LPWAVEFORMATEX pwfxDst;
  971. LPADPCMWAVEFORMAT pwfadpcm;
  972. LPPCMWAVEFORMAT pwfpcm;
  973. pwfxSrc = padfs->pwfxSrc;
  974. pwfxDst = padfs->pwfxDst;
  975. //
  976. //
  977. //
  978. //
  979. switch (pwfxSrc->wFormatTag)
  980. {
  981. case WAVE_FORMAT_PCM:
  982. //
  983. // verify source format is acceptable for this driver
  984. //
  985. if (!pcmIsValidFormat(pwfxSrc))
  986. break;
  987. //
  988. // Verify that you are not asking for a particular dest format
  989. // that is not ADPCM.
  990. //
  991. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) &&
  992. (pwfxDst->wFormatTag != WAVE_FORMAT_ADPCM) ) {
  993. return (ACMERR_NOTPOSSIBLE);
  994. }
  995. // Verify that if other restrictions are given, they
  996. // match to the source. (Since we do not convert
  997. // the nChannels or nSamplesPerSec
  998. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS) &&
  999. (pwfxSrc->nChannels != pwfxDst->nChannels) ) {
  1000. return (ACMERR_NOTPOSSIBLE);
  1001. }
  1002. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC) &&
  1003. (pwfxSrc->nSamplesPerSec != pwfxDst->nSamplesPerSec) ) {
  1004. return (ACMERR_NOTPOSSIBLE);
  1005. }
  1006. // Verify that if we are asking for a specific number of bits
  1007. // per sample, that it is the correct #
  1008. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE) &&
  1009. (pwfxDst->wBitsPerSample != 4) ) {
  1010. return (ACMERR_NOTPOSSIBLE);
  1011. }
  1012. //
  1013. // suggest an ADPCM format that has most of the same details
  1014. // as the source PCM format
  1015. //
  1016. pwfxDst->wFormatTag = WAVE_FORMAT_ADPCM;
  1017. pwfxDst->nSamplesPerSec = pwfxSrc->nSamplesPerSec;
  1018. pwfxDst->nChannels = pwfxSrc->nChannels;
  1019. pwfxDst->wBitsPerSample = MSADPCM_BITS_PER_SAMPLE;
  1020. pwfxDst->nBlockAlign = adpcmBlockAlign(pwfxDst);
  1021. pwfxDst->nAvgBytesPerSec = adpcmAvgBytesPerSec(pwfxDst);
  1022. pwfxDst->cbSize = MSADPCM_WFX_EXTRA_BYTES;
  1023. pwfadpcm = (LPADPCMWAVEFORMAT)pwfxDst;
  1024. pwfadpcm->wSamplesPerBlock = adpcmSamplesPerBlock(pwfxDst);
  1025. adpcmCopyCoefficients(pwfadpcm);
  1026. return (MMSYSERR_NOERROR);
  1027. case WAVE_FORMAT_ADPCM:
  1028. //
  1029. // verify source format is acceptable for this driver
  1030. //
  1031. if (!adpcmIsValidFormat(pwfxSrc) ||
  1032. !adpcmIsMagicFormat((LPADPCMWAVEFORMAT)pwfxSrc))
  1033. break;
  1034. //
  1035. // Verify that you are not asking for a particular dest format
  1036. // that is not PCM.
  1037. //
  1038. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) &&
  1039. (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) ) {
  1040. return (ACMERR_NOTPOSSIBLE);
  1041. }
  1042. // Verify that if other restrictions are given, they
  1043. // match to the source. (Since we do not convert
  1044. // the nChannels or nSamplesPerSec
  1045. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS) &&
  1046. (pwfxSrc->nChannels != pwfxDst->nChannels) ) {
  1047. return (ACMERR_NOTPOSSIBLE);
  1048. }
  1049. if( (padfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC) &&
  1050. (pwfxSrc->nSamplesPerSec != pwfxDst->nSamplesPerSec) ) {
  1051. return (ACMERR_NOTPOSSIBLE);
  1052. }
  1053. //
  1054. // suggest a PCM format that has most of the same details
  1055. // as the source ADPCM format
  1056. //
  1057. pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
  1058. pwfxDst->nSamplesPerSec = pwfxSrc->nSamplesPerSec;
  1059. pwfxDst->nChannels = pwfxSrc->nChannels;
  1060. // Verify that if we are asking for a specific number of bits
  1061. // per sample, that it is the correct #
  1062. if( padfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE ) {
  1063. if( (pwfxDst->wBitsPerSample != 8) &&
  1064. (pwfxDst->wBitsPerSample != 16) ) {
  1065. return (ACMERR_NOTPOSSIBLE);
  1066. }
  1067. } else {
  1068. // Default to 16 bit decode
  1069. pwfxDst->wBitsPerSample = 16;
  1070. }
  1071. pwfpcm = (LPPCMWAVEFORMAT)pwfxDst;
  1072. pwfxDst->nBlockAlign = PCM_BLOCKALIGNMENT(pwfxDst);
  1073. pwfxDst->nAvgBytesPerSec = pwfxDst->nSamplesPerSec *
  1074. pwfxDst->nBlockAlign;
  1075. return (MMSYSERR_NOERROR);
  1076. }
  1077. //
  1078. // can't suggest anything because either the source format is foreign
  1079. // or the destination format has restrictions that this converter
  1080. // cannot deal with.
  1081. //
  1082. return (ACMERR_NOTPOSSIBLE);
  1083. } // acmdFormatSuggest()
  1084. //==========================================================================;
  1085. //
  1086. //
  1087. //
  1088. //
  1089. //==========================================================================;
  1090. //--------------------------------------------------------------------------;
  1091. //
  1092. // LRESULT acmdFormatTagDetails
  1093. //
  1094. // Description:
  1095. //
  1096. //
  1097. // Arguments:
  1098. // PCODECINST pci:
  1099. //
  1100. // LPACMFORMATTAGDETAILS padft:
  1101. //
  1102. // DWORD fdwDetails:
  1103. //
  1104. // Return (LRESULT):
  1105. //
  1106. // History:
  1107. // 08/01/93 cjp [curtisp]
  1108. //
  1109. //--------------------------------------------------------------------------;
  1110. LRESULT FNLOCAL acmdFormatTagDetails
  1111. (
  1112. PCODECINST pci,
  1113. LPACMFORMATTAGDETAILS padft,
  1114. DWORD fdwDetails
  1115. )
  1116. {
  1117. UINT uFormatTag;
  1118. //
  1119. //
  1120. //
  1121. //
  1122. //
  1123. switch (ACM_FORMATTAGDETAILSF_QUERYMASK & fdwDetails)
  1124. {
  1125. case ACM_FORMATTAGDETAILSF_INDEX:
  1126. //
  1127. // if the index is too large, then they are asking for a
  1128. // non-existant format. return error.
  1129. //
  1130. if (CODEC_MAX_FORMAT_TAGS <= padft->dwFormatTagIndex)
  1131. return (ACMERR_NOTPOSSIBLE);
  1132. uFormatTag = gauFormatTagIndexToTag[(UINT)padft->dwFormatTagIndex];
  1133. break;
  1134. case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
  1135. switch (padft->dwFormatTag)
  1136. {
  1137. case WAVE_FORMAT_UNKNOWN:
  1138. case WAVE_FORMAT_ADPCM:
  1139. uFormatTag = WAVE_FORMAT_ADPCM;
  1140. break;
  1141. case WAVE_FORMAT_PCM:
  1142. uFormatTag = WAVE_FORMAT_PCM;
  1143. break;
  1144. default:
  1145. return (ACMERR_NOTPOSSIBLE);
  1146. }
  1147. break;
  1148. case ACM_FORMATTAGDETAILSF_FORMATTAG:
  1149. switch (padft->dwFormatTag)
  1150. {
  1151. case WAVE_FORMAT_ADPCM:
  1152. uFormatTag = WAVE_FORMAT_ADPCM;
  1153. break;
  1154. case WAVE_FORMAT_PCM:
  1155. uFormatTag = WAVE_FORMAT_PCM;
  1156. break;
  1157. default:
  1158. return (ACMERR_NOTPOSSIBLE);
  1159. }
  1160. break;
  1161. //
  1162. // if this converter does not understand a query type, then
  1163. // return 'not supported'
  1164. //
  1165. default:
  1166. return (MMSYSERR_NOTSUPPORTED);
  1167. }
  1168. //
  1169. //
  1170. //
  1171. //
  1172. switch (uFormatTag)
  1173. {
  1174. case WAVE_FORMAT_PCM:
  1175. padft->dwFormatTagIndex = 0;
  1176. padft->dwFormatTag = WAVE_FORMAT_PCM;
  1177. padft->cbFormatSize = sizeof(PCMWAVEFORMAT);
  1178. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1179. padft->cStandardFormats = CODEC_MAX_FORMATS_PCM;
  1180. //
  1181. // the ACM is responsible for the PCM format tag name
  1182. //
  1183. padft->szFormatTag[0] = '\0';
  1184. break;
  1185. case WAVE_FORMAT_ADPCM:
  1186. padft->dwFormatTagIndex = 1;
  1187. padft->dwFormatTag = WAVE_FORMAT_ADPCM;
  1188. padft->cbFormatSize = sizeof(WAVEFORMATEX) +
  1189. MSADPCM_WFX_EXTRA_BYTES;
  1190. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1191. padft->cStandardFormats = CODEC_MAX_FORMATS_ADPCM;
  1192. LoadStringCodec(pci->hinst, IDS_CODEC_NAME, padft->szFormatTag, SIZEOFACMSTR(padft->szFormatTag));
  1193. break;
  1194. default:
  1195. return (ACMERR_NOTPOSSIBLE);
  1196. }
  1197. //
  1198. // return only the requested info
  1199. //
  1200. // the ACM will guarantee that the ACMFORMATTAGDETAILS structure
  1201. // passed is at least large enough to hold the base information of
  1202. // the details structure
  1203. //
  1204. padft->cbStruct = min(padft->cbStruct, sizeof(*padft));
  1205. //
  1206. //
  1207. //
  1208. return (MMSYSERR_NOERROR);
  1209. } // acmdFormatTagDetails()
  1210. //--------------------------------------------------------------------------;
  1211. //
  1212. // LRESULT acmdFormatDetails
  1213. //
  1214. // Description:
  1215. //
  1216. //
  1217. // Arguments:
  1218. // PCODECINST pci:
  1219. //
  1220. // LPACMFORMATDETAILS padf:
  1221. //
  1222. // DWORD fdwDetails:
  1223. //
  1224. // Return (LRESULT):
  1225. //
  1226. // History:
  1227. // 06/13/93 cjp [curtisp]
  1228. //
  1229. //--------------------------------------------------------------------------;
  1230. LRESULT FNLOCAL acmdFormatDetails
  1231. (
  1232. PCODECINST pci,
  1233. LPACMFORMATDETAILS padf,
  1234. DWORD fdwDetails
  1235. )
  1236. {
  1237. LPWAVEFORMATEX pwfx;
  1238. LPADPCMWAVEFORMAT pwfadpcm;
  1239. UINT uFormatIndex;
  1240. UINT u;
  1241. pwfx = padf->pwfx;
  1242. //
  1243. //
  1244. //
  1245. //
  1246. //
  1247. switch (ACM_FORMATDETAILSF_QUERYMASK & fdwDetails)
  1248. {
  1249. case ACM_FORMATDETAILSF_INDEX:
  1250. //
  1251. // enumerate by index
  1252. //
  1253. // for this converter, this is more code than necessary... just
  1254. // verify that the format tag is something we know about
  1255. //
  1256. switch (padf->dwFormatTag)
  1257. {
  1258. case WAVE_FORMAT_PCM:
  1259. if (CODEC_MAX_FORMATS_PCM <= padf->dwFormatIndex)
  1260. return (ACMERR_NOTPOSSIBLE);
  1261. //
  1262. // put some stuff in more accessible variables--note
  1263. // that we bring variable sizes down to a reasonable
  1264. // size for 16 bit code...
  1265. //
  1266. uFormatIndex = (UINT)padf->dwFormatIndex;
  1267. pwfx = padf->pwfx;
  1268. //
  1269. // now fill in the format structure
  1270. //
  1271. pwfx->wFormatTag = WAVE_FORMAT_PCM;
  1272. u = uFormatIndex / (CODEC_MAX_BITSPERSAMPLE_PCM * CODEC_MAX_CHANNELS);
  1273. pwfx->nSamplesPerSec = gauFormatIndexToSampleRate[u];
  1274. u = uFormatIndex % CODEC_MAX_CHANNELS;
  1275. pwfx->nChannels = u + 1;
  1276. u = (uFormatIndex / CODEC_MAX_CHANNELS) % CODEC_MAX_CHANNELS;
  1277. pwfx->wBitsPerSample = (WORD)gauFormatIndexToBitsPerSample[u];
  1278. pwfx->nBlockAlign = PCM_BLOCKALIGNMENT(pwfx);
  1279. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  1280. //
  1281. // note that the cbSize field is NOT valid for PCM
  1282. // formats
  1283. //
  1284. // pwfx->cbSize = 0;
  1285. break;
  1286. case WAVE_FORMAT_ADPCM:
  1287. if (CODEC_MAX_FORMATS_ADPCM <= padf->dwFormatIndex)
  1288. return (ACMERR_NOTPOSSIBLE);
  1289. //
  1290. // put some stuff in more accessible variables--note that we
  1291. // bring variable sizes down to a reasonable size for 16 bit
  1292. // code...
  1293. //
  1294. uFormatIndex = (UINT)padf->dwFormatIndex;
  1295. pwfx = padf->pwfx;
  1296. pwfadpcm = (LPADPCMWAVEFORMAT)pwfx;
  1297. //
  1298. //
  1299. //
  1300. pwfx->wFormatTag = WAVE_FORMAT_ADPCM;
  1301. u = uFormatIndex / (CODEC_MAX_BITSPERSAMPLE_ADPCM * CODEC_MAX_CHANNELS);
  1302. pwfx->nSamplesPerSec = gauFormatIndexToSampleRate[u];
  1303. u = uFormatIndex % CODEC_MAX_CHANNELS;
  1304. pwfx->nChannels = u + 1;
  1305. pwfx->wBitsPerSample = MSADPCM_BITS_PER_SAMPLE;
  1306. pwfx->nBlockAlign = adpcmBlockAlign(pwfx);
  1307. pwfx->nAvgBytesPerSec = adpcmAvgBytesPerSec(pwfx);
  1308. pwfx->cbSize = MSADPCM_WFX_EXTRA_BYTES;
  1309. pwfadpcm->wSamplesPerBlock = adpcmSamplesPerBlock(pwfx);
  1310. adpcmCopyCoefficients(pwfadpcm);
  1311. break;
  1312. default:
  1313. return (ACMERR_NOTPOSSIBLE);
  1314. }
  1315. case ACM_FORMATDETAILSF_FORMAT:
  1316. //
  1317. // must want to verify that the format passed in is supported
  1318. // and return a string description...
  1319. //
  1320. switch (pwfx->wFormatTag)
  1321. {
  1322. case WAVE_FORMAT_PCM:
  1323. if (!pcmIsValidFormat(pwfx))
  1324. return (ACMERR_NOTPOSSIBLE);
  1325. break;
  1326. case WAVE_FORMAT_ADPCM:
  1327. if (!adpcmIsValidFormat(pwfx) ||
  1328. !adpcmIsMagicFormat((LPADPCMWAVEFORMAT)pwfx))
  1329. return (ACMERR_NOTPOSSIBLE);
  1330. break;
  1331. default:
  1332. return (ACMERR_NOTPOSSIBLE);
  1333. }
  1334. break;
  1335. default:
  1336. //
  1337. // don't know how to do the query type passed--return 'not
  1338. // supported'.
  1339. //
  1340. return (MMSYSERR_NOTSUPPORTED);
  1341. }
  1342. //
  1343. // return only the requested info
  1344. //
  1345. // the ACM will guarantee that the ACMFORMATDETAILS structure
  1346. // passed is at least large enough to hold the base structure
  1347. //
  1348. // note that we let the ACM create the format string for us since
  1349. // we require no special formatting (and don't want to deal with
  1350. // internationalization issues, etc)
  1351. //
  1352. padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1353. padf->szFormat[0] = '\0';
  1354. padf->cbStruct = min(padf->cbStruct, sizeof(*padf));
  1355. //
  1356. //
  1357. //
  1358. return (MMSYSERR_NOERROR);
  1359. } // acmdFormatDetails()
  1360. //==========================================================================;
  1361. //
  1362. //
  1363. //
  1364. //
  1365. //==========================================================================;
  1366. //--------------------------------------------------------------------------;
  1367. //
  1368. // LRESULT acmdStreamQuery
  1369. //
  1370. // Description:
  1371. // This is an internal helper used by the ACMDM_STREM_OPEN
  1372. // and ACMDM_STREAM_SIZE messages.
  1373. // The purpose of this function is to tell the caller if the proposed
  1374. // conversion can be handled by this codec.
  1375. //
  1376. // Arguments:
  1377. // PCODECINST pci: Pointer to private codec instance structure.
  1378. //
  1379. // LPWAVEFORMATEX pwfxSrc:
  1380. //
  1381. // LPWAVEFORMATEX pwfxDst:
  1382. //
  1383. // LPWAVEFILTER pwfltr:
  1384. //
  1385. // DWORD fdwOpen:
  1386. //
  1387. // Return (LRESULT):
  1388. // The return value is zero (MMSYSERR_NOERROR) if this function
  1389. // succeeds with no errors. The return value is a non-zero ACMERR_*
  1390. // or MMSYSERR_* if the function fails.
  1391. //
  1392. // A return value of ACMERR_NOTPOSSIBLE must be returned if the conversion
  1393. // cannot be performed by this codec.
  1394. //
  1395. // History:
  1396. // 11/28/92 cjp [curtisp]
  1397. //
  1398. //--------------------------------------------------------------------------;
  1399. LRESULT FNLOCAL acmdStreamQuery
  1400. (
  1401. PCODECINST pci,
  1402. LPWAVEFORMATEX pwfxSrc,
  1403. LPWAVEFORMATEX pwfxDst,
  1404. LPWAVEFILTER pwfltr,
  1405. DWORD fdwOpen
  1406. )
  1407. {
  1408. LPADPCMWAVEFORMAT pwfADPCM;
  1409. LPPCMWAVEFORMAT pwfPCM;
  1410. //
  1411. // check to see if this
  1412. // codec can convert from the source to the destination.
  1413. //
  1414. // first check if source is ADPCM so destination must be PCM..
  1415. //
  1416. if (adpcmIsValidFormat(pwfxSrc))
  1417. {
  1418. if (!pcmIsValidFormat(pwfxDst))
  1419. return (ACMERR_NOTPOSSIBLE);
  1420. //
  1421. // converting from ADPCM to PCM...
  1422. //
  1423. pwfADPCM = (LPADPCMWAVEFORMAT)pwfxSrc;
  1424. pwfPCM = (LPPCMWAVEFORMAT)pwfxDst;
  1425. if (pwfADPCM->wfx.nChannels != pwfPCM->wf.nChannels)
  1426. return (ACMERR_NOTPOSSIBLE);
  1427. if (pwfADPCM->wfx.nSamplesPerSec != pwfPCM->wf.nSamplesPerSec)
  1428. return (ACMERR_NOTPOSSIBLE);
  1429. if (!adpcmIsMagicFormat(pwfADPCM))
  1430. return (ACMERR_NOTPOSSIBLE);
  1431. return (MMSYSERR_NOERROR);
  1432. }
  1433. //
  1434. // now try source as PCM so destination must be ADPCM..
  1435. //
  1436. else if (pcmIsValidFormat(pwfxSrc))
  1437. {
  1438. if (!adpcmIsValidFormat(pwfxDst))
  1439. return (ACMERR_NOTPOSSIBLE);
  1440. //
  1441. // converting from PCM to ADPCM...
  1442. //
  1443. pwfPCM = (LPPCMWAVEFORMAT)pwfxSrc;
  1444. pwfADPCM = (LPADPCMWAVEFORMAT)pwfxDst;
  1445. if (pwfADPCM->wfx.nChannels != pwfPCM->wf.nChannels)
  1446. return (ACMERR_NOTPOSSIBLE);
  1447. if (pwfADPCM->wfx.nSamplesPerSec != pwfPCM->wf.nSamplesPerSec)
  1448. return (ACMERR_NOTPOSSIBLE);
  1449. if (!adpcmIsMagicFormat(pwfADPCM))
  1450. return (ACMERR_NOTPOSSIBLE);
  1451. return (MMSYSERR_NOERROR);
  1452. }
  1453. //
  1454. // we are unable to perform the conversion we are being queried for
  1455. // so return ACMERR_NOTPOSSIBLE to signify this...
  1456. //
  1457. return (ACMERR_NOTPOSSIBLE);
  1458. } // acmdStreamQuery()
  1459. //--------------------------------------------------------------------------;
  1460. //
  1461. // LRESULT acmdStreamOpen
  1462. //
  1463. // Description:
  1464. // This function handles the ACMDM_STREAM_OPEN message. This message
  1465. // is sent to initiate a new conversion stream. This is usually caused
  1466. // by an application calling acmOpenConversion. If this function is
  1467. // successful, then one or more ACMDM_STREAM_CONVERT messages will be
  1468. // sent to convert individual buffers (user calls acmStreamConvert).
  1469. //
  1470. // Arguments:
  1471. // PCODECINST pci: Pointer to private codec instance structure.
  1472. //
  1473. // LPACMDRVINSTANCE padi: Pointer to instance data for the conversion
  1474. // stream. This structure was allocated by the ACM and filled with
  1475. // the most common instance data needed for conversions.
  1476. //
  1477. // Return (LRESULT):
  1478. // The return value is zero (MMSYSERR_NOERROR) if this function
  1479. // succeeds with no errors. The return value is a non-zero ACMERR_*
  1480. // or MMSYSERR_* if the function fails.
  1481. //
  1482. // History:
  1483. // 11/28/92 cjp [curtisp]
  1484. //
  1485. //--------------------------------------------------------------------------;
  1486. LRESULT FNLOCAL acmdStreamOpen
  1487. (
  1488. PCODECINST pci,
  1489. LPACMDRVSTREAMINSTANCE padsi
  1490. )
  1491. {
  1492. LPWAVEFORMATEX pwfxSrc;
  1493. LPWAVEFORMATEX pwfxDst;
  1494. pwfxSrc = padsi->pwfxSrc;
  1495. pwfxDst = padsi->pwfxDst;
  1496. //
  1497. // the most important condition to check before doing anything else
  1498. // is that this codec can actually perform the conversion we are
  1499. // being opened for. this check should fail as quickly as possible
  1500. // if the conversion is not possible by this codec.
  1501. //
  1502. // it is VERY important to fail quickly so the ACM can attempt to
  1503. // find a codec that is suitable for the conversion. also note that
  1504. // the ACM may call this codec several times with slightly different
  1505. // format specifications before giving up.
  1506. //
  1507. // this codec first verifies that the src and dst formats are
  1508. // acceptable...
  1509. //
  1510. if (acmdStreamQuery(pci,
  1511. pwfxSrc,
  1512. pwfxDst,
  1513. padsi->pwfltr,
  1514. padsi->fdwOpen))
  1515. {
  1516. //
  1517. // either the source or destination format is illegal for this
  1518. // codec--or the conversion between the formats can not be
  1519. // performed by this codec.
  1520. //
  1521. return (ACMERR_NOTPOSSIBLE);
  1522. }
  1523. //
  1524. // we have decided that this codec can handle the conversion stream.
  1525. // so we want to do _as much work as possible_ right now to prepare
  1526. // for converting data. any resource allocation, table building, etc
  1527. // that can be dealt with at this time should be done.
  1528. //
  1529. // THIS IS VERY IMPORTANT! all ACMDM_STREAM_CONVERT messages need to
  1530. // be handled as quickly as possible.
  1531. //
  1532. // this codec is very simple, so we only figure out what conversion
  1533. // function that should be used for converting from the src format
  1534. // to the dst format and place this in the dwDrvInstance member
  1535. // of the ACMDRVINSTANCE structure. we then only need to 'call'
  1536. // this function during the ACMDM_STREAM_CONVERT message.
  1537. //
  1538. if (pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM)
  1539. {
  1540. #ifdef WIN32
  1541. switch (pwfxDst->nChannels)
  1542. {
  1543. case 1:
  1544. if (8 == pwfxDst->wBitsPerSample)
  1545. padsi->dwDriver = (DWORD_PTR)adpcmDecode4Bit_M08;
  1546. else
  1547. padsi->dwDriver = (DWORD_PTR)adpcmDecode4Bit_M16;
  1548. break;
  1549. case 2:
  1550. if (8 == pwfxDst->wBitsPerSample)
  1551. padsi->dwDriver = (DWORD_PTR)adpcmDecode4Bit_S08;
  1552. else
  1553. padsi->dwDriver = (DWORD_PTR)adpcmDecode4Bit_S16;
  1554. break;
  1555. default:
  1556. return ACMERR_NOTPOSSIBLE;
  1557. }
  1558. #else
  1559. padsi->dwDriver = (DWORD_PTR)DecodeADPCM_4Bit_386;
  1560. #endif
  1561. return (MMSYSERR_NOERROR);
  1562. }
  1563. else if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
  1564. {
  1565. //
  1566. // Check to see if we will be doing this conversion in realtime.
  1567. // (The default is yes)
  1568. //
  1569. if (padsi->fdwOpen & ACM_STREAMOPENF_NONREALTIME)
  1570. {
  1571. switch (pwfxSrc->nChannels)
  1572. {
  1573. case 1:
  1574. if (8 == pwfxSrc->wBitsPerSample)
  1575. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_M08_FullPass;
  1576. else
  1577. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_M16_FullPass;
  1578. break;
  1579. case 2:
  1580. if (8 == pwfxSrc->wBitsPerSample)
  1581. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_S08_FullPass;
  1582. else
  1583. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_S16_FullPass;
  1584. break;
  1585. default:
  1586. return ACMERR_NOTPOSSIBLE;
  1587. }
  1588. }
  1589. else
  1590. {
  1591. #ifdef WIN32
  1592. switch (pwfxSrc->nChannels)
  1593. {
  1594. case 1:
  1595. if (8 == pwfxSrc->wBitsPerSample)
  1596. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_M08_OnePass;
  1597. else
  1598. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_M16_OnePass;
  1599. break;
  1600. case 2:
  1601. if (8 == pwfxSrc->wBitsPerSample)
  1602. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_S08_OnePass;
  1603. else
  1604. padsi->dwDriver = (DWORD_PTR)adpcmEncode4Bit_S16_OnePass;
  1605. break;
  1606. default:
  1607. return ACMERR_NOTPOSSIBLE;
  1608. }
  1609. #else
  1610. padsi->dwDriver = (DWORD_PTR)EncodeADPCM_4Bit_386;
  1611. #endif
  1612. }
  1613. return (MMSYSERR_NOERROR);
  1614. }
  1615. //
  1616. // fail--we cannot perform the conversion
  1617. //
  1618. return (ACMERR_NOTPOSSIBLE);
  1619. } // acmdStreamOpen()
  1620. //--------------------------------------------------------------------------;
  1621. //
  1622. // LRESULT acmdStreamClose
  1623. //
  1624. // Description:
  1625. // This function is called to handle the ACMDM_STREAM_CLOSE message.
  1626. // This message is sent when a conversion stream is no longer being
  1627. // used (the stream is being closed; usually by an application
  1628. // calling acmCloseConversion). The codec should clean up any resources
  1629. // that were allocated for the stream.
  1630. //
  1631. // Arguments:
  1632. // PCODECINST pci: Pointer to private codec instance structure.
  1633. //
  1634. // LPACMDRVINSTANCE padi: Pointer to instance data for the conversion
  1635. // stream.
  1636. //
  1637. // Return (LRESULT):
  1638. // The return value is zero (MMSYSERR_NOERROR) if this function
  1639. // succeeds with no errors. The return value is a non-zero ACMERR_*
  1640. // or MMSYSERR_* if the function fails.
  1641. //
  1642. // NOTE! It is _strongly_ recommended that a codec not fail to close
  1643. // a conversion stream.
  1644. //
  1645. // History:
  1646. // 11/28/92 cjp [curtisp]
  1647. //
  1648. //--------------------------------------------------------------------------;
  1649. LRESULT FNLOCAL acmdStreamClose
  1650. (
  1651. PCODECINST pci,
  1652. LPACMDRVSTREAMINSTANCE padsi
  1653. )
  1654. {
  1655. //
  1656. // the codec should clean up all resources that were allocated for
  1657. // the stream instance.
  1658. //
  1659. // this codec did not allocate any resources, so we succeed immediately
  1660. //
  1661. return (MMSYSERR_NOERROR);
  1662. } // acmdStreamClose()
  1663. //--------------------------------------------------------------------------;
  1664. //
  1665. // LRESULT acmdStreamSize
  1666. //
  1667. // Description:
  1668. // This function handles the ACMDM_STREAM_SIZE message. The purpose
  1669. // of this function is to provide the _largest size in bytes_ that
  1670. // the source or destination buffer needs to be given the input and
  1671. // output formats and the size in bytes of the source or destination
  1672. // data buffer.
  1673. //
  1674. // In other words: how big does my destination buffer need to be to
  1675. // hold the converted data? (ACM_STREAMSIZEF_SOURCE)
  1676. //
  1677. // Or: how big can my source buffer be given the destination buffer?
  1678. // (ACM_STREAMSIZEF_DESTINATION)
  1679. //
  1680. // Arguments:
  1681. // PCODECINST pci: Pointer to private ACM driver instance structure.
  1682. // This structure is [optionally] allocated during the DRV_OPEN message
  1683. // which is handled by the acmdDriverOpen function.
  1684. //
  1685. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1686. // conversion stream. This structure was allocated by the ACM and
  1687. // filled with the most common instance data needed for conversions.
  1688. // The information in this structure is exactly the same as it was
  1689. // during the ACMDM_STREAM_OPEN message--so it is not necessary
  1690. // to re-verify the information referenced by this structure.
  1691. //
  1692. // LPACMDRVSTREAMSIZE padss: Specifies a pointer to the ACMDRVSTREAMSIZE
  1693. // structure that defines the conversion stream size query attributes.
  1694. //
  1695. // Return (LRESULT):
  1696. // The return value is zero (MMSYSERR_NOERROR) if this function
  1697. // succeeds with no errors. The return value is a non-zero error code
  1698. // if the function fails.
  1699. //
  1700. // An ACM driver should return MMSYSERR_NOTSUPPORTED if a query type
  1701. // is requested that the driver does not understand. Note that a driver
  1702. // must support both the ACM_STREAMSIZEF_DESTINATION and
  1703. // ACM_STREAMSIZEF_SOURCE queries.
  1704. //
  1705. // If the conversion would be 'out of range' given the input arguments,
  1706. // then ACMERR_NOTPOSSIBLE should be returned.
  1707. //
  1708. //--------------------------------------------------------------------------;
  1709. LRESULT FNLOCAL acmdStreamSize
  1710. (
  1711. PCODECINST pci,
  1712. LPACMDRVSTREAMINSTANCE padsi,
  1713. LPACMDRVSTREAMSIZE padss
  1714. )
  1715. {
  1716. LPWAVEFORMATEX pwfxSrc;
  1717. LPWAVEFORMATEX pwfxDst;
  1718. LPADPCMWAVEFORMAT pwfadpcm;
  1719. DWORD cb;
  1720. DWORD cBlocks;
  1721. DWORD cbBytesPerBlock;
  1722. pwfxSrc = padsi->pwfxSrc;
  1723. pwfxDst = padsi->pwfxDst;
  1724. //
  1725. //
  1726. //
  1727. switch (ACM_STREAMSIZEF_QUERYMASK & padss->fdwSize)
  1728. {
  1729. case ACM_STREAMSIZEF_SOURCE:
  1730. cb = padss->cbSrcLength;
  1731. if (WAVE_FORMAT_ADPCM == pwfxSrc->wFormatTag)
  1732. {
  1733. //
  1734. // how many destination PCM bytes are needed to hold
  1735. // the decoded ADPCM data of padss->cbSrcLength bytes
  1736. //
  1737. // always round UP
  1738. //
  1739. cBlocks = cb / pwfxSrc->nBlockAlign;
  1740. if (0 == cBlocks)
  1741. {
  1742. return (ACMERR_NOTPOSSIBLE);
  1743. }
  1744. pwfadpcm = (LPADPCMWAVEFORMAT)pwfxSrc;
  1745. cbBytesPerBlock = pwfadpcm->wSamplesPerBlock * pwfxDst->nBlockAlign;
  1746. if ((0xFFFFFFFFL / cbBytesPerBlock) < cBlocks)
  1747. {
  1748. return (ACMERR_NOTPOSSIBLE);
  1749. }
  1750. if (0 == (cb % pwfxSrc->nBlockAlign))
  1751. {
  1752. cb = cBlocks * cbBytesPerBlock;
  1753. }
  1754. else
  1755. {
  1756. cb = (cBlocks + 1) * cbBytesPerBlock;
  1757. }
  1758. }
  1759. else
  1760. {
  1761. //
  1762. // how many destination ADPCM bytes are needed to hold
  1763. // the encoded PCM data of padss->cbSrcLength bytes
  1764. //
  1765. // always round UP
  1766. //
  1767. pwfadpcm = (LPADPCMWAVEFORMAT)pwfxDst;
  1768. cbBytesPerBlock = pwfadpcm->wSamplesPerBlock * pwfxSrc->nBlockAlign;
  1769. cBlocks = cb / cbBytesPerBlock;
  1770. if (0 == (cb % cbBytesPerBlock))
  1771. {
  1772. cb = cBlocks * pwfxDst->nBlockAlign;
  1773. }
  1774. else
  1775. {
  1776. cb = (cBlocks + 1) * pwfxDst->nBlockAlign;
  1777. }
  1778. if (0L == cb)
  1779. {
  1780. return (ACMERR_NOTPOSSIBLE);
  1781. }
  1782. }
  1783. padss->cbDstLength = cb;
  1784. return (MMSYSERR_NOERROR);
  1785. case ACM_STREAMSIZEF_DESTINATION:
  1786. cb = padss->cbDstLength;
  1787. if (WAVE_FORMAT_ADPCM == pwfxDst->wFormatTag)
  1788. {
  1789. //
  1790. // how many source PCM bytes can be encoded into a
  1791. // destination buffer of padss->cbDstLength bytes
  1792. //
  1793. // always round DOWN
  1794. //
  1795. cBlocks = cb / pwfxDst->nBlockAlign;
  1796. if (0 == cBlocks)
  1797. {
  1798. return (ACMERR_NOTPOSSIBLE);
  1799. }
  1800. pwfadpcm = (LPADPCMWAVEFORMAT)pwfxDst;
  1801. cbBytesPerBlock = pwfadpcm->wSamplesPerBlock * pwfxSrc->nBlockAlign;
  1802. if ((0xFFFFFFFFL / cbBytesPerBlock) < cBlocks)
  1803. {
  1804. return (ACMERR_NOTPOSSIBLE);
  1805. }
  1806. cb = cBlocks * cbBytesPerBlock;
  1807. }
  1808. else
  1809. {
  1810. //
  1811. // how many source ADPCM bytes can be decoded into a
  1812. // destination buffer of padss->cbDstLength bytes
  1813. //
  1814. // always round DOWN
  1815. //
  1816. pwfadpcm = (LPADPCMWAVEFORMAT)pwfxSrc;
  1817. cbBytesPerBlock = pwfadpcm->wSamplesPerBlock * pwfxDst->nBlockAlign;
  1818. cBlocks = cb / cbBytesPerBlock;
  1819. if (0 == cBlocks)
  1820. {
  1821. return (ACMERR_NOTPOSSIBLE);
  1822. }
  1823. cb = cBlocks * pwfxSrc->nBlockAlign;
  1824. }
  1825. padss->cbSrcLength = cb;
  1826. return (MMSYSERR_NOERROR);
  1827. }
  1828. //
  1829. //
  1830. //
  1831. return (MMSYSERR_NOTSUPPORTED);
  1832. } // acmdStreamSize()
  1833. //--------------------------------------------------------------------------;
  1834. //
  1835. // LRESULT acmdStreamConvert
  1836. //
  1837. // Description:
  1838. // This function handles the ACMDM_STREAM_CONVERT message. This is the
  1839. // whole purpose of writing a codec--to convert data. This message is
  1840. // sent after a stream has been opened (the codec receives and succeeds
  1841. // the ACMDM_STREAM_OPEN message).
  1842. //
  1843. // Arguments:
  1844. // PCODECINST pci: Pointer to private codec instance structure.
  1845. //
  1846. // LPACMDRVSTREAMHEADER pdsh: Pointer to a conversion stream instance
  1847. // structure.
  1848. //
  1849. // DWORD fdwConvert: Misc. flags for how conversion should be done.
  1850. //
  1851. // Return (LRESULT):
  1852. // The return value is zero (MMSYSERR_NOERROR) if this function
  1853. // succeeds with no errors. The return value is a non-zero ACMERR_*
  1854. // or MMSYSERR_* if the function fails.
  1855. //
  1856. // History:
  1857. // 11/28/92 cjp [curtisp]
  1858. //
  1859. //--------------------------------------------------------------------------;
  1860. LRESULT FNLOCAL acmdStreamConvert
  1861. (
  1862. PCODECINST pci,
  1863. LPACMDRVSTREAMINSTANCE padsi,
  1864. LPACMDRVSTREAMHEADER padsh
  1865. )
  1866. {
  1867. CONVERTPROC_C fpConvertC;
  1868. #ifndef WIN32
  1869. CONVERTPROC_ASM fpConvertAsm;
  1870. BOOL fRealTime;
  1871. #endif
  1872. BOOL fBlockAlign;
  1873. BOOL fDecode;
  1874. LPWAVEFORMATEX pwfpcm;
  1875. LPADPCMWAVEFORMAT pwfadpcm;
  1876. DWORD dw;
  1877. fBlockAlign = (0 != (ACM_STREAMCONVERTF_BLOCKALIGN & padsh->fdwConvert));
  1878. fDecode = ( WAVE_FORMAT_PCM == padsi->pwfxDst->wFormatTag );
  1879. if( !fDecode )
  1880. {
  1881. //
  1882. // encode
  1883. //
  1884. pwfpcm = padsi->pwfxSrc;
  1885. pwfadpcm = (LPADPCMWAVEFORMAT)padsi->pwfxDst;
  1886. dw = PCM_BYTESTOSAMPLES(pwfpcm, padsh->cbSrcLength);
  1887. if (fBlockAlign)
  1888. {
  1889. dw = (dw / pwfadpcm->wSamplesPerBlock) * pwfadpcm->wSamplesPerBlock;
  1890. }
  1891. //
  1892. // Look for an easy exit. We can only handle an even number of
  1893. // samples.
  1894. //
  1895. if( dw < 2 )
  1896. {
  1897. padsh->cbDstLengthUsed = 0;
  1898. if( fBlockAlign )
  1899. padsh->cbSrcLengthUsed = 0;
  1900. else
  1901. padsh->cbSrcLengthUsed = padsh->cbSrcLength;
  1902. return MMSYSERR_NOERROR;
  1903. }
  1904. //
  1905. // Make sure we have an even number of samples.
  1906. //
  1907. dw &= ~1;
  1908. dw = PCM_SAMPLESTOBYTES(pwfpcm, dw);
  1909. padsh->cbSrcLengthUsed = dw;
  1910. }
  1911. else
  1912. {
  1913. //
  1914. // Decode.
  1915. //
  1916. pwfadpcm = (LPADPCMWAVEFORMAT)padsi->pwfxSrc;
  1917. pwfpcm = padsi->pwfxDst;
  1918. //
  1919. // Determine the number of samples to convert.
  1920. //
  1921. dw = padsh->cbSrcLength;
  1922. if (fBlockAlign) {
  1923. dw = (dw / pwfadpcm->wfx.nBlockAlign) * pwfadpcm->wfx.nBlockAlign;
  1924. }
  1925. padsh->cbSrcLengthUsed = dw;
  1926. }
  1927. //
  1928. // Call the conversion routine.
  1929. //
  1930. #ifdef WIN32
  1931. fpConvertC = (CONVERTPROC_C)padsi->dwDriver;
  1932. padsh->cbDstLengthUsed = (*fpConvertC)(
  1933. (HPBYTE)padsh->pbSrc,
  1934. padsh->cbSrcLengthUsed,
  1935. (HPBYTE)padsh->pbDst,
  1936. (UINT)pwfadpcm->wfx.nBlockAlign,
  1937. (UINT)pwfadpcm->wSamplesPerBlock,
  1938. (UINT)pwfadpcm->wNumCoef,
  1939. (LPADPCMCOEFSET)&(pwfadpcm->aCoef[0])
  1940. );
  1941. #else
  1942. fRealTime = (0L == (padsi->fdwOpen & ACM_STREAMOPENF_NONREALTIME) );
  1943. if( fDecode || fRealTime ) {
  1944. fpConvertAsm = (CONVERTPROC_ASM)padsi->dwDriver;
  1945. padsh->cbDstLengthUsed = (*fpConvertAsm)(
  1946. padsi->pwfxSrc,
  1947. padsh->pbSrc,
  1948. padsi->pwfxDst,
  1949. padsh->pbDst,
  1950. padsh->cbSrcLengthUsed
  1951. );
  1952. } else {
  1953. fpConvertC = (CONVERTPROC_C)padsi->dwDriver;
  1954. padsh->cbDstLengthUsed = (*fpConvertC)(
  1955. (HPBYTE)padsh->pbSrc,
  1956. padsh->cbSrcLengthUsed,
  1957. (HPBYTE)padsh->pbDst,
  1958. (UINT)pwfadpcm->wfx.nBlockAlign,
  1959. (UINT)pwfadpcm->wSamplesPerBlock,
  1960. (UINT)pwfadpcm->wNumCoef,
  1961. (LPADPCMCOEFSET)&(pwfadpcm->aCoef[0])
  1962. );
  1963. }
  1964. #endif
  1965. return (MMSYSERR_NOERROR);
  1966. } // acmdStreamConvert()
  1967. //==========================================================================;
  1968. //
  1969. //
  1970. //
  1971. //
  1972. //==========================================================================;
  1973. //--------------------------------------------------------------------------;
  1974. //
  1975. // LRESULT DriverProc
  1976. //
  1977. // Description:
  1978. //
  1979. //
  1980. // Arguments:
  1981. // DWORD_PTR dwId: For most messages, dwId is the DWORD_PTR value that
  1982. // the driver returns in response to a DRV_OPEN message. Each time
  1983. // that the driver is opened, through the DrvOpen API, the driver
  1984. // receives a DRV_OPEN message and can return an arbitrary, non-zero
  1985. // value. The installable driver interface saves this value and returns
  1986. // a unique driver handle to the application. Whenever the application
  1987. // sends a message to the driver using the driver handle, the interface
  1988. // routes the message to this entry point and passes the corresponding
  1989. // dwId. This mechanism allows the driver to use the same or different
  1990. // identifiers for multiple opens but ensures that driver handles are
  1991. // unique at the application interface layer.
  1992. //
  1993. // The following messages are not related to a particular open instance
  1994. // of the driver. For these messages, the dwId will always be zero.
  1995. //
  1996. // DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN
  1997. //
  1998. // HDRVR hdrvr: This is the handle returned to the application
  1999. // by the driver interface.
  2000. //
  2001. // UINT uMsg: The requested action to be performed. Message
  2002. // values below DRV_RESERVED are used for globally defined messages.
  2003. // Message values from DRV_RESERVED to DRV_USER are used for defined
  2004. // driver protocols. Messages above DRV_USER are used for driver
  2005. // specific messages.
  2006. //
  2007. // LPARAM lParam1: Data for this message. Defined separately for
  2008. // each message.
  2009. //
  2010. // LPARAM lParam2: Data for this message. Defined separately for
  2011. // each message.
  2012. //
  2013. //
  2014. // Return (LRESULT):
  2015. // Defined separately for each message.
  2016. //
  2017. // History:
  2018. // 11/16/92 cjp [curtisp]
  2019. //
  2020. //--------------------------------------------------------------------------;
  2021. LRESULT FNEXPORT DriverProc
  2022. (
  2023. DWORD_PTR dwId,
  2024. HDRVR hdrvr,
  2025. UINT uMsg,
  2026. LPARAM lParam1,
  2027. LPARAM lParam2
  2028. )
  2029. {
  2030. LRESULT lr;
  2031. PCODECINST pci;
  2032. //
  2033. // make pci either NULL or a valid instance pointer. note that dwId
  2034. // is 0 for several of the DRV_* messages (ie DRV_LOAD, DRV_OPEN...)
  2035. // see acmdDriverOpen for information on what dwId is for other
  2036. // messages (instance data).
  2037. //
  2038. pci = (PCODECINST)dwId;
  2039. switch (uMsg)
  2040. {
  2041. //
  2042. // lParam1: Unused.
  2043. //
  2044. // lParam2: Unused.
  2045. //
  2046. case DRV_LOAD:
  2047. #ifdef WIN32
  2048. DbgInitialize(TRUE);
  2049. #endif
  2050. DPF(4, "DRV_LOAD");
  2051. return(1L);
  2052. //
  2053. // lParam1: Unused.
  2054. //
  2055. // lParam2: Unused.
  2056. //
  2057. case DRV_FREE:
  2058. DPF(4, "DRV_FREE");
  2059. return (1L);
  2060. //
  2061. // lParam1: Not used. Ignore this argument.
  2062. //
  2063. // lParam2: Pointer to ACMDRVOPENDESC (or NULL).
  2064. //
  2065. case DRV_OPEN:
  2066. DPF(4, "DRV_OPEN");
  2067. lr = acmdDriverOpen(hdrvr, (LPACMDRVOPENDESC)lParam2);
  2068. return (lr);
  2069. //
  2070. // lParam1: Unused.
  2071. //
  2072. // lParam2: Unused.
  2073. //
  2074. case DRV_CLOSE:
  2075. DPF(4, "DRV_CLOSE");
  2076. lr = acmdDriverClose(pci);
  2077. return (lr);
  2078. //
  2079. // lParam1: Unused.
  2080. //
  2081. // lParam2: Unused.
  2082. //
  2083. case DRV_INSTALL:
  2084. DPF(4, "DRV_INSTALL");
  2085. return ((LRESULT)DRVCNF_RESTART);
  2086. //
  2087. // lParam1: Unused.
  2088. //
  2089. // lParam2: Unused.
  2090. //
  2091. case DRV_REMOVE:
  2092. DPF(4, "DRV_REMOVE");
  2093. return ((LRESULT)DRVCNF_RESTART);
  2094. //
  2095. // lParam1: Not used.
  2096. //
  2097. // lParam2: Not used.
  2098. //
  2099. case DRV_QUERYCONFIGURE:
  2100. DPF(4, "DRV_QUERYCONFIGURE");
  2101. //
  2102. // set up lParam1 and lParam2 to values that can be used by
  2103. // acmdDriverConfigure to know that it is being 'queried'
  2104. // for hardware configuration support.
  2105. //
  2106. lParam1 = -1L;
  2107. lParam2 = 0L;
  2108. //--fall through--//
  2109. //
  2110. // lParam1: Handle to parent window for the configuration dialog
  2111. // box.
  2112. //
  2113. // lParam2: Optional pointer to DRVCONFIGINFO structure.
  2114. //
  2115. case DRV_CONFIGURE:
  2116. DPF(4, "DRV_CONFIGURE");
  2117. lr = acmdDriverConfigure(pci, (HWND)lParam1,
  2118. (LPDRVCONFIGINFO)lParam2);
  2119. return (lr);
  2120. //
  2121. // lParam1: Pointer to ACMDRIVERDETAILS structure.
  2122. //
  2123. // lParam2: Size in bytes of ACMDRIVERDETAILS stucture passed.
  2124. //
  2125. case ACMDM_DRIVER_DETAILS:
  2126. DPF(4, "ACMDM_DRIVER_DETAILS");
  2127. lr = acmdDriverDetails(pci, (LPACMDRIVERDETAILS)lParam1);
  2128. return (lr);
  2129. //
  2130. // lParam1: Handle to parent window to use if displaying your own
  2131. // about box.
  2132. //
  2133. // lParam2: Not used.
  2134. //
  2135. case ACMDM_DRIVER_ABOUT:
  2136. DPF(4, "ACMDM_DRIVER_ABOUT");
  2137. lr = acmdDriverAbout(pci, (HWND)lParam1);
  2138. return (lr);
  2139. //--------------------------------------------------------------------------;
  2140. //--------------------------------------------------------------------------;
  2141. //
  2142. // lParam1: Pointer to ACMDRVFORMATSUGGEST structure.
  2143. //
  2144. // lParam2: Not used.
  2145. //
  2146. case ACMDM_FORMAT_SUGGEST:
  2147. DPF(4, "ACMDM_FORMAT_SUGGEST");
  2148. lr = acmdFormatSuggest(pci, (LPACMDRVFORMATSUGGEST)lParam1 );
  2149. return (lr);
  2150. //
  2151. // lParam1: FORMATTAGDETAILS
  2152. //
  2153. // lParam2: Not used.
  2154. //
  2155. case ACMDM_FORMATTAG_DETAILS:
  2156. DPF(4, "ACMDM_FORMATTAG_DETAILS");
  2157. lr = acmdFormatTagDetails(pci, (LPACMFORMATTAGDETAILS)lParam1, (DWORD)lParam2);
  2158. return (lr);
  2159. //
  2160. // lParam1: FORMATDETAILS
  2161. //
  2162. // lParam2: fdwDetails
  2163. //
  2164. case ACMDM_FORMAT_DETAILS:
  2165. DPF(4, "ACMDM_FORMAT_DETAILS");
  2166. lr = acmdFormatDetails(pci, (LPACMFORMATDETAILS)lParam1, (DWORD)lParam2);
  2167. return (lr);
  2168. //--------------------------------------------------------------------------;
  2169. //--------------------------------------------------------------------------;
  2170. //
  2171. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2172. //
  2173. // lParam2: Not used.
  2174. //
  2175. case ACMDM_STREAM_OPEN:
  2176. DPF(4, "ACMDM_STREAM_OPEN");
  2177. lr = acmdStreamOpen(pci, (LPACMDRVSTREAMINSTANCE)lParam1);
  2178. return (lr);
  2179. //
  2180. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2181. //
  2182. // lParam2: Not Used.
  2183. //
  2184. case ACMDM_STREAM_CLOSE:
  2185. DPF(4, "ACMDM_STREAM_CLOSE");
  2186. lr = acmdStreamClose(pci, (LPACMDRVSTREAMINSTANCE)lParam1);
  2187. return (lr);
  2188. //
  2189. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2190. //
  2191. // lParam2: Pointer to ACMDRVSTREAMSIZE structure.
  2192. //
  2193. case ACMDM_STREAM_SIZE:
  2194. DPF(4, "ACMDM_STREAM_SIZE");
  2195. lr = acmdStreamSize(pci, (LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMSIZE)lParam2);
  2196. return (lr);
  2197. //
  2198. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2199. //
  2200. // lParam2: Pointer to ACMDRVSTREAMHEADER structure.
  2201. //
  2202. case ACMDM_STREAM_CONVERT:
  2203. DPF(4, "ACMDM_STREAM_CONVERT");
  2204. lr = acmdStreamConvert(pci, (LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMHEADER)lParam2);
  2205. return (lr);
  2206. }
  2207. //
  2208. // if we are executing the following code, then this codec does not
  2209. // handle the message that was sent. there are two ranges of messages
  2210. // we need to deal with:
  2211. //
  2212. // o ACM specific driver messages: if a codec does not answer a
  2213. // message sent in the ACM driver message range, then it must
  2214. // return MMSYSERR_NOTSUPPORTED. this applies to the 'user'
  2215. // range as well (for consistency).
  2216. //
  2217. // o Other installable driver messages: if a codec does not answer
  2218. // a message that is NOT in the ACM driver message range, then
  2219. // it must call DefDriverProc and return that result.
  2220. //
  2221. DPF(4, "OTHER MESSAGE RECEIVED BY DRIVERPROC");
  2222. if (uMsg >= ACMDM_USER)
  2223. return (MMSYSERR_NOTSUPPORTED);
  2224. else
  2225. return (DefDriverProc(dwId, hdrvr, uMsg, lParam1, lParam2));
  2226. } // DriverProc()