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.

3159 lines
100 KiB

  1. /* *************************************************************************
  2. ** INTEL Corporation Proprietary Information
  3. **
  4. ** This listing is supplied under the terms of a license
  5. ** agreement with INTEL Corporation and may not be copied
  6. ** nor disclosed except in accordance with the terms of
  7. ** that agreement.
  8. **
  9. ** Copyright (c) 1996 Intel Corporation.
  10. ** All Rights Reserved.
  11. **
  12. ** *************************************************************************
  13. ** codec.c
  14. **
  15. ** Description:
  16. ** This file contains the ACM wrapper code for the G.723.1 compressor.
  17. **
  18. **
  19. ****************************************************************************
  20. */
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <mmsystem.h>
  24. //#include <mmddk.h>
  25. #include <ctype.h>
  26. #include <mmreg.h>
  27. #include <msacm.h>
  28. #include <msacmdrv.h>
  29. #include "g723.h"
  30. #include "debug.h"
  31. //#include "cst_lbc.h"
  32. #include "coder.h"
  33. #include "decod.h"
  34. #include "sdstuff.h"
  35. #include "float.h"
  36. #ifdef DEBUG
  37. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  38. #include "isrg.h"
  39. #endif // } NO_DEBUGGING_OUTPUT
  40. #endif
  41. const UINT gauFormatTagIndexToTag[] =
  42. {
  43. WAVE_FORMAT_PCM,
  44. WAVE_FORMAT_MSG723
  45. };
  46. #define ACM_DRIVER_MAX_FORMAT_TAGS SIZEOF_ARRAY(gauFormatTagIndexToTag)
  47. #define ACM_DRIVER_MAX_FILTER_TAGS 0
  48. //
  49. // Required by config.c as well as codec.c.
  50. //
  51. #define ACM_DRIVER_MAX_BITSPERSAMPLE_PCM 1
  52. #define ACM_DRIVER_MAX_BITSPERSAMPLE_G723 0
  53. //extern void glblSDinitialize(CODDEF *CodStat);
  54. //extern void prefilter(CODDEF *CodStat,int bufsize);
  55. //extern void getParams(CODDEF *CodStat,int buffersize);
  56. //extern int initializeSD(CODDEF *CodStat);
  57. //extern int silenceDetect(CODDEF *CodStat);
  58. //extern void execSDloop(CODDEF *CodStat, int *isFrameSilent);
  59. //
  60. // number of formats we enumerate per channel is number of sample rates
  61. // times number of channels times number of types (bits per sample).
  62. //
  63. #define ACM_DRIVER_MAX_FORMATS_PCM 2
  64. #define ACM_DRIVER_MAX_FORMATS_G723 2
  65. //==========================================================================;
  66. //
  67. //
  68. //
  69. //
  70. //==========================================================================;
  71. static float SDThreashold = 5.0f; // silence converter threashold.
  72. #ifdef DEBUG
  73. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  74. static WORD ghISRInst = 0;
  75. #endif // } NO_DEBUGGING_OUTPUT
  76. #endif
  77. //--------------------------------------------------------------------------;
  78. //
  79. // int LoadStringCodec
  80. //
  81. // Description:
  82. // This function should be used by all codecs to load resource strings
  83. // which will be passed back to the ACM. It works correctly for all
  84. // platforms, as follows:
  85. //
  86. // Win16: Compiled to LoadString to load ANSI strings.
  87. //
  88. // Win32: The 32-bit ACM always expects Unicode strings. Therefore,
  89. // when UNICODE is defined, this function is compiled to
  90. // LoadStringW to load a Unicode string. When UNICODE is
  91. // not defined, this function loads an ANSI string, converts
  92. // it to Unicode, and returns the Unicode string to the
  93. // codec.
  94. //
  95. // Note that you may use LoadString for other strings (strings which
  96. // will not be passed back to the ACM), because these strings will
  97. // always be consistent with the definition of UNICODE.
  98. //
  99. // Arguments:
  100. // Same as LoadString, except that it expects an LPSTR for Win16 and a
  101. // LPWSTR for Win32.
  102. //
  103. // Return (int):
  104. // Same as LoadString.
  105. //
  106. //--------------------------------------------------------------------------;
  107. #ifndef _WIN32
  108. #define LoadStringCodec LoadString
  109. #else
  110. #ifdef UNICODE
  111. #define LoadStringCodec LoadStringW
  112. #else
  113. int FNGLOBAL LoadStringCodec
  114. (
  115. HINSTANCE hinst,
  116. UINT uID,
  117. LPWSTR lpwstr,
  118. int cch)
  119. {
  120. LPSTR lpstr;
  121. int iReturn;
  122. lpstr = (LPSTR)GlobalAlloc(GPTR, cch);
  123. if (NULL == lpstr)
  124. {
  125. return 0;
  126. }
  127. iReturn = LoadStringA(hinst, uID, lpstr, cch);
  128. if (0 == iReturn)
  129. {
  130. if (0 != cch)
  131. {
  132. lpwstr[0] = '\0';
  133. }
  134. }
  135. else
  136. {
  137. MultiByteToWideChar( GetACP(), 0, lpstr, cch, lpwstr, cch );
  138. }
  139. GlobalFree((HGLOBAL)lpstr);
  140. return iReturn;
  141. }
  142. #endif // UNICODE
  143. #endif // _WIN32
  144. //--------------------------------------------------------------------------;
  145. //
  146. // BOOL pcmIsValidFormat
  147. //
  148. // Description:
  149. // This function verifies that a wave format header is a valid PCM
  150. // header that we can deal with. Right now we are limited to an 8k
  151. // sampling rate. That should go to 8 and 11 shortly.
  152. //
  153. // Arguments:
  154. // LPWAVEFORMATEX pwfx: Pointer to format header to verify.
  155. //
  156. // Return (BOOL):
  157. // The return value is non-zero if the format header looks valid. A
  158. // zero return means the header is not valid.
  159. //
  160. //--------------------------------------------------------------------------;
  161. BOOL FNLOCAL pcmIsValidFormat
  162. (
  163. LPWAVEFORMATEX pwfx
  164. )
  165. {
  166. int i;
  167. if (NULL == pwfx)
  168. return (FALSE);
  169. if (WAVE_FORMAT_PCM != pwfx->wFormatTag)
  170. {
  171. #ifdef DEBUG
  172. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  173. TTDBG(ghISRInst,TT_TRACE,"Bad pcm wave format tag: %d",
  174. pwfx->wFormatTag);
  175. #endif // } NO_DEBUGGING_OUTPUT
  176. #endif
  177. return (FALSE);
  178. }
  179. //
  180. // verify nChannels member is within the allowed range
  181. //
  182. if ((pwfx->nChannels != G723_MAX_CHANNELS) )
  183. {
  184. #ifdef DEBUG
  185. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  186. TTDBG(ghISRInst,TT_TRACE,"Bad pcm channels: %d",pwfx->nChannels);
  187. #endif // } NO_DEBUGGING_OUTPUT
  188. #endif
  189. return (FALSE);
  190. }
  191. //
  192. // only allow the bits per sample that we can encode and decode with
  193. //
  194. if (16 != pwfx->wBitsPerSample )
  195. {
  196. #ifdef DEBUG
  197. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  198. TTDBG(ghISRInst,TT_TRACE,"Bad pcm bits per sample: %d",
  199. pwfx->wBitsPerSample);
  200. #endif // } NO_DEBUGGING_OUTPUT
  201. #endif
  202. return (FALSE);
  203. }
  204. //
  205. // only allow supported sampling rates
  206. //
  207. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  208. if (pwfx->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  209. break;
  210. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  211. {
  212. #ifdef DEBUG
  213. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  214. TTDBG(ghISRInst,TT_TRACE,"Bad pcm sampling rate: %d",
  215. pwfx->nSamplesPerSec);
  216. #endif // } NO_DEBUGGING_OUTPUT
  217. #endif
  218. return(FALSE);
  219. }
  220. //
  221. // now verify that the block alignment is correct..
  222. //
  223. if (PCM_BLOCKALIGNMENT(pwfx) != pwfx->nBlockAlign)
  224. {
  225. #ifdef DEBUG
  226. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  227. TTDBG(ghISRInst,TT_TRACE,"Bad pcm block alignment: %d",
  228. pwfx->nBlockAlign);
  229. #endif // } NO_DEBUGGING_OUTPUT
  230. #endif
  231. return (FALSE);
  232. }
  233. //
  234. // finally, verify that avg bytes per second is correct
  235. //
  236. if (PCM_AVGBYTESPERSEC(pwfx) != pwfx->nAvgBytesPerSec)
  237. {
  238. #ifdef DEBUG
  239. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  240. TTDBG(ghISRInst,TT_TRACE,"Bad pcm avg bytes per sec: %d",
  241. pwfx->nAvgBytesPerSec);
  242. #endif // } NO_DEBUGGING_OUTPUT
  243. #endif
  244. return (FALSE);
  245. }
  246. return (TRUE);
  247. }
  248. //--------------------------------------------------------------------------;
  249. //
  250. // BOOL G723IsValidFormat
  251. //
  252. // Description:
  253. // This function verifies that a wave format header is a valid
  254. // G.723.1 header that this ACM driver can deal with.
  255. //
  256. // Arguments:
  257. // LPWAVEFORMATEX pwfx: Pointer to format header to verify.
  258. //
  259. // Return (BOOL):
  260. // The return value is non-zero if the format header looks valid. A
  261. // zero return means the header is not valid.
  262. //
  263. //--------------------------------------------------------------------------;
  264. BOOL FNLOCAL g723IsValidFormat
  265. (
  266. LPWAVEFORMATEX pwfx
  267. )
  268. {
  269. // LPMSG723WAVEFORMAT pwfg723;
  270. if (NULL == pwfx)
  271. {
  272. #ifdef DEBUG
  273. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  274. TTDBG(ghISRInst,TT_TRACE,"Bad 723 format structure pointer");
  275. #endif // } NO_DEBUGGING_OUTPUT
  276. #endif
  277. return (FALSE);
  278. }
  279. if (WAVE_FORMAT_MSG723 != pwfx->wFormatTag)
  280. {
  281. #ifdef DEBUG
  282. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  283. TTDBG(ghISRInst,TT_TRACE,"Bad 723 format tag: %d",
  284. pwfx->wFormatTag);
  285. #endif // } NO_DEBUGGING_OUTPUT
  286. #endif
  287. return (FALSE);
  288. }
  289. //
  290. // check wBitsPerSample
  291. //
  292. if (G723_BITS_PER_SAMPLE != pwfx->wBitsPerSample)
  293. {
  294. #ifdef DEBUG
  295. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  296. TTDBG(ghISRInst,TT_TRACE,"Bad 723 bits per sample: %d",
  297. pwfx->wBitsPerSample);
  298. #endif // } NO_DEBUGGING_OUTPUT
  299. #endif
  300. return (FALSE);
  301. }
  302. //
  303. // check channels
  304. //
  305. if (pwfx->nChannels != G723_MAX_CHANNELS)
  306. {
  307. #ifdef DEBUG
  308. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  309. TTDBG(ghISRInst,TT_TRACE,"Bad 723 channels: %d",
  310. pwfx->nChannels);
  311. #endif // } NO_DEBUGGING_OUTPUT
  312. #endif
  313. return (FALSE);
  314. }
  315. //
  316. // Check block alignment - must be an integral number of DWORDs for
  317. // mono, or an even number of DWORDs for stereo.
  318. //
  319. if( 0 != pwfx->nBlockAlign % (sizeof(DWORD)) )
  320. {
  321. #ifdef DEBUG
  322. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  323. TTDBG(ghISRInst,TT_TRACE,"Bad 723 block alignment: %d",
  324. pwfx->nBlockAlign);
  325. #endif // } NO_DEBUGGING_OUTPUT
  326. #endif
  327. return FALSE;
  328. }
  329. if (G723_WFX_EXTRA_BYTES != pwfx->cbSize)
  330. {
  331. #ifdef DEBUG
  332. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  333. TTDBG(ghISRInst,TT_TRACE,"Bad 723 extra bytes: %d",
  334. pwfx->cbSize);
  335. #endif // } NO_DEBUGGING_OUTPUT
  336. #endif
  337. return (FALSE);
  338. }
  339. // pwfg723 = (LPMSG723WAVEFORMAT)pwfx;
  340. return (TRUE);
  341. }
  342. //--------------------------------------------------------------------------;
  343. //
  344. // UINT g723BlockAlign
  345. //
  346. // Description:
  347. // This function computes the standard block alignment that should
  348. // be used given the WAVEFORMATEX structure.
  349. //
  350. // NOTE! It is _assumed_ that the format is a valid G723 format
  351. // and that the following fields in the format structure are valid:
  352. //
  353. // nChannels
  354. // nSamplesPerSec
  355. //
  356. // Arguments:
  357. // LPWAVEFORMATEX pwfx: Pointer to format header.
  358. //
  359. // Return (UINT):
  360. // The return value is the block alignment that should be placed in
  361. // the pwfx->nBlockAlign field.
  362. //
  363. //--------------------------------------------------------------------------;
  364. UINT FNLOCAL g723BlockAlign
  365. (
  366. LPMSG723WAVEFORMAT pwfg723
  367. )
  368. {
  369. UINT uBlockAlign;
  370. if((pwfg723->wConfigWord&RATE) == Rate63)
  371. uBlockAlign = 24;
  372. else uBlockAlign = 20;
  373. return (uBlockAlign);
  374. }
  375. //--------------------------------------------------------------------------;
  376. //
  377. // UINT g723AvgBytesPerSec
  378. //
  379. // Description:
  380. // This function computes the Average Bytes Per Second (decoded!)
  381. // that should be used given the WAVEFORMATEX structure.
  382. //
  383. // NOTE! It is _assumed_ that the format is a valid g723 format
  384. // and that the following fields in the format structure are valid:
  385. //
  386. // nSamplesPerSec
  387. // nBlockAlign
  388. //
  389. // Arguments:
  390. // LPWAVEFORMATEX pwfx: Pointer to format header.
  391. //
  392. // Return (DWORD):
  393. // The return value is the average bytes per second that should be
  394. // placed in the pwfx->nAvgBytesPerSec field.
  395. //
  396. //--------------------------------------------------------------------------;
  397. DWORD FNLOCAL g723AvgBytesPerSec
  398. (
  399. LPWAVEFORMATEX pwfx
  400. )
  401. {
  402. int i;
  403. DWORD dwAvgBytesPerSec;
  404. //
  405. // compute bytes per second including header bytes
  406. //
  407. dwAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign)
  408. / G723_SAMPLES_PER_BLOCK_PCM[0];
  409. for(i=1;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  410. if (pwfx->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  411. dwAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign)
  412. / G723_SAMPLES_PER_BLOCK_PCM[i];
  413. return (dwAvgBytesPerSec);
  414. }
  415. //--------------------------------------------------------------------------;
  416. //
  417. // LRESULT acmdDriverOpen
  418. //
  419. // Description:
  420. // This function is used to handle the DRV_OPEN message for the ACM
  421. // driver. The driver is 'opened' for many reasons with the most common
  422. // being in preperation for conversion work. It is very important that
  423. // the driver be able to correctly handle multiple open driver
  424. // instances.
  425. //
  426. // Read the comments for this function carefully!
  427. //
  428. // Note that multiple _streams_ can (and will) be opened on a single
  429. // open _driver instance_. Do not store/create instance data that must
  430. // be unique for each stream in this function. See the acmdStreamOpen
  431. // function for information on conversion streams.
  432. //
  433. // Arguments:
  434. // HDRVR hdrvr: Driver handle that will be returned to caller of the
  435. // OpenDriver function. Normally, this will be the ACM--but this is
  436. // not guaranteed. For example, if an ACM driver is implemented within
  437. // a waveform driver, then the driver will be opened by both MMSYSTEM
  438. // and the ACM.
  439. //
  440. // LPACMDRVOPENDESC paod: Open description defining how the ACM driver
  441. // is being opened. This argument may be NULL--see the comments below
  442. // for more information.
  443. //
  444. // Return (LRESULT):
  445. // The return value is non-zero if the open is successful. A zero
  446. // return signifies that the driver cannot be opened.
  447. //
  448. //--------------------------------------------------------------------------;
  449. LRESULT FNLOCAL acmdDriverOpen
  450. (
  451. HDRVR hdrvr,
  452. LPACMDRVOPENDESC paod
  453. )
  454. {
  455. PDRIVERINSTANCE pdi;
  456. //
  457. // the [optional] open description that is passed to this driver can
  458. // be from multiple 'managers.' for example, AVI looks for installable
  459. // drivers that are tagged with 'vidc' and 'vcap'. we need to verify
  460. // that we are being opened as an Audio Compression Manager driver.
  461. //
  462. // if paod is NULL, then the driver is being opened for some purpose
  463. // other than converting (that is, there will be no stream open
  464. // requests for this instance of being opened). the most common case
  465. // of this is the Control Panel's Drivers option checking for config
  466. // support (DRV_[QUERY]CONFIGURE).
  467. //
  468. // we want to succeed this open, but be able to know that this
  469. // open instance is bogus for creating streams. for this purpose we
  470. // leave most of the members of our instance structure that we
  471. // allocate below as zero...
  472. //
  473. // for some reason, floating point exceptions will crash Win9x
  474. // machines. They should be getting ignored. The only work-around
  475. // is to call _fpreset to force the floating point control word to
  476. // be reinitialized
  477. _fpreset();
  478. if (NULL != paod)
  479. {
  480. //
  481. // refuse to open if we are not being opened as an ACM driver.
  482. // note that we do NOT modify the value of paod->dwError in this
  483. // case.
  484. //
  485. if (ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC != paod->fccType)
  486. return (0L);
  487. }
  488. //
  489. // we are being opened as an installable driver--we can allocate some
  490. // instance data to be returned in dwId argument of the DriverProc;
  491. // or simply return non-zero to succeed the open.
  492. //
  493. // this driver allocates a small instance structure. note that we
  494. // rely on allocating the memory as zero-initialized!
  495. //
  496. pdi = (PDRIVERINSTANCE)LocalAlloc(LPTR, sizeof(*pdi));
  497. if (NULL == pdi)
  498. {
  499. //
  500. // if this open attempt was as an ACM driver, then return the
  501. // reason we are failing in the open description structure..
  502. //
  503. if (NULL != paod)
  504. {
  505. paod->dwError = MMSYSERR_NOMEM;
  506. }
  507. return (0L);
  508. }
  509. #ifdef NOTPRODUCT
  510. pdi->enabled = TRUE;
  511. #else
  512. pdi->enabled = FALSE;
  513. #endif
  514. pdi->hdrvr = hdrvr;
  515. pdi->hinst = GetDriverModuleHandle(hdrvr); // Module handle.
  516. if (NULL != paod)
  517. {
  518. pdi->fnDriverProc = NULL;
  519. pdi->fccType = paod->fccType;
  520. pdi->vdwACM = paod->dwVersion;
  521. pdi->fdwOpen = paod->dwFlags;
  522. paod->dwError = MMSYSERR_NOERROR;
  523. }
  524. #ifdef G723_USECONFIG
  525. //
  526. // Get config info for this driver. If we're not passed an
  527. // ACMDRVOPENDESC structure then we'll assume we are being
  528. // opened for configuration and will put off getting the config
  529. // info until we receive the DRV_CONFIGURE message. Otherwise we
  530. // get the config info now using the alias passed through the
  531. // ACMDRVOPENDESC structure.
  532. //
  533. pdi->hkey = NULL; // This is important!
  534. if (NULL != paod)
  535. {
  536. #if defined(_WIN32) && !defined(UNICODE)
  537. //
  538. // We must translate the UNICODE alias name to an ANSI version
  539. // that we can use.
  540. //
  541. LPSTR lpstr;
  542. int iLen;
  543. //
  544. // Calculate required length without calling UNICODE APIs or CRT.
  545. //
  546. iLen = WideCharToMultiByte( GetACP(), 0, paod->pszAliasName,-1,
  547. NULL, 0, NULL, NULL );
  548. lpstr = (LPSTR)GlobalAllocPtr( GPTR, iLen );
  549. if (NULL != lpstr)
  550. {
  551. WideCharToMultiByte( GetACP(), 0, paod->pszAliasName, iLen,
  552. lpstr, iLen, NULL, NULL );
  553. }
  554. acmdDriverConfigInit(pdi, lpstr); // Note: OK to pass lpstr==NULL
  555. if (NULL != lpstr)
  556. {
  557. GlobalFreePtr( lpstr );
  558. }
  559. #else
  560. acmdDriverConfigInit(pdi, paod->pszAliasName);
  561. #endif // _WIN32 && !UNICODE
  562. }
  563. #else
  564. //
  565. // Actually, fdwConfig is not used - there is no configuration data.
  566. //
  567. pdi->fdwConfig = 0L;
  568. #endif // G723_USECONFIG
  569. //
  570. // non-zero return is success for DRV_OPEN
  571. //
  572. #ifdef DEBUG
  573. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  574. ISRREGISTERMODULE(&ghISRInst,"G723ACM","G.723.1 ACM Driver");
  575. TTDBG(ghISRInst,TT_TRACE,"Driver Opened");
  576. #endif // } NO_DEBUGGING_OUTPUT
  577. #endif
  578. return ((LRESULT)(UINT)pdi);
  579. }
  580. //--------------------------------------------------------------------------;
  581. //
  582. // LRESULT acmdDriverClose
  583. //
  584. // Description:
  585. // This function handles the DRV_CLOSE message for the ACM driver. The
  586. // driver receives a DRV_CLOSE message for each succeeded DRV_OPEN
  587. // message (see acmdDriverOpen). The driver will only receive a close
  588. // message for _successful_ opens.
  589. //
  590. // Arguments:
  591. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  592. // This structure is [optionally] allocated during the DRV_OPEN message
  593. // which is handled by the acmdDriverOpen function.
  594. //
  595. // Return (LRESULT):
  596. // The return value is non-zero if the open instance can be closed.
  597. // A zero return signifies that the ACM driver instance could not be
  598. // closed.
  599. //
  600. // NOTE! It is _strongly_ recommended that the driver never fail to
  601. // close. Note that the ACM will never allow a driver instance to
  602. // be closed if there are open streams. An ACM driver does not need
  603. // to check for this case.
  604. //
  605. //--------------------------------------------------------------------------;
  606. LRESULT FNLOCAL acmdDriverClose
  607. (
  608. PDRIVERINSTANCE pdi
  609. )
  610. {
  611. #ifdef G723_USECONFIG
  612. //
  613. // Release the registry key, if we allocated one.
  614. //
  615. if( NULL != pdi->hkey )
  616. {
  617. (void)RegCloseKey( pdi->hkey );
  618. }
  619. #endif
  620. //
  621. // check to see if we allocated instance data. if we did not, then
  622. // immediately succeed.
  623. //
  624. if (NULL != pdi)
  625. {
  626. //
  627. // close down the driver instance. this driver simply needs
  628. // to free the instance data structure... note that if this
  629. // 'free' fails, then this ACM driver probably trashed its
  630. // heap; assume we didn't do that.
  631. //
  632. LocalFree((HLOCAL)pdi);
  633. }
  634. return (1L);
  635. } // acmdDriverClose()
  636. //--------------------------------------------------------------------------;
  637. //
  638. // LRESULT acmdDriverConfigure
  639. //
  640. // Description:
  641. // This function is called to handle the DRV_[QUERY]CONFIGURE messages.
  642. // These messages are for 'configuration' support of the driver.
  643. // Normally this will be for 'hardware'--that is, a dialog should be
  644. // displayed to configure ports, IRQ's, memory mappings, etc if it
  645. // needs to. However, a software only ACM driver may also require
  646. // configuration for 'what is real time' or other quality vs time
  647. // issues.
  648. //
  649. // The most common way that these messages are generated under Win 3.1
  650. // and NT Product 1 is from the Control Panel's Drivers option. Other
  651. // sources may generate these messages in future versions of Windows.
  652. //
  653. // Arguments:
  654. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  655. // This structure is [optionally] allocated during the DRV_OPEN message
  656. // which is handled by the acmdDriverOpen function.
  657. //
  658. // HWND hwnd: Handle to parent window to use when displaying the
  659. // configuration dialog box. An ACM driver is _required_ to display a
  660. // modal dialog box using this hwnd argument as the parent. This
  661. // argument may be (HWND)-1 which tells the driver that it is only
  662. // being queried for configuration support.
  663. //
  664. // LPDRVCONFIGINFO pdci: Pointer to optional DRVCONFIGINFO structure.
  665. // If this argument is NULL, then the ACM driver should invent its own
  666. // storage location.
  667. //
  668. // Return (LRESULT):
  669. // If the driver is being 'queried' for configuration support (that is,
  670. // hwnd == (HWND)-1), then non-zero should be returned specifying
  671. // the driver does support a configuration dialog--or zero should be
  672. // returned specifying that no configuration dialog is supported.
  673. //
  674. // If the driver is being called to display the configuration dialog
  675. // (that is, hwnd != (HWND)-1), then one of the following values
  676. // should be returned:
  677. //
  678. // DRVCNF_CANCEL (0x0000): specifies that the dialog was displayed
  679. // and canceled by the user. this value should also be returned if
  680. // no configuration information was modified.
  681. //
  682. // DRVCNF_OK (0x0001): specifies that the dialog was displayed and
  683. // the user pressed OK. This value should be returned even if the
  684. // user didn't change anything - otherwise, the driver may not
  685. // install properly.
  686. //
  687. // DRVCNF_RESTART (0x0002): specifies that the dialog was displayed
  688. // and some configuration information was changed that requires
  689. // Windows to be restarted before the changes take affect. the driver
  690. // should remain configured with current values until the driver
  691. // has been 'rebooted'.
  692. //
  693. //--------------------------------------------------------------------------;
  694. LRESULT FNLOCAL acmdDriverConfigure
  695. (
  696. PDRIVERINSTANCE pdi,
  697. HWND hwnd,
  698. LPDRVCONFIGINFO pdci
  699. )
  700. {
  701. // int n;
  702. //
  703. // first check to see if we are only being queried for configuration
  704. // support. if hwnd == (HWND)-1 then we are being queried and should
  705. // return zero for 'not supported' and non-zero for 'supported'.
  706. //
  707. if ((HWND)-1 == hwnd)
  708. {
  709. #ifdef G723_USECONFIG
  710. //
  711. // this ACM driver supports a configuration dialog box, so
  712. // return non-zero...
  713. //
  714. return (1L);
  715. #else
  716. return(0L);
  717. #endif
  718. }
  719. //
  720. // we are being asked to bring up our configuration dialog. if this
  721. // driver supports a configuration dialog box, then after the dialog
  722. // is dismissed we must return one of the following values:
  723. //
  724. // DRVCNF_CANCEL (0x0000): specifies that the dialog was displayed
  725. // and canceled by the user. this value should also be returned if
  726. // no configuration information was modified.
  727. //
  728. // DRVCNF_OK (0x0001): specifies that the dialog was displayed and
  729. // the user pressed OK. This value should be returned even if the
  730. // user didn't change anything - otherwise, the driver may not
  731. // install properly.
  732. //
  733. // DRVCNF_RESTART (0x0002): specifies that the dialog was displayed
  734. // and some configuration information was changed that requires
  735. // Windows to be restarted before the changes take affect. the driver
  736. // should remain configured with current values until the driver
  737. // has been 'rebooted'.
  738. //
  739. #ifdef G723_USECONFIG
  740. if (NULL == pdci)
  741. {
  742. //
  743. // !!!
  744. //
  745. DPF(2,"acmdDriverConfigure returning CANCEL due to NULL==pdci.");
  746. return (DRVCNF_CANCEL);
  747. }
  748. pdi->pdci = pdci;
  749. //
  750. // We may not have our config info yet if the driver has only been
  751. // opened specifically for configuration. So, read our configuration
  752. // using the alias passed in the DRVCONFIGINFO structure passed
  753. // through the DRV_CONFIGURE message
  754. //
  755. #if (defined(_WIN32) && !defined(UNICODE))
  756. {
  757. //
  758. // We must translate the UNICODE alias name to an ANSI version
  759. // that we can use.
  760. //
  761. LPSTR lpstr;
  762. int iLen;
  763. //
  764. // Calculate required length without calling UNICODE APIs or CRT.
  765. //
  766. iLen = WideCharToMultiByte( GetACP(), 0, pdci->lpszDCIAliasName, -1,
  767. NULL, 0, NULL, NULL );
  768. lpstr = (LPSTR)GlobalAllocPtr( GPTR, iLen );
  769. if (NULL != lpstr)
  770. {
  771. WideCharToMultiByte( GetACP(), 0, pdci->lpszDCIAliasName, iLen,
  772. lpstr, iLen, NULL, NULL );
  773. }
  774. acmdDriverConfigInit(pdi, lpstr); // Note: OK to pass lpstr==NULL
  775. if (NULL != lpstr)
  776. {
  777. GlobalFreePtr( lpstr );
  778. }
  779. }
  780. #else
  781. acmdDriverConfigInit(pdi, pdci->lpszDCIAliasName);
  782. #endif // _WIN32 && !UNICODE
  783. n = DialogBoxParam(pdi->hinst,
  784. IDD_CONFIG,
  785. hwnd,
  786. acmdDlgProcConfigure,
  787. (LPARAM)(UINT)pdi);
  788. pdi->pdci = NULL;
  789. return ((LRESULT)n);
  790. #else
  791. return(DRVCNF_CANCEL);
  792. #endif // G723_USECONFIG
  793. }
  794. //--------------------------------------------------------------------------;
  795. //
  796. // LRESULT acmdDriverDetails
  797. //
  798. // Description:
  799. // This function handles the ACMDM_DRIVER_DETAILS message. The ACM
  800. // driver is responsible for filling in the ACMDRIVERDETAILS structure
  801. // with various information.
  802. //
  803. // NOTE! It is *VERY* important that you fill in your ACMDRIVERDETAILS
  804. // structure correctly. The ACM and applications must be able to
  805. // rely on this information.
  806. //
  807. // WARNING! The _reserved_ bits of any fields of the ACMDRIVERDETAILS
  808. // structure are _exactly that_: RESERVED. Do NOT use any extra
  809. // flag bits, etc. for custom information. The proper way to add
  810. // custom capabilities to your ACM driver is this:
  811. //
  812. // o define a new message in the ACMDM_USER range.
  813. //
  814. // o an application that wishes to use one of these extra features
  815. // should then:
  816. //
  817. // o open the driver with acmDriverOpen.
  818. //
  819. // o check for the proper wMid and wPid using acmDriverDetails.
  820. //
  821. // o send the 'user defined' message with acmDriverMessage
  822. // to retrieve additional information, etc.
  823. //
  824. // o close the driver with acmDriverClose.
  825. //
  826. // Arguments:
  827. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  828. // This structure is [optionally] allocated during the DRV_OPEN message
  829. // which is handled by the acmdDriverOpen function.
  830. //
  831. // LPACMDRIVERDETAILS padd: Pointer to ACMDRIVERDETAILS structure to
  832. // fill in for the caller. This structure may be larger or smaller than
  833. // the current definition of ACMDRIVERDETAILS--cbStruct specifies the
  834. // valid size.
  835. //
  836. // Return (LRESULT):
  837. // The return value is zero (MMSYSERR_NOERROR) for success. Non-zero
  838. // signifies that the driver details could not be retrieved.
  839. //
  840. // NOTE THAT THIS FUNCTION SHOULD NEVER FAIL! There are two possible
  841. // error conditions:
  842. //
  843. // o if padd is NULL or an invalid pointer.
  844. //
  845. // o if cbStruct is less than four; in this case, there is not enough
  846. // room to return the number of bytes filled in.
  847. //
  848. // Because these two error conditions are easily defined, the ACM
  849. // will catch these errors. The driver does NOT need to check for these
  850. // conditions.
  851. //
  852. //--------------------------------------------------------------------------;
  853. LRESULT FNLOCAL acmdDriverDetails
  854. (
  855. PDRIVERINSTANCE pdi,
  856. LPACMDRIVERDETAILS padd
  857. )
  858. {
  859. ACMDRIVERDETAILS add;
  860. DWORD cbStruct;
  861. //
  862. // it is easiest to fill in a temporary structure with valid info
  863. // and then copy the requested number of bytes to the destination
  864. // buffer.
  865. //
  866. cbStruct = min(padd->cbStruct, sizeof(ACMDRIVERDETAILS));
  867. add.cbStruct = cbStruct;
  868. //
  869. // for the current implementation of an ACM driver, the fccType and
  870. // fccComp members *MUST* always be ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
  871. // ('audc') and ACMDRIVERDETAILS_FCCCOMP_UNDEFINED (0) respectively.
  872. //
  873. add.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
  874. add.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
  875. //
  876. // the manufacturer id (wMid) and product id (wPid) must be filled
  877. // in with your company's _registered_ identifier's. for more
  878. // information on these identifier's and how to get them registered
  879. // contact Microsoft and get the Multimedia Developer Registration Kit:
  880. //
  881. // Microsoft Corporation
  882. // Multimedia Technology Group
  883. // One Microsoft Way
  884. // Redmond, WA 98052-6399
  885. //
  886. // Developer Services Phone: (800) 227-4679 x11771
  887. //
  888. // note that during the development phase or your ACM driver, you may
  889. // use the reserved value of '0' for both wMid and wPid. however it
  890. // is not acceptable to ship a driver with these values.
  891. //
  892. add.wMid = MM_MICROSOFT;
  893. add.wPid = NETMEETING_MSG723_ACM_ID;
  894. //
  895. // the vdwACM and vdwDriver members contain version information for
  896. // the driver.
  897. //
  898. // vdwACM: must contain the version of the *ACM* that the driver was
  899. // _designed_ for. this is the _minimum_ version number of the ACM
  900. // that the driver will work with. this value must be >= V2.00.000.
  901. //
  902. // vdwDriver: the version of this ACM driver.
  903. //
  904. // ACM driver versions are 32 bit numbers broken into three parts as
  905. // follows (note these parts are displayed as decimal values):
  906. //
  907. // bits 24 - 31: 8 bit _major_ version number
  908. // bits 16 - 23: 8 bit _minor_ version number
  909. // bits 0 - 15: 16 bit build number
  910. //
  911. add.vdwACM = VERSION_MSACM;
  912. add.vdwDriver = VERSION_ACM_DRIVER;
  913. //
  914. // the following flags are used to specify the type of conversion(s)
  915. // that the ACM driver supports. note that a driver may support one or
  916. // more of these flags in any combination.
  917. //
  918. // ACMDRIVERDETAILS_SUPPORTF_CODEC: this flag is set if the driver
  919. // supports conversions from one format tag to another format tag. for
  920. // example, if a converter compresses or decompresses WAVE_FORMAT_PCM
  921. // and WAVE_FORMAT_IMA_ADPCM, then this bit should be set. this is
  922. // true even if the data is not actually changed in size--for example
  923. // a conversion from u-Law to A-Law will still set this bit because
  924. // the format tags differ.
  925. //
  926. // ACMDRIVERDETAILS_SUPPORTF_CONVERTER: this flags is set if the
  927. // driver supports conversions on the same format tag. as an example,
  928. // the PCM converter that is built into the ACM sets this bit (and only
  929. // this bit) because it converts only between PCM formats (bits, sample
  930. // rate).
  931. //
  932. // ACMDRIVERDETAILS_SUPPORTF_FILTER: this flag is set if the driver
  933. // supports transformations on a single format tag but does change
  934. // the base characteristics of the format (bit depth, sample rate, etc
  935. // will remain the same). for example, a driver that changed the
  936. // 'volume' of PCM data or applied a low pass filter would set this bit.
  937. //
  938. add.fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  939. //
  940. // the number of individual format tags this ACM driver supports. for
  941. // example, if a driver uses the WAVE_FORMAT_IMA_ADPCM and
  942. // WAVE_FORMAT_PCM format tags, then this value would be two. if the
  943. // driver only supports filtering on WAVE_FORMAT_PCM, then this value
  944. // would be one. if this driver supported WAVE_FORMAT_ALAW,
  945. // WAVE_FORMAT_MULAW and WAVE_FORMAT_PCM, then this value would be
  946. // three. etc, etc.
  947. //
  948. add.cFormatTags = ACM_DRIVER_MAX_FORMAT_TAGS;
  949. //
  950. // the number of individual filter tags this ACM driver supports. if
  951. // a driver supports no filters (ACMDRIVERDETAILS_SUPPORTF_FILTER is
  952. // NOT set in the fdwSupport member), then this value must be zero.
  953. //
  954. add.cFilterTags = ACM_DRIVER_MAX_FILTER_TAGS;
  955. //
  956. // the remaining members in the ACMDRIVERDETAILS structure are sometimes
  957. // not needed. because of this we make a quick check to see if we
  958. // should go through the effort of filling in these members.
  959. //
  960. if (FIELD_OFFSET(ACMDRIVERDETAILS, hicon) < cbStruct)
  961. {
  962. //
  963. // fill in the hicon member will a handle to a custom icon for
  964. // the ACM driver. this allows the driver to be represented by
  965. // an application graphically (usually this will be a company
  966. // logo or something). if a driver does not wish to have a custom
  967. // icon displayed, then simply set this member to NULL and a
  968. // generic icon will be displayed instead.
  969. //
  970. // See the MSFILTER sample for a codec which contains a custom icon.
  971. //
  972. add.hicon = NULL;
  973. //
  974. // the short name and long name are used to represent the driver
  975. // in a unique description. the short name is intended for small
  976. // display areas (for example, in a menu or combo box). the long
  977. // name is intended for more descriptive displays (for example,
  978. // in an 'about box').
  979. //
  980. // NOTE! an ACM driver should never place formatting characters
  981. // of any sort in these strings (for example CR/LF's, etc). it
  982. // is up to the application to format the text.
  983. //
  984. LoadStringCodec(pdi->hinst, IDS_ACM_DRIVER_SHORTNAME, add.szShortName, SIZEOFACMSTR(add.szShortName));
  985. LoadStringCodec(pdi->hinst, IDS_ACM_DRIVER_LONGNAME, add.szLongName, SIZEOFACMSTR(add.szLongName));
  986. //
  987. // the last three members are intended for 'about box' information.
  988. // these members are optional and may be zero length strings if
  989. // the driver wishes.
  990. //
  991. // NOTE! an ACM driver should never place formatting characters
  992. // of any sort in these strings (for example CR/LF's, etc). it
  993. // is up to the application to format the text.
  994. //
  995. if (FIELD_OFFSET(ACMDRIVERDETAILS, szCopyright) < cbStruct)
  996. {
  997. LoadStringCodec(pdi->hinst, IDS_ACM_DRIVER_COPYRIGHT, add.szCopyright, SIZEOFACMSTR(add.szCopyright));
  998. LoadStringCodec(pdi->hinst, IDS_ACM_DRIVER_LICENSING, add.szLicensing, SIZEOFACMSTR(add.szLicensing));
  999. LoadStringCodec(pdi->hinst, IDS_ACM_DRIVER_FEATURES, add.szFeatures, SIZEOFACMSTR(add.szFeatures));
  1000. }
  1001. }
  1002. //
  1003. // now copy the correct number of bytes to the caller's buffer
  1004. //
  1005. _fmemcpy(padd, &add, (UINT)add.cbStruct);
  1006. //
  1007. // success!
  1008. //
  1009. return (MMSYSERR_NOERROR);
  1010. }
  1011. //--------------------------------------------------------------------------;
  1012. //
  1013. // LRESULT acmdDriverAbout
  1014. //
  1015. // Description:
  1016. // This function is called to handle the ACMDM_DRIVER_ABOUT message.
  1017. // An ACM driver has the option of displaying its own 'about box' or
  1018. // letting the ACM (or calling application) display one for it. This
  1019. // message is normally sent by the Control Panel's Sound Mapper
  1020. // option.
  1021. //
  1022. // It is recommended that an ACM driver allow a default about box
  1023. // be displayed for it--there should be no reason to bloat the size
  1024. // of a driver to simply display copyright, etc information when that
  1025. // information is contained in the ACMDRIVERDETAILS structure.
  1026. //
  1027. // Arguments:
  1028. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  1029. // This structure is [optionally] allocated during the DRV_OPEN message
  1030. // which is handled by the acmdDriverOpen function.
  1031. //
  1032. // HWND hwnd: Handle to parent window to use when displaying the
  1033. // configuration dialog box. An ACM driver is _required_ to display a
  1034. // modal dialog box using this hwnd argument as the parent. This
  1035. // argument may be (HWND)-1 which tells the driver that it is only
  1036. // being queried for about box support.
  1037. //
  1038. // Return (LRESULT):
  1039. // The return value is MMSYSERR_NOTSUPPORTED if the ACM driver does
  1040. // not support a custom dialog box. In this case, the ACM or calling
  1041. // application will display a generic about box using the information
  1042. // contained in the ACMDRIVERDETAILS structure returned by the
  1043. // ACMDM_DRIVER_DETAILS message.
  1044. //
  1045. // If the driver chooses to display its own dialog box, then after
  1046. // the dialog is dismissed by the user, MMSYSERR_NOERROR should be
  1047. // returned.
  1048. //
  1049. // If the hwnd argument is equal to (HWND)-1, then no dialog should
  1050. // be displayed (the driver is only being queried for support). The
  1051. // driver must still return MMSYSERR_NOERROR (supported) or
  1052. // MMSYSERR_NOTSUPPORTED (no custom about box supported).
  1053. //
  1054. //--------------------------------------------------------------------------;
  1055. LRESULT FNLOCAL acmdDriverAbout
  1056. (
  1057. PDRIVERINSTANCE pdi,
  1058. HWND hwnd
  1059. )
  1060. {
  1061. //
  1062. // first check to see if we are only being queried for custom about
  1063. // box support. if hwnd == (HWND)-1 then we are being queried and
  1064. // should return MMSYSERR_NOTSUPPORTED for 'not supported' and
  1065. // MMSYSERR_NOERROR for 'supported'.
  1066. //
  1067. if ((HWND)-1 == hwnd)
  1068. {
  1069. //
  1070. // this ACM driver does NOT support a custom about box, so
  1071. // return MMSYSERR_NOTSUPPORTED...
  1072. //
  1073. return (MMSYSERR_NOTSUPPORTED);
  1074. }
  1075. //
  1076. // this driver does not support a custom dialog, so tell the ACM or
  1077. // calling application to display one for us. note that this is the
  1078. // _recommended_ method for consistency and simplicity of ACM drivers.
  1079. // why write code when you don't have to?
  1080. //
  1081. return (MMSYSERR_NOTSUPPORTED);
  1082. }
  1083. //--------------------------------------------------------------------------;
  1084. //
  1085. // LRESULT acmdFormatSuggest
  1086. //
  1087. // Description:
  1088. // This function handles the ACMDM_FORMAT_SUGGEST message. The purpose
  1089. // of this function is to provide a way for the ACM, a wave mapper or
  1090. // an application to quickly get a destination format that this driver
  1091. // can convert the source format to. The 'suggested' format should
  1092. // be as close to a common format as possible. This message is normally
  1093. // sent in response to an acmFormatSuggest function call.
  1094. //
  1095. // Another way to think about this message is: what format would this
  1096. // driver like to convert the source format to?
  1097. //
  1098. // The caller may place restrictions on the destination format that
  1099. // should be suggested. The padfs->fdwSuggest member contains the
  1100. // restriction bits passed by the caller--see the description for
  1101. // the return value for more information.
  1102. //
  1103. // Arguments:
  1104. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  1105. // This structure is [optionally] allocated during the DRV_OPEN message
  1106. // which is handled by the acmdDriverOpen function.
  1107. //
  1108. // LPACMDRVFORMATSUGGEST padfs: Pointer to an ACMDRVFORMATSUGGEST
  1109. // structure that describes the source and destination (possibly with
  1110. // restrictions) for a conversion.
  1111. //
  1112. // Return (LRESULT):
  1113. // The return value is zero (MMSYSERR_NOERROR) if this function
  1114. // succeeds with no errors. The return value is a non-zero error code
  1115. // if the function fails.
  1116. //
  1117. // The driver should return MMSYSERR_NOTSUPPORTED if one or more of
  1118. // the destination restriction bits is not supported. It is strongly
  1119. // recommended that the driver support at least the following suggestion
  1120. // restriction bits:
  1121. //
  1122. // ACM_FORMATSUGGESTF_WFORMATTAG: The destination format tag must be
  1123. // the same as the wFormatTag member in the destination format header.
  1124. //
  1125. // ACM_FORMATSUGGESTF_NCHANNELS: The destination channel count must be
  1126. // the same as the nChannels member in the destination format header.
  1127. //
  1128. // ACM_FORMATSUGGESTF_NSAMPLESPERSEC: The destination samples per
  1129. // second must be the same as the nSamplesPerSec member in the
  1130. // destination format header.
  1131. //
  1132. // ACM_FORMATSUGGESTF_WBITSPERSAMPLE: The destination bits per sample
  1133. // must be the same as the wBitsPerSample member in the destination
  1134. // format header.
  1135. //
  1136. // If no destintation format can be suggested, then the driver should
  1137. // return ACMERR_NOTPOSSIBLE.
  1138. //
  1139. //--------------------------------------------------------------------------;
  1140. LRESULT FNLOCAL acmdFormatSuggest
  1141. (
  1142. PDRIVERINSTANCE pdi,
  1143. LPACMDRVFORMATSUGGEST padfs
  1144. )
  1145. {
  1146. #define ACMD_FORMAT_SUGGEST_SUPPORT (ACM_FORMATSUGGESTF_WFORMATTAG | \
  1147. ACM_FORMATSUGGESTF_NCHANNELS | \
  1148. ACM_FORMATSUGGESTF_NSAMPLESPERSEC |\
  1149. ACM_FORMATSUGGESTF_WBITSPERSAMPLE)
  1150. LPWAVEFORMATEX pwfxSrc;
  1151. LPWAVEFORMATEX pwfxDst;
  1152. LPMSG723WAVEFORMAT pwfg723;
  1153. DWORD fdwSuggest;
  1154. int i;
  1155. //
  1156. // grab the suggestion restriction bits and verify that we support
  1157. // the ones that are specified... an ACM driver must return the
  1158. // MMSYSERR_NOTSUPPORTED if the suggestion restriction bits specified
  1159. // are not supported.
  1160. //
  1161. fdwSuggest = (ACM_FORMATSUGGESTF_TYPEMASK & padfs->fdwSuggest);
  1162. if (~ACMD_FORMAT_SUGGEST_SUPPORT & fdwSuggest)
  1163. return (MMSYSERR_NOTSUPPORTED);
  1164. //
  1165. // get the source and destination formats in more convenient variables
  1166. //
  1167. pwfxSrc = padfs->pwfxSrc;
  1168. pwfxDst = padfs->pwfxDst;
  1169. //
  1170. //
  1171. //
  1172. //
  1173. switch (pwfxSrc->wFormatTag)
  1174. {
  1175. case WAVE_FORMAT_PCM:
  1176. //
  1177. // strictly verify that the source format is acceptable for
  1178. // this driver
  1179. //
  1180. if (!pcmIsValidFormat(pwfxSrc))
  1181. break;
  1182. //
  1183. // if the destination format tag is restricted, verify that
  1184. // it is within our capabilities...
  1185. //
  1186. // this driver is only able to encode to G.723.1
  1187. //
  1188. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  1189. {
  1190. if (WAVE_FORMAT_MSG723 != pwfxDst->wFormatTag)
  1191. return (ACMERR_NOTPOSSIBLE);
  1192. }
  1193. else
  1194. {
  1195. pwfxDst->wFormatTag = WAVE_FORMAT_MSG723;
  1196. }
  1197. //
  1198. // if the destination channel count is restricted, verify that
  1199. // it is within our capabilities...
  1200. //
  1201. // this driver is not able to handle more than 1 channel
  1202. //
  1203. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  1204. {
  1205. if (pwfxSrc->nChannels != G723_MAX_CHANNELS)
  1206. return (ACMERR_NOTPOSSIBLE);
  1207. }
  1208. else
  1209. {
  1210. pwfxDst->nChannels = G723_MAX_CHANNELS;
  1211. }
  1212. //
  1213. // if the destination samples per second is restricted, verify
  1214. // that it is within our capabilities...
  1215. //
  1216. // G.723.1 is designed for 8000 Hz sampling rate
  1217. //
  1218. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  1219. {
  1220. if (pwfxDst->nSamplesPerSec != 8000)
  1221. return (ACMERR_NOTPOSSIBLE);
  1222. }
  1223. else
  1224. {
  1225. pwfxDst->nSamplesPerSec = 8000;
  1226. }
  1227. //
  1228. // if the destination bits per sample is restricted, verify
  1229. // that it is within our capabilities...
  1230. //
  1231. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  1232. {
  1233. if (G723_BITS_PER_SAMPLE != pwfxDst->wBitsPerSample)
  1234. return (ACMERR_NOTPOSSIBLE);
  1235. }
  1236. else
  1237. {
  1238. pwfxDst->wBitsPerSample = G723_BITS_PER_SAMPLE;
  1239. }
  1240. //
  1241. // at this point, we have filled in all fields except the
  1242. // following for our 'suggested' destination format:
  1243. //
  1244. // nAvgBytesPerSec
  1245. // nBlockAlign
  1246. // cbSize
  1247. //
  1248. // wSamplesPerBlock -> G723 extended information
  1249. //
  1250. pwfg723 = (LPMSG723WAVEFORMAT)pwfxDst;
  1251. pwfg723->wConfigWord = Rate63;
  1252. pwfxDst->nBlockAlign = g723BlockAlign(pwfg723);
  1253. pwfxDst->nAvgBytesPerSec = g723AvgBytesPerSec(pwfxDst);
  1254. pwfxDst->cbSize = G723_WFX_EXTRA_BYTES;
  1255. return (MMSYSERR_NOERROR);
  1256. case WAVE_FORMAT_MSG723:
  1257. //
  1258. // strictly verify that the source format is acceptable for
  1259. // this driver
  1260. //
  1261. if (!g723IsValidFormat(pwfxSrc))
  1262. return (ACMERR_NOTPOSSIBLE);
  1263. //
  1264. // if the destination format tag is restricted, verify that
  1265. // it is within our capabilities...
  1266. //
  1267. // this driver is only able to decode to PCM
  1268. //
  1269. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  1270. {
  1271. if (WAVE_FORMAT_PCM != pwfxDst->wFormatTag)
  1272. return (ACMERR_NOTPOSSIBLE);
  1273. }
  1274. else
  1275. {
  1276. pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
  1277. }
  1278. //
  1279. // if the destination channel count is restricted, verify that
  1280. // it is within our capabilities...
  1281. //
  1282. // this driver is not able to change the number of channels
  1283. //
  1284. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  1285. {
  1286. if (pwfxSrc->nChannels != G723_MAX_CHANNELS)
  1287. return (ACMERR_NOTPOSSIBLE);
  1288. }
  1289. else
  1290. {
  1291. pwfxDst->nChannels = G723_MAX_CHANNELS;
  1292. }
  1293. //
  1294. // if the destination samples per second is restricted, verify
  1295. // that it is within our capabilities...
  1296. //
  1297. // G.723.1 produces PCM at 8000 Hz sampling rate
  1298. //
  1299. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  1300. {
  1301. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  1302. if (pwfxDst->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  1303. break;
  1304. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  1305. return (ACMERR_NOTPOSSIBLE);
  1306. pwfxDst->nSamplesPerSec = pwfxSrc->nSamplesPerSec;
  1307. }
  1308. else
  1309. {
  1310. //
  1311. // 11025 is the default since it is more common
  1312. // in the PC world than 8000. Moreover, this
  1313. // prevents applications like MS Sound Recorder
  1314. // from using a low quality SRC in certain cases.
  1315. //
  1316. pwfxDst->nSamplesPerSec = 11025;
  1317. }
  1318. //
  1319. // if the destination bits per sample is restricted, verify
  1320. // that it is within our capabilities...
  1321. //
  1322. // this driver is only able to decode to 16 bit
  1323. //
  1324. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  1325. {
  1326. if (16 != pwfxDst->wBitsPerSample)
  1327. return (ACMERR_NOTPOSSIBLE);
  1328. }
  1329. else
  1330. {
  1331. pwfxDst->wBitsPerSample = 16;
  1332. }
  1333. //
  1334. // at this point, we have filled in all fields except the
  1335. // following for our 'suggested' destination format:
  1336. //
  1337. // nAvgBytesPerSec
  1338. // nBlockAlign
  1339. // cbSize !!! not used for PCM !!!
  1340. //
  1341. pwfxDst->nBlockAlign = PCM_BLOCKALIGNMENT(pwfxDst);
  1342. pwfxDst->nAvgBytesPerSec = pwfxDst->nSamplesPerSec *
  1343. pwfxDst->nBlockAlign;
  1344. // pwfxDst->cbSize = not used;
  1345. return (MMSYSERR_NOERROR);
  1346. }
  1347. //
  1348. // can't suggest anything because either the source format is foreign
  1349. // or the destination format has restrictions that this ACM driver
  1350. // cannot deal with.
  1351. //
  1352. return (ACMERR_NOTPOSSIBLE);
  1353. }
  1354. //--------------------------------------------------------------------------;
  1355. //
  1356. // LRESULT acmdFormatTagDetails
  1357. //
  1358. // Description:
  1359. // This function handles the ACMDM_FORMATTAG_DETAILS message. This
  1360. // message is normally sent in response to an acmFormatTagDetails or
  1361. // acmFormatTagEnum function call. The purpose of this function is
  1362. // to get details about a specific format tag supported by this ACM
  1363. // driver.
  1364. //
  1365. // Arguments:
  1366. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  1367. // This structure is [optionally] allocated during the DRV_OPEN message
  1368. // which is handled by the acmdDriverOpen function.
  1369. //
  1370. // LPACMFORMATTAGDETAILS padft: Pointer to an ACMFORMATTAGDETAILS
  1371. // structure that describes what format tag to retrieve details for.
  1372. //
  1373. // DWORD fdwDetails: Flags defining what format tag to retrieve the
  1374. // details for.
  1375. //
  1376. // Return (LRESULT):
  1377. // The return value is zero (MMSYSERR_NOERROR) if this function
  1378. // succeeds with no errors. The return value is a non-zero error code
  1379. // if the function fails.
  1380. //
  1381. // The driver should return MMSYSERR_NOTSUPPORTED if the query type
  1382. // specified in fdwDetails is not supported. An ACM driver must
  1383. // support at least the following query types:
  1384. //
  1385. // ACM_FORMATTAGDETAILSF_INDEX: Indicates that a format tag index
  1386. // was given in the dwFormatTagIndex member of the ACMFORMATTAGDETAILS
  1387. // structure. The format tag and details must be returned in the
  1388. // structure specified by padft. The index ranges from zero to one less
  1389. // than the cFormatTags member returned in the ACMDRIVERDETAILS
  1390. // structure for this driver.
  1391. //
  1392. // ACM_FORMATTAGDETAILSF_FORMATTAG: Indicates that a format tag
  1393. // was given in the dwFormatTag member of the ACMFORMATTAGDETAILS
  1394. // structure. The format tag details must be returned in the structure
  1395. // specified by padft.
  1396. //
  1397. // ACM_FORMATTAGDETAILSF_LARGESTSIZE: Indicates that the details
  1398. // on the format tag with the largest format size in bytes must be
  1399. // returned. The dwFormatTag member will either be WAVE_FORMAT_UNKNOWN
  1400. // or the format tag to find the largest size for.
  1401. //
  1402. // If the details for the specified format tag cannot be retrieved
  1403. // from this driver, then ACMERR_NOTPOSSIBLE should be returned.
  1404. //
  1405. //--------------------------------------------------------------------------;
  1406. LRESULT FNLOCAL acmdFormatTagDetails
  1407. (
  1408. PDRIVERINSTANCE pdi,
  1409. LPACMFORMATTAGDETAILS padft,
  1410. DWORD fdwDetails
  1411. )
  1412. {
  1413. UINT uFormatTag;
  1414. switch (ACM_FORMATTAGDETAILSF_QUERYMASK & fdwDetails)
  1415. {
  1416. case ACM_FORMATTAGDETAILSF_INDEX:
  1417. //
  1418. // if the index is too large, then they are asking for a
  1419. // non-existant format. return error.
  1420. //
  1421. if (ACM_DRIVER_MAX_FORMAT_TAGS <= padft->dwFormatTagIndex)
  1422. return (ACMERR_NOTPOSSIBLE);
  1423. uFormatTag = gauFormatTagIndexToTag[(UINT)padft->dwFormatTagIndex];
  1424. break;
  1425. case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
  1426. switch (padft->dwFormatTag)
  1427. {
  1428. case WAVE_FORMAT_UNKNOWN:
  1429. case WAVE_FORMAT_MSG723:
  1430. uFormatTag = WAVE_FORMAT_MSG723;
  1431. break;
  1432. case WAVE_FORMAT_PCM:
  1433. uFormatTag = WAVE_FORMAT_PCM;
  1434. break;
  1435. default:
  1436. return (ACMERR_NOTPOSSIBLE);
  1437. }
  1438. break;
  1439. case ACM_FORMATTAGDETAILSF_FORMATTAG:
  1440. switch (padft->dwFormatTag)
  1441. {
  1442. case WAVE_FORMAT_MSG723:
  1443. uFormatTag = WAVE_FORMAT_MSG723;
  1444. break;
  1445. case WAVE_FORMAT_PCM:
  1446. uFormatTag = WAVE_FORMAT_PCM;
  1447. break;
  1448. default:
  1449. return (ACMERR_NOTPOSSIBLE);
  1450. }
  1451. break;
  1452. //
  1453. // if this ACM driver does not understand a query type, then
  1454. // return 'not supported'
  1455. //
  1456. default:
  1457. return (MMSYSERR_NOTSUPPORTED);
  1458. }
  1459. //
  1460. //
  1461. //
  1462. //
  1463. switch (uFormatTag)
  1464. {
  1465. case WAVE_FORMAT_PCM:
  1466. padft->dwFormatTagIndex = 0;
  1467. padft->dwFormatTag = WAVE_FORMAT_PCM;
  1468. padft->cbFormatSize = sizeof(PCMWAVEFORMAT);
  1469. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1470. padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_PCM;
  1471. //
  1472. // the ACM is responsible for the PCM format tag name
  1473. //
  1474. padft->szFormatTag[0] = '\0';
  1475. break;
  1476. case WAVE_FORMAT_MSG723:
  1477. padft->dwFormatTagIndex = 1;
  1478. padft->dwFormatTag = WAVE_FORMAT_MSG723;
  1479. padft->cbFormatSize = sizeof(WAVEFORMATEX) +
  1480. G723_WFX_EXTRA_BYTES;
  1481. padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1482. padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_G723;
  1483. LoadStringCodec(pdi->hinst,
  1484. IDS_ACM_DRIVER_TAG_NAME,
  1485. padft->szFormatTag,
  1486. SIZEOFACMSTR(padft->szFormatTag));
  1487. break;
  1488. default:
  1489. return (ACMERR_NOTPOSSIBLE);
  1490. }
  1491. //
  1492. // return only the requested info
  1493. //
  1494. // the ACM will guarantee that the ACMFORMATTAGDETAILS structure
  1495. // passed is at least large enough to hold the base information of
  1496. // the details structure
  1497. //
  1498. padft->cbStruct = min(padft->cbStruct, sizeof(*padft));
  1499. //
  1500. return (MMSYSERR_NOERROR);
  1501. } // acmdFormatTagDetails()
  1502. //--------------------------------------------------------------------------;
  1503. //
  1504. // LRESULT acmdFormatDetails
  1505. //
  1506. // Description:
  1507. // This function handles the ACMDM_FORMAT_DETAILS message. This
  1508. // message is normally sent in response to an acmFormatDetails or
  1509. // acmFormatEnum function call. The purpose of this function is
  1510. // to get details about a specific format for a specified format tag
  1511. // supported by this ACM driver.
  1512. //
  1513. // Note that an ACM driver can return a zero length string for the
  1514. // format name if it wishes to have the ACM create a format string
  1515. // for it. This is strongly recommended to simplify internationalizing
  1516. // the driver--the ACM will automatically take care of that. The
  1517. // following formula is used to format a string by the ACM:
  1518. //
  1519. // <nSamplesPerSec> kHz, <bit depth> bit, [Mono | Stereo | nChannels]
  1520. //
  1521. // <bit depth> = <nAvgBytesPerSec> * 8 / nSamplesPerSec / nChannels;
  1522. //
  1523. // Arguments:
  1524. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  1525. // This structure is [optionally] allocated during the DRV_OPEN message
  1526. // which is handled by the acmdDriverOpen function.
  1527. //
  1528. // LPACMFORMATDETAILS padf: Pointer to an ACMFORMATDETAILS structure
  1529. // that describes what format (for a specified format tag) to retrieve
  1530. // details for.
  1531. //
  1532. // DWORD fdwDetails: Flags defining what format for a specified format
  1533. // tag to retrieve the details for.
  1534. //
  1535. // Return (LRESULT):
  1536. // The return value is zero (MMSYSERR_NOERROR) if this function
  1537. // succeeds with no errors. The return value is a non-zero error code
  1538. // if the function fails.
  1539. //
  1540. // The driver should return MMSYSERR_NOTSUPPORTED if the query type
  1541. // specified in fdwDetails is not supported. An ACM driver must
  1542. // support at least the following query types:
  1543. //
  1544. // ACM_FORMATDETAILSF_INDEX: Indicates that a format index for the
  1545. // format tag was given in the dwFormatIndex member of the
  1546. // ACMFORMATDETAILS structure. The format details must be returned in
  1547. // the structure specified by padf. The index ranges from zero to one
  1548. // less than the cStandardFormats member returned in the
  1549. // ACMFORMATTAGDETAILS structure for a format tag.
  1550. //
  1551. // ACM_FORMATDETAILSF_FORMAT: Indicates that a WAVEFORMATEX structure
  1552. // pointed to by pwfx of the ACMFORMATDETAILS structure was given and
  1553. // the remaining details should be returned. The dwFormatTag member
  1554. // of the ACMFORMATDETAILS will be initialized to the same format
  1555. // tag as the pwfx member specifies. This query type may be used to
  1556. // get a string description of an arbitrary format structure.
  1557. //
  1558. // If the details for the specified format cannot be retrieved
  1559. // from this driver, then ACMERR_NOTPOSSIBLE should be returned.
  1560. //
  1561. //--------------------------------------------------------------------------;
  1562. LRESULT FNLOCAL acmdFormatDetails
  1563. (
  1564. PDRIVERINSTANCE pdi,
  1565. LPACMFORMATDETAILS padf,
  1566. DWORD fdwDetails
  1567. )
  1568. {
  1569. LPWAVEFORMATEX pwfx;
  1570. LPMSG723WAVEFORMAT pwfg723;
  1571. switch (ACM_FORMATDETAILSF_QUERYMASK & fdwDetails)
  1572. {
  1573. //
  1574. // enumerate by index
  1575. //
  1576. // verify that the format tag is something we know about and
  1577. // return the details on the 'standard format' supported by
  1578. // this driver at the specified index...
  1579. //
  1580. case ACM_FORMATDETAILSF_INDEX:
  1581. pwfx = padf->pwfx;
  1582. switch (padf->dwFormatTag)
  1583. {
  1584. case WAVE_FORMAT_PCM:
  1585. if (padf->dwFormatIndex >= ACM_DRIVER_MAX_FORMATS_PCM)
  1586. return (ACMERR_NOTPOSSIBLE);
  1587. pwfx->nSamplesPerSec
  1588. = PCM_SAMPLING_RATE[padf->dwFormatIndex];
  1589. pwfx->wFormatTag = WAVE_FORMAT_PCM;
  1590. pwfx->nChannels = 1;
  1591. pwfx->wBitsPerSample = 16;
  1592. pwfx->nBlockAlign = PCM_BLOCKALIGNMENT(pwfx);
  1593. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  1594. //
  1595. // note that the cbSize field is NOT valid for PCM
  1596. // formats
  1597. //
  1598. // pwfx->cbSize = 0;
  1599. break;
  1600. case WAVE_FORMAT_MSG723:
  1601. if (padf->dwFormatIndex >= ACM_DRIVER_MAX_FORMATS_G723)
  1602. return (ACMERR_NOTPOSSIBLE);
  1603. pwfx->wFormatTag = WAVE_FORMAT_MSG723;
  1604. pwfx->nSamplesPerSec
  1605. = G723_SAMPLING_RATE[padf->dwFormatIndex];
  1606. pwfx->nChannels = G723_MAX_CHANNELS;
  1607. pwfx->wBitsPerSample = G723_BITS_PER_SAMPLE;
  1608. pwfg723 = (LPMSG723WAVEFORMAT)pwfx;
  1609. if(padf->dwFormatIndex == 0)
  1610. {
  1611. pwfx->nBlockAlign = 24;
  1612. pwfx->nAvgBytesPerSec = 800;
  1613. pwfg723->wConfigWord = Rate63+POST_FILTER;
  1614. }
  1615. if(padf->dwFormatIndex == 1)
  1616. {
  1617. pwfx->nBlockAlign = 20;
  1618. pwfx->nAvgBytesPerSec = 666;
  1619. pwfg723->wConfigWord = Rate53+POST_FILTER;
  1620. }
  1621. if(padf->dwFormatIndex == 2)
  1622. {
  1623. pwfx->nBlockAlign = 24;
  1624. pwfx->nAvgBytesPerSec = 800;
  1625. pwfg723->wConfigWord=Rate63+POST_FILTER+SILENCE_ENABLE;
  1626. }
  1627. if(padf->dwFormatIndex == 3)
  1628. {
  1629. pwfx->nBlockAlign = 20;
  1630. pwfx->nAvgBytesPerSec = 666;
  1631. pwfg723->wConfigWord=Rate53+POST_FILTER+SILENCE_ENABLE;
  1632. }
  1633. pwfx->cbSize = G723_WFX_EXTRA_BYTES;
  1634. break;
  1635. default:
  1636. return (ACMERR_NOTPOSSIBLE);
  1637. }
  1638. //
  1639. // return details on specified format
  1640. //
  1641. // the caller normally uses this to verify that the format is
  1642. // supported and to retrieve a string description...
  1643. //
  1644. case ACM_FORMATDETAILSF_FORMAT:
  1645. pwfx = padf->pwfx;
  1646. switch (pwfx->wFormatTag)
  1647. {
  1648. case WAVE_FORMAT_PCM:
  1649. if (!pcmIsValidFormat(pwfx))
  1650. return (ACMERR_NOTPOSSIBLE);
  1651. break;
  1652. case WAVE_FORMAT_MSG723:
  1653. if (!g723IsValidFormat(pwfx))
  1654. return (ACMERR_NOTPOSSIBLE);
  1655. break;
  1656. default:
  1657. return (ACMERR_NOTPOSSIBLE);
  1658. }
  1659. break;
  1660. default:
  1661. return (MMSYSERR_NOTSUPPORTED);
  1662. }
  1663. padf->cbStruct = min(padf->cbStruct, sizeof(*padf));
  1664. padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  1665. pwfg723 = (LPMSG723WAVEFORMAT)pwfx;
  1666. if(padf->dwFormatTag == WAVE_FORMAT_MSG723)
  1667. {
  1668. if((pwfg723->wConfigWord&5) == 0)
  1669. LoadStringCodec(pdi->hinst, IDS_FORMAT_DETAILS_MONO_8KHZ_6400BIT_S,
  1670. padf->szFormat,SIZEOFACMSTR(padf->szFormat));
  1671. if((pwfg723->wConfigWord&5) == 4)
  1672. LoadStringCodec(pdi->hinst, IDS_FORMAT_DETAILS_MONO_8KHZ_6400BIT_SID,
  1673. padf->szFormat,SIZEOFACMSTR(padf->szFormat));
  1674. if((pwfg723->wConfigWord&5) == 1)
  1675. LoadStringCodec(pdi->hinst, IDS_FORMAT_DETAILS_MONO_8KHZ_5333BIT_S,
  1676. padf->szFormat,SIZEOFACMSTR(padf->szFormat));
  1677. if((pwfg723->wConfigWord&5) == 5)
  1678. LoadStringCodec(pdi->hinst, IDS_FORMAT_DETAILS_MONO_8KHZ_5333BIT_SID,
  1679. padf->szFormat,SIZEOFACMSTR(padf->szFormat));
  1680. }
  1681. else
  1682. padf->szFormat[0] = '\0';
  1683. //
  1684. //
  1685. //
  1686. return (MMSYSERR_NOERROR);
  1687. } // acmdFormatDetails()
  1688. //==========================================================================;
  1689. //
  1690. //
  1691. //
  1692. //
  1693. //==========================================================================;
  1694. //--------------------------------------------------------------------------;
  1695. //
  1696. // LRESULT acmdStreamOpen
  1697. //
  1698. // Description:
  1699. // This function handles the ACMDM_STREAM_OPEN message. This message
  1700. // is sent to initiate a new conversion stream. This is usually caused
  1701. // by an application calling acmStreamOpen. If this function is
  1702. // successful, then one or more ACMDM_STREAM_CONVERT messages will be
  1703. // sent to convert individual buffers (user calls acmStreamConvert).
  1704. //
  1705. // Note that an ACM driver will not receive open requests for ASYNC
  1706. // or FILTER operations unless the ACMDRIVERDETAILS_SUPPORTF_ASYNC
  1707. // or ACMDRIVERDETAILS_SUPPORTF_FILTER flags are set in the
  1708. // ACMDRIVERDETAILS structure. There is no need for the driver to
  1709. // check for these requests unless it sets those support bits.
  1710. //
  1711. // If the ACM_STREAMOPENF_QUERY flag is set in the padsi->fdwOpen
  1712. // member, then no resources should be allocated. Just verify that
  1713. // the conversion request is possible by this driver and return the
  1714. // appropriate error (either ACMERR_NOTPOSSIBLE or MMSYSERR_NOERROR).
  1715. // The driver will NOT receive an ACMDM_STREAM_CLOSE for queries.
  1716. //
  1717. // Arguments:
  1718. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  1719. // This structure is [optionally] allocated during the DRV_OPEN message
  1720. // which is handled by the acmdDriverOpen function.
  1721. //
  1722. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1723. // conversion stream. This structure was allocated by the ACM and
  1724. // filled with the most common instance data needed for conversions.
  1725. // This structure will be passed back to all future stream messages
  1726. // if the open succeeds. The information in this structure will never
  1727. // change during the lifetime of the stream--so it is not necessary
  1728. // to re-verify the information referenced by this structure.
  1729. //
  1730. // Return (LRESULT):
  1731. // The return value is zero (MMSYSERR_NOERROR) if this function
  1732. // succeeds with no errors. The return value is a non-zero error code
  1733. // if the function fails.
  1734. //
  1735. // A driver should return ACMERR_NOTPOSSIBLE if the conversion cannot
  1736. // be performed due to incompatible source and destination formats.
  1737. //
  1738. // A driver should return MMSYSERR_NOTSUPPORTED if the conversion
  1739. // cannot be performed in real-time and the request does not specify
  1740. // the ACM_STREAMOPENF_NONREALTIME flag.
  1741. //
  1742. //--------------------------------------------------------------------------;
  1743. LRESULT FNLOCAL acmdStreamOpen
  1744. (
  1745. PDRIVERINSTANCE pdi,
  1746. LPACMDRVSTREAMINSTANCE padsi
  1747. )
  1748. {
  1749. LPWAVEFORMATEX pwfxSrc;
  1750. LPWAVEFORMATEX pwfxDst;
  1751. LPMSG723WAVEFORMAT pwfg723;
  1752. CODDEF *CodStat;
  1753. DECDEF *DecStat;
  1754. G723CODDEF *g723Inst;
  1755. INSTNCE *SD_Inst;
  1756. UINT psi;
  1757. int i;
  1758. #ifdef G723_USECONFIG
  1759. DWORD nConfigMaxRTEncodeSamplesPerSec;
  1760. DWORD nConfigMaxRTDecodeSamplesPerSec;
  1761. DWORD dw;
  1762. #endif
  1763. //
  1764. //
  1765. //
  1766. pwfxSrc = padsi->pwfxSrc;
  1767. pwfxDst = padsi->pwfxDst;
  1768. // fRealTime = (0 == (padsi->fdwOpen & ACM_STREAMOPENF_NONREALTIME));
  1769. //
  1770. // this driver first verifies that the source and destination formats
  1771. // are acceptable...
  1772. //
  1773. switch (pwfxSrc->wFormatTag)
  1774. {
  1775. case WAVE_FORMAT_PCM:
  1776. if (!pcmIsValidFormat(pwfxSrc))
  1777. return (ACMERR_NOTPOSSIBLE);
  1778. if (!g723IsValidFormat(pwfxDst))
  1779. return (ACMERR_NOTPOSSIBLE);
  1780. break;
  1781. case WAVE_FORMAT_MSG723:
  1782. if (!g723IsValidFormat(pwfxSrc))
  1783. return (ACMERR_NOTPOSSIBLE);
  1784. if (!pcmIsValidFormat(pwfxDst))
  1785. return (ACMERR_NOTPOSSIBLE);
  1786. break;
  1787. default:
  1788. return (ACMERR_NOTPOSSIBLE);
  1789. }
  1790. //
  1791. // for this driver, we must also verify that the nChannels
  1792. // member is the same between the source and destination
  1793. // formats.
  1794. //
  1795. if (pwfxSrc->nChannels != pwfxDst->nChannels)
  1796. return (MMSYSERR_NOTSUPPORTED);
  1797. //
  1798. // we have determined that the conversion requested is possible by
  1799. // this driver. now check if we are just being queried for support.
  1800. // if this is just a query, then do NOT allocate any instance data
  1801. // or create tables, etc. just succeed the call.
  1802. //
  1803. if (0 != (ACM_STREAMOPENF_QUERY & padsi->fdwOpen))
  1804. {
  1805. #ifdef DEBUG
  1806. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  1807. TTDBG(ghISRInst,TT_TRACE,"Stream open query");
  1808. #endif // } NO_DEBUGGING_OUTPUT
  1809. #endif
  1810. return (MMSYSERR_NOERROR);
  1811. }
  1812. //
  1813. // we have decided that this driver can handle the conversion stream.
  1814. // so we want to do _AS MUCH WORK AS POSSIBLE_ right now to prepare
  1815. // for converting data. any resource allocation, table building, etc
  1816. // that can be dealt with at this time should be done.
  1817. //
  1818. // THIS IS VERY IMPORTANT! all ACMDM_STREAM_CONVERT messages need to
  1819. // be handled as quickly as possible.
  1820. //
  1821. // this driver allocates a small instance structure for each stream
  1822. //
  1823. //
  1824. switch (pwfxSrc->wFormatTag)
  1825. {
  1826. case WAVE_FORMAT_PCM:
  1827. g723Inst = LocalAlloc(LPTR,sizeof(G723CODDEF));
  1828. if (NULL == g723Inst)
  1829. return (MMSYSERR_NOMEM);
  1830. CodStat = &g723Inst->CodStat;
  1831. Init_Coder(CodStat);
  1832. CodStat->UseHp = True;
  1833. pwfg723 = (LPMSG723WAVEFORMAT)pwfxDst;
  1834. CodStat->WrkRate = pwfg723->wConfigWord&RATE;
  1835. CodStat->srccount = (int)0;
  1836. for(i=0;i<SRCSTATELEN;i++)
  1837. CodStat->srcstate[i] = (short)0;
  1838. /*****************************************************************
  1839. Silence detector Init
  1840. *****************************************************************/
  1841. /* This value enables silence detection, early exit, and the default
  1842. ** squelch value.
  1843. */
  1844. SD_Inst = &g723Inst->SD_Instance;
  1845. SD_Inst->SDFlags = 0x00000005;
  1846. // isFrameSilent = 0; // initialize to "not silent"
  1847. /*
  1848. ** Inintialize first OFFSET samples of storebuff
  1849. */
  1850. for(i=0;i<OFFSET;i++)SD_Inst->SDstate.Filt.storebuff[i] = 0.0f;
  1851. glblSDinitialize(SD_Inst);
  1852. psi = (DWORD)(UINT)g723Inst;
  1853. #ifndef NOTPRODUCT
  1854. if ((pwfg723->dwCodeword1 == G723MAGICWORD1)
  1855. && (pwfg723->dwCodeword2 == G723MAGICWORD2))
  1856. {
  1857. pdi->enabled = TRUE;
  1858. }
  1859. #endif // NOTPRODUCT
  1860. break;
  1861. case WAVE_FORMAT_MSG723:
  1862. DecStat = LocalAlloc(LPTR,sizeof(DECDEF));
  1863. if (NULL == DecStat)
  1864. return (MMSYSERR_NOMEM);
  1865. Init_Decod(DecStat); //low rate high pass and post filters enabled
  1866. pwfg723 = (LPMSG723WAVEFORMAT)pwfxSrc;
  1867. DecStat->UsePf = pwfg723->wConfigWord & POST_FILTER;
  1868. #ifndef NOTPRODUCT
  1869. if ((pwfg723->dwCodeword1 == G723MAGICWORD1)
  1870. && (pwfg723->dwCodeword2 == G723MAGICWORD2))
  1871. {
  1872. pdi->enabled = TRUE;
  1873. }
  1874. #endif // NOTPRODUCT
  1875. // DecStat->FrameSize = 20;
  1876. // if((pwfg723->wConfigWord & RATE) == 0)
  1877. // DecStat->FrameSize = 24;
  1878. DecStat->srccount = (int)0;
  1879. for(i=0;i<SRCSTATELEN;i++)
  1880. DecStat->srcstate[i] = (short)0;
  1881. DecStat->i = 0;
  1882. // DecStat->srcbuffend = DecStat->srcbuff;
  1883. psi = (DWORD)(UINT)DecStat;
  1884. break;
  1885. }
  1886. //
  1887. // fill out our instance structure
  1888. //
  1889. // this driver stores a pointer to the conversion function that will
  1890. // be used for each conversion on this stream. we also store a
  1891. // copy of the _current_ configuration of the driver instance we
  1892. // are opened on. this must not change during the life of the stream
  1893. // instance.
  1894. //
  1895. // this is also very important! if the user is able to configure how
  1896. // the driver performs conversions, the changes should only affect
  1897. // future open streams. all current open streams should behave as
  1898. // they were configured during the open.
  1899. //
  1900. // psi->fnConvert = fnConvert;
  1901. // psi->fdwConfig = pdi->fdwConfig;
  1902. //
  1903. // fill in our instance data--this will be passed back to all stream
  1904. // messages in the ACMDRVSTREAMINSTANCE structure. it is entirely
  1905. // up to the driver what gets stored (and maintained) in the
  1906. // fdwDriver and dwDriver members.
  1907. //
  1908. padsi->fdwDriver = 0L;
  1909. padsi->dwDriver = psi;
  1910. #ifdef DEBUG
  1911. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  1912. TTDBG(ghISRInst,TT_TRACE,"Stream Open padsi=%lx psi=%lx",padsi,psi);
  1913. #endif // } NO_DEBUGGING_OUTPUT
  1914. #endif
  1915. return (MMSYSERR_NOERROR);
  1916. } // acmdStreamOpen()
  1917. //--------------------------------------------------------------------------;
  1918. //
  1919. // LRESULT acmdStreamClose
  1920. //
  1921. // Description:
  1922. // This function is called to handle the ACMDM_STREAM_CLOSE message.
  1923. // This message is sent when a conversion stream is no longer being
  1924. // used (the stream is being closed; usually by an application
  1925. // calling acmStreamClose).
  1926. //
  1927. // Arguments:
  1928. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  1929. // conversion stream.
  1930. //
  1931. // Return (LRESULT):
  1932. // The return value is zero (MMSYSERR_NOERROR) if this function
  1933. // succeeds with no errors. The return value is a non-zero error code
  1934. // if the function fails.
  1935. //
  1936. //
  1937. // An asyncronous conversion stream may fail with ACMERR_BUSY if there
  1938. // are pending buffers. An application may call acmStreamReset to
  1939. // force all pending buffers to be posted.
  1940. //
  1941. //--------------------------------------------------------------------------;
  1942. LRESULT FNLOCAL acmdStreamClose
  1943. (
  1944. LPACMDRVSTREAMINSTANCE padsi
  1945. )
  1946. {
  1947. UINT psi;
  1948. #ifdef LOG_ENCODE_TIMINGS_ON // { LOG_ENCODE_TIMINGS_ON
  1949. CODDEF *CodStat;
  1950. G723CODDEF *g723Inst;
  1951. #endif // } LOG_ENCODE_TIMINGS_ON
  1952. #ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
  1953. DECDEF *DecStat;
  1954. #endif // } LOG_ENCODE_TIMINGS_ON
  1955. //
  1956. // the driver should clean up all privately allocated resources that
  1957. // were created for maintaining the stream instance. if no resources
  1958. // were allocated, then simply succeed.
  1959. //
  1960. // in the case of this driver, we need to free the stream instance
  1961. // structure that we allocated during acmdStreamOpen.
  1962. //
  1963. psi = (UINT)padsi->dwDriver;
  1964. #ifdef DEBUG
  1965. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  1966. TTDBG(ghISRInst,TT_TRACE,"Stream Close padsi=%lx psi=%lx",padsi,psi);
  1967. #endif // } NO_DEBUGGING_OUTPUT
  1968. #endif
  1969. if (0 != psi)
  1970. {
  1971. #ifdef LOG_ENCODE_TIMINGS_ON // { LOG_ENCODE_TIMINGS_ON
  1972. g723Inst = (G723CODDEF *)psi;
  1973. CodStat = &g723Inst->CodStat;
  1974. OutputEncodeTimingStatistics("c:\\encode.txt", CodStat->EncTimingInfo, CodStat->dwStatFrameCount);
  1975. #endif // } LOG_ENCODE_TIMINGS_ON
  1976. #ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
  1977. DecStat = (DECDEF *)psi;
  1978. OutputDecodeTimingStatistics("c:\\decode.txt", DecStat->DecTimingInfo, DecStat->dwStatFrameCount);
  1979. #endif // } LOG_DECODE_TIMINGS_ON
  1980. //
  1981. // free the stream instance structure
  1982. //
  1983. LocalFree((HLOCAL)psi);
  1984. }
  1985. return (MMSYSERR_NOERROR);
  1986. } // acmdStreamClose()
  1987. //--------------------------------------------------------------------------;
  1988. //
  1989. // LRESULT acmdStreamSize
  1990. //
  1991. // Description:
  1992. // This function handles the ACMDM_STREAM_SIZE message. The purpose
  1993. // of this function is to provide the _largest size in bytes_ that
  1994. // the source or destination buffer needs to be given the input and
  1995. // output formats and the size in bytes of the source or destination
  1996. // data buffer.
  1997. //
  1998. // In other words: how big does my destination buffer need to be to
  1999. // hold the converted data? (ACM_STREAMSIZEF_SOURCE)
  2000. //
  2001. // Or: how big can my source buffer be given the destination buffer?
  2002. // (ACM_STREAMSIZEF_DESTINATION)
  2003. //
  2004. // Arguments:
  2005. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  2006. // conversion stream. This structure was allocated by the ACM and
  2007. // filled with the most common instance data needed for conversions.
  2008. // The information in this structure is exactly the same as it was
  2009. // during the ACMDM_STREAM_OPEN message--so it is not necessary
  2010. // to re-verify the information referenced by this structure.
  2011. //
  2012. // LPACMDRVSTREAMSIZE padss: Specifies a pointer to the ACMDRVSTREAMSIZE
  2013. // structure that defines the conversion stream size query attributes.
  2014. //
  2015. // Return (LRESULT):
  2016. // The return value is zero (MMSYSERR_NOERROR) if this function
  2017. // succeeds with no errors. The return value is a non-zero error code
  2018. // if the function fails.
  2019. //
  2020. // An ACM driver should return MMSYSERR_NOTSUPPORTED if a query type
  2021. // is requested that the driver does not understand. Note that a driver
  2022. // must support both the ACM_STREAMSIZEF_DESTINATION and
  2023. // ACM_STREAMSIZEF_SOURCE queries.
  2024. //
  2025. // If the conversion would be 'out of range' given the input arguments,
  2026. // then ACMERR_NOTPOSSIBLE should be returned.
  2027. //
  2028. //--------------------------------------------------------------------------;
  2029. LRESULT FNLOCAL acmdStreamSize
  2030. (
  2031. LPACMDRVSTREAMINSTANCE padsi,
  2032. LPACMDRVSTREAMSIZE padss
  2033. )
  2034. {
  2035. PSTREAMINSTANCE psi;
  2036. LPWAVEFORMATEX pwfxSrc;
  2037. LPWAVEFORMATEX pwfxDst;
  2038. LPMSG723WAVEFORMAT pwfg723;
  2039. DWORD cb;
  2040. DWORD cBlocks;
  2041. DWORD cbBytesPerBlock;
  2042. int i;
  2043. pwfxSrc = padsi->pwfxSrc;
  2044. pwfxDst = padsi->pwfxDst;
  2045. psi = (PSTREAMINSTANCE)(UINT)padsi->dwDriver;
  2046. //
  2047. //
  2048. //
  2049. //
  2050. //
  2051. switch (ACM_STREAMSIZEF_QUERYMASK & padss->fdwSize)
  2052. {
  2053. case ACM_STREAMSIZEF_SOURCE:
  2054. cb = padss->cbSrcLength;
  2055. if (WAVE_FORMAT_MSG723 == pwfxSrc->wFormatTag)
  2056. {
  2057. //
  2058. // how many destination PCM bytes are needed to hold
  2059. // the decoded g723 data of padss->cbSrcLength bytes
  2060. //
  2061. // always round UP
  2062. //
  2063. cBlocks = cb / pwfxSrc->nBlockAlign;
  2064. if (0 == cBlocks)
  2065. {
  2066. return (ACMERR_NOTPOSSIBLE);
  2067. }
  2068. pwfg723 = (LPMSG723WAVEFORMAT)pwfxSrc;
  2069. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  2070. if (pwfxDst->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  2071. {
  2072. cbBytesPerBlock = G723_SAMPLES_PER_BLOCK_PCM[i]
  2073. * pwfxDst->nBlockAlign;
  2074. break;
  2075. }
  2076. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  2077. return (ACMERR_NOTPOSSIBLE);
  2078. if ((0xFFFFFFFFL / cbBytesPerBlock) < cBlocks)
  2079. {
  2080. return (ACMERR_NOTPOSSIBLE);
  2081. }
  2082. if (0 == (cb % pwfxSrc->nBlockAlign))
  2083. {
  2084. cb = cBlocks * cbBytesPerBlock;
  2085. }
  2086. else
  2087. {
  2088. cb = (cBlocks + 1) * cbBytesPerBlock;
  2089. }
  2090. //
  2091. // This ensures that there is enough room to adjust
  2092. // from 11000 to 11025 Hz sampling rate when necessary
  2093. //
  2094. if (G723_SAMPLES_PER_BLOCK_PCM[i] == 330)
  2095. cb += (int)(1.0 + cBlocks / 440.0) * cbBytesPerBlock;
  2096. }
  2097. else
  2098. {
  2099. //
  2100. // how many destination g723 bytes are needed to hold
  2101. // the encoded PCM data of padss->cbSrcLength bytes
  2102. //
  2103. // always round UP
  2104. //
  2105. pwfg723 = (LPMSG723WAVEFORMAT)pwfxDst;
  2106. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  2107. if (pwfxSrc->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  2108. {
  2109. cbBytesPerBlock = G723_SAMPLES_PER_BLOCK_PCM[i]
  2110. * pwfxSrc->nBlockAlign;
  2111. break;
  2112. }
  2113. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  2114. return (ACMERR_NOTPOSSIBLE);
  2115. cBlocks = cb / cbBytesPerBlock;
  2116. if (0 == (cb % cbBytesPerBlock))
  2117. {
  2118. cb = cBlocks * pwfxDst->nBlockAlign;
  2119. }
  2120. else
  2121. {
  2122. cb = (cBlocks + 1) * pwfxDst->nBlockAlign;
  2123. }
  2124. if (0L == cb)
  2125. {
  2126. return (ACMERR_NOTPOSSIBLE);
  2127. }
  2128. }
  2129. padss->cbDstLength = cb;
  2130. return (MMSYSERR_NOERROR);
  2131. case ACM_STREAMSIZEF_DESTINATION:
  2132. cb = padss->cbDstLength;
  2133. if (WAVE_FORMAT_MSG723 == pwfxDst->wFormatTag)
  2134. {
  2135. //
  2136. // how many source PCM bytes can be encoded into a
  2137. // destination buffer of padss->cbDstLength bytes
  2138. //
  2139. // always round DOWN
  2140. //
  2141. cBlocks = cb / pwfxDst->nBlockAlign;
  2142. if (0 == cBlocks)
  2143. {
  2144. return (ACMERR_NOTPOSSIBLE);
  2145. }
  2146. pwfg723 = (LPMSG723WAVEFORMAT)pwfxDst;
  2147. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  2148. if (pwfxSrc->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  2149. {
  2150. cbBytesPerBlock = G723_SAMPLES_PER_BLOCK_PCM[i]
  2151. * pwfxSrc->nBlockAlign;
  2152. break;
  2153. }
  2154. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  2155. return (ACMERR_NOTPOSSIBLE);
  2156. if ((0xFFFFFFFFL / cbBytesPerBlock) < cBlocks)
  2157. {
  2158. return (ACMERR_NOTPOSSIBLE);
  2159. }
  2160. cb = cBlocks * cbBytesPerBlock;
  2161. }
  2162. else
  2163. {
  2164. //
  2165. // how many source g723 bytes can be decoded into a
  2166. // destination buffer of padss->cbDstLength bytes
  2167. //
  2168. // always round DOWN
  2169. //
  2170. pwfg723 = (LPMSG723WAVEFORMAT)pwfxSrc;
  2171. for(i=0;i<ACM_DRIVER_MAX_FORMATS_PCM;i++)
  2172. if (pwfxDst->nSamplesPerSec == PCM_SAMPLING_RATE[i])
  2173. {
  2174. cbBytesPerBlock = G723_SAMPLES_PER_BLOCK_PCM[i]
  2175. * pwfxDst->nBlockAlign;
  2176. break;
  2177. }
  2178. if (i == ACM_DRIVER_MAX_FORMATS_PCM)
  2179. return (ACMERR_NOTPOSSIBLE);
  2180. cBlocks = cb / cbBytesPerBlock;
  2181. //
  2182. // This ensures that there is enough room to adjust
  2183. // from 11000 to 11025 Hz sampling rate when necessary
  2184. //
  2185. if (G723_SAMPLES_PER_BLOCK_PCM[i] == 330)
  2186. cBlocks -= (int)(1.0 + cBlocks / 440.0);
  2187. if (0 == cBlocks)
  2188. {
  2189. return (ACMERR_NOTPOSSIBLE);
  2190. }
  2191. cb = cBlocks * pwfxSrc->nBlockAlign;
  2192. }
  2193. padss->cbSrcLength = cb;
  2194. return (MMSYSERR_NOERROR);
  2195. }
  2196. //
  2197. //
  2198. //
  2199. return (MMSYSERR_NOTSUPPORTED);
  2200. } // acmdStreamSize()
  2201. //--------------------------------------------------------------------------;
  2202. //
  2203. // LRESULT acmdStreamConvert
  2204. //
  2205. // Description:
  2206. // This function handles the ACMDM_STREAM_CONVERT message.
  2207. //
  2208. // Arguments:
  2209. // PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
  2210. // This structure is [optionally] allocated during the DRV_OPEN message
  2211. // which is handled by the acmdDriverOpen function.
  2212. //
  2213. // LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
  2214. // conversion stream. This structure was allocated by the ACM and
  2215. // filled with the most common instance data needed for conversions.
  2216. // The information in this structure is exactly the same as it was
  2217. // during the ACMDM_STREAM_OPEN message--so it is not necessary
  2218. // to re-verify the information referenced by this structure.
  2219. //
  2220. // LPACMDRVSTREAMHEADER padsh: Pointer to stream header structure
  2221. // that defines the source data and destination buffer to convert.
  2222. //
  2223. // Return (LRESULT):
  2224. // The return value is zero (MMSYSERR_NOERROR) if this function
  2225. // succeeds with no errors. The return value is a non-zero error code
  2226. // if the function fails.
  2227. //
  2228. //--------------------------------------------------------------------------;
  2229. LRESULT FNLOCAL acmdStreamConvert
  2230. (
  2231. PDRIVERINSTANCE pdi,
  2232. LPACMDRVSTREAMINSTANCE padsi,
  2233. LPACMDRVSTREAMHEADER padsh
  2234. )
  2235. {
  2236. LPWAVEFORMATEX pwfxSrc;
  2237. LPWAVEFORMATEX pwfxDst;
  2238. LPMSG723WAVEFORMAT pwfg723;
  2239. UINT psi;
  2240. CODDEF *CodStat;
  2241. DECDEF *DecStat;
  2242. G723CODDEF *g723Inst;
  2243. INSTNCE *SD_Inst;
  2244. char *Dst,*Src;
  2245. short *wDst;
  2246. short *wSrc;
  2247. float Dbuf[240];
  2248. short Ebuf[330];
  2249. short Sbuf[240];
  2250. int i,k,m,cBlocks,temp,src_length,frame_size;
  2251. int Dst_length,isFrameSilent,silence,tmpbuf[24];
  2252. int pcm_format;
  2253. //__asm int 3
  2254. psi = padsi->dwDriver;
  2255. pwfxSrc = padsi->pwfxSrc;
  2256. pwfxDst = padsi->pwfxDst;
  2257. if (WAVE_FORMAT_PCM == pwfxSrc->wFormatTag) {
  2258. #ifdef DEBUG
  2259. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2260. TTDBG(ghISRInst,TT_TRACE,"Stream Encode padsi=%lx psi=%lx",padsi,psi);
  2261. #endif // } NO_DEBUGGING_OUTPUT
  2262. #endif
  2263. //
  2264. // Encode.
  2265. //
  2266. g723Inst = (G723CODDEF *)psi;
  2267. CodStat = &g723Inst->CodStat;
  2268. SD_Inst = &g723Inst->SD_Instance;
  2269. pwfg723 = (LPMSG723WAVEFORMAT)padsi->pwfxDst;
  2270. if(padsh->cbSrcLength == 0)
  2271. return (MMSYSERR_NOERROR);
  2272. // *** compute # of frames that we can encode.***
  2273. for(pcm_format=0;pcm_format<ACM_DRIVER_MAX_FORMATS_PCM;pcm_format++)
  2274. if (pwfxSrc->nSamplesPerSec == PCM_SAMPLING_RATE[pcm_format])
  2275. break;
  2276. if (pcm_format == ACM_DRIVER_MAX_FORMATS_PCM)
  2277. return(MMSYSERR_INVALPARAM);
  2278. cBlocks = padsh->cbSrcLength
  2279. / (pwfxSrc->nBlockAlign
  2280. * G723_SAMPLES_PER_BLOCK_PCM[pcm_format]);
  2281. // check to see if there are enough extra samples to remove
  2282. // every 441st sample (to go from 11025 to 11000 Hz)
  2283. if (G723_SAMPLES_PER_BLOCK_PCM[pcm_format] == 330)
  2284. {
  2285. i = padsh->cbSrcLength / pwfxSrc->nBlockAlign; // input samples
  2286. k = cBlocks
  2287. * G723_SAMPLES_PER_BLOCK_PCM[pcm_format]; // used samples
  2288. if (i - k < k / 441) // if there aren't enough extra samples
  2289. cBlocks -= (1+k/(441*330)); // then decrement the number of blocks
  2290. }
  2291. if(cBlocks == 0)
  2292. {
  2293. padsh->cbDstLengthUsed = 0;
  2294. padsh->cbSrcLengthUsed = 0;
  2295. return (MMSYSERR_NOERROR);
  2296. }
  2297. wSrc = (short *)padsh->pbSrc;
  2298. Dst = (char *)padsh->pbDst;
  2299. frame_size = (CodStat->WrkRate == Rate63) ? 24 : 20;
  2300. silence = 0;
  2301. for(i=0;i<cBlocks;i++)
  2302. {
  2303. if (G723_SAMPLES_PER_BLOCK_PCM[pcm_format] == 330)
  2304. {
  2305. for (k=0; k<330; k++)
  2306. {
  2307. Ebuf[k] = *wSrc++;
  2308. // *** code to adjust from 11025 Hz to 11000 Hz ***
  2309. if (++ CodStat->srccount == 441)
  2310. {
  2311. Ebuf[k] = *wSrc++; // skip a sample
  2312. CodStat->srccount = 0;
  2313. }
  2314. }
  2315. convert11to8(Ebuf,Sbuf,CodStat->srcstate,330);
  2316. for (k=0; k<240; k++)
  2317. SD_Inst->SDstate.Filt.sbuff[k] = (float) Sbuf[k];
  2318. }
  2319. else
  2320. for (k=0; k<240; k++)
  2321. SD_Inst->SDstate.Filt.sbuff[k] = (float) *wSrc++;
  2322. if(pwfg723->wConfigWord & SILENCE_ENABLE)
  2323. {
  2324. prefilter(SD_Inst,SD_Inst->SDstate.Filt.sbuff,
  2325. SD_Inst->SDstate.Filt.storebuff,240);
  2326. getParams(SD_Inst, SD_Inst->SDstate.Filt.storebuff,240);
  2327. execSDloop(SD_Inst,&isFrameSilent,SDThreashold);
  2328. }
  2329. else isFrameSilent = 0;
  2330. if(isFrameSilent)
  2331. {
  2332. *Dst++ = 0x02;
  2333. *Dst++ = 0;
  2334. *Dst++ = 0;
  2335. *Dst++ = 0;
  2336. padsh->cbDstLengthUsed += 4;
  2337. silence++;
  2338. }
  2339. else
  2340. {
  2341. Coder(SD_Inst->SDstate.Filt.sbuff,(Word32*)(long HUGE_T*)Dst,CodStat,0,1,0);
  2342. Dst += frame_size;
  2343. padsh->cbDstLengthUsed += frame_size;
  2344. }
  2345. }
  2346. padsh->cbSrcLengthUsed = pwfxSrc->nBlockAlign
  2347. * (wSrc - (short *)padsh->pbSrc);
  2348. return (MMSYSERR_NOERROR);
  2349. }
  2350. else
  2351. {
  2352. // Decode ---------------------------------------------
  2353. #ifdef DEBUG
  2354. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2355. TTDBG(ghISRInst,TT_TRACE,"Stream Decode padsi=%lx psi=%lx",padsi,psi);
  2356. #endif // } NO_DEBUGGING_OUTPUT
  2357. #endif
  2358. for(pcm_format=0;pcm_format<ACM_DRIVER_MAX_FORMATS_PCM;pcm_format++)
  2359. if (pwfxDst->nSamplesPerSec == PCM_SAMPLING_RATE[pcm_format])
  2360. break;
  2361. if (pcm_format == ACM_DRIVER_MAX_FORMATS_PCM)
  2362. return(MMSYSERR_INVALPARAM);
  2363. DecStat = (DECDEF *)psi;
  2364. cBlocks = 0;
  2365. wDst = (short *)padsh->pbDst;
  2366. Dst_length = padsh->cbDstLength;
  2367. Src = (char *)padsh->pbSrc;
  2368. src_length = padsh->cbSrcLength;
  2369. padsh->cbSrcLengthUsed = 0;
  2370. while(src_length > 0)
  2371. {
  2372. switch(*Src&3)
  2373. {
  2374. case 0 :
  2375. DecStat->WrkRate = Rate63;
  2376. frame_size = 24;
  2377. break;
  2378. case 1 :
  2379. DecStat->WrkRate = Rate53;
  2380. frame_size = 20;
  2381. break;
  2382. case 2 :
  2383. // DecStat->WrkRate = Silent; // Uncomment for V5.0 of G.723.1
  2384. frame_size = 4; // this is an SID frame
  2385. break;
  2386. case 3 :
  2387. DecStat->WrkRate = Lost;
  2388. frame_size = 4;
  2389. break;
  2390. }
  2391. src_length-=frame_size;
  2392. if(src_length < 0) break; // just in case we are given a partial frame
  2393. memcpy(tmpbuf,(long HUGE_T *)Src,frame_size);
  2394. Decod(Dbuf,(Word32*)(long HUGE_T*)tmpbuf,0,DecStat);
  2395. Src += frame_size;
  2396. padsh->cbSrcLengthUsed += frame_size;
  2397. cBlocks++;
  2398. if (G723_SAMPLES_PER_BLOCK_PCM[pcm_format] == 330)
  2399. {
  2400. //
  2401. // Ouput Sampling rate is 11025 Hz
  2402. //
  2403. if (440 - DecStat->srccount <= 240) // need to insert a sample?
  2404. {
  2405. DecStat->srcbuff[DecStat->i++] = FLOATTOSHORT(Dbuf[0]);
  2406. if (++ DecStat->srccount == 440) DecStat->srccount = 0;
  2407. DecStat->srcbuff[DecStat->i++] = FLOATTOSHORT(0.25 * Dbuf[0]
  2408. + 0.75 * Dbuf[1]);
  2409. if (++ DecStat->srccount == 440) DecStat->srccount = 0;
  2410. DecStat->srcbuff[DecStat->i++] = FLOATTOSHORT(0.50 * Dbuf[1]
  2411. + 0.50 * Dbuf[2]);
  2412. if (++ DecStat->srccount == 440) DecStat->srccount = 0;
  2413. DecStat->srcbuff[DecStat->i++] = FLOATTOSHORT(0.75 * Dbuf[2]
  2414. + 0.25 * Dbuf[3]);
  2415. if (++ DecStat->srccount == 440) DecStat->srccount = 0;
  2416. m = 3;
  2417. }
  2418. else m = 0;
  2419. for (k=m; k<240; k++)
  2420. {
  2421. DecStat->srcbuff[DecStat->i++] = FLOATTOSHORT(Dbuf[k]);
  2422. if (++ DecStat->srccount == 440)
  2423. DecStat->srccount = 0;
  2424. }
  2425. if (DecStat->i == 480)
  2426. {
  2427. //
  2428. // *** 240 extra samples have accumulated ***
  2429. //
  2430. convert8to11(DecStat->srcbuff,wDst,DecStat->srcstate,480);
  2431. Dst_length -= 1320; // two output frames (1320 bytes)
  2432. wDst += 660;
  2433. DecStat->i = 0;
  2434. if(Dst_length < 1320) break; // no more space in output buffer
  2435. }
  2436. else
  2437. {
  2438. //
  2439. // *** less than 240 extra samples have accumulated ***
  2440. //
  2441. convert8to11(DecStat->srcbuff,wDst,DecStat->srcstate,240);
  2442. Dst_length -= 660; // one output frame (660 bytes)
  2443. wDst += 330;
  2444. //
  2445. // move partial frame to the front of the SRC buffer
  2446. //
  2447. for(i=0;i<DecStat->i-240;i++)
  2448. DecStat->srcbuff[i] = DecStat->srcbuff[i+240];
  2449. DecStat->i -=240;
  2450. if(Dst_length < 1320) break; // no more space in output buffer
  2451. }
  2452. }
  2453. else
  2454. {
  2455. //
  2456. // Ouput Sampling rate is 8000 Hz
  2457. //
  2458. for (k=0; k<240; k++)
  2459. {
  2460. temp = FLOATTOSHORT(Dbuf[k]);
  2461. *wDst++ = temp;
  2462. }
  2463. Dst_length -= 480; // we just chewed up 480 bytes;
  2464. if(Dst_length < 480) break; // we can't do any more!
  2465. }
  2466. }
  2467. padsh->cbDstLengthUsed = pwfxDst->nBlockAlign * cBlocks
  2468. * G723_SAMPLES_PER_BLOCK_PCM[pcm_format];
  2469. }
  2470. return (MMSYSERR_NOERROR);
  2471. } // acmdStreamConvert()
  2472. //==========================================================================;
  2473. //
  2474. //
  2475. //
  2476. //
  2477. //==========================================================================;
  2478. //--------------------------------------------------------------------------;
  2479. //
  2480. // LRESULT DriverProc
  2481. //
  2482. // Description:
  2483. //
  2484. //
  2485. // Arguments:
  2486. // DWORD dwId: For most messages, dwId is the DWORD value that
  2487. // the driver returns in response to a DRV_OPEN message. Each time
  2488. // the driver is opened, through the OpenDriver API, the driver
  2489. // receives a DRV_OPEN message and can return an arbitrary, non-zero
  2490. // value. The installable driver interface saves this value and returns
  2491. // a unique driver handle to the application. Whenever the application
  2492. // sends a message to the driver using the driver handle, the interface
  2493. // routes the message to this entry point and passes the corresponding
  2494. // dwId. This mechanism allows the driver to use the same or different
  2495. // identifiers for multiple opens but ensures that driver handles are
  2496. // unique at the application interface layer.
  2497. //
  2498. // The following messages are not related to a particular open instance
  2499. // of the driver. For these messages, the dwId will always be zero.
  2500. //
  2501. // DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN
  2502. //
  2503. // HDRVR hdrvr: This is the handle returned to the application
  2504. // by the driver interface.
  2505. //
  2506. // UINT uMsg: The requested action to be performed. Message
  2507. // values below DRV_RESERVED are used for globally defined messages.
  2508. // Message values from DRV_RESERVED to DRV_USER are used for defined
  2509. // driver protocols. Messages above DRV_USER are used for driver
  2510. // specific messages.
  2511. //
  2512. // LPARAM lParam1: Data for this message. Defined separately for
  2513. // each message.
  2514. //
  2515. // LPARAM lParam2: Data for this message. Defined separately for
  2516. // each message.
  2517. //
  2518. // Return (LRESULT):
  2519. // Defined separately for each message.
  2520. //
  2521. //--------------------------------------------------------------------------;
  2522. EXTERN_C LRESULT FNEXPORT DriverProc
  2523. (
  2524. DWORD dwId,
  2525. HDRVR hdrvr,
  2526. UINT uMsg,
  2527. LPARAM lParam1,
  2528. LPARAM lParam2
  2529. )
  2530. {
  2531. LRESULT lr;
  2532. PDRIVERINSTANCE pdi;
  2533. int k;
  2534. //
  2535. // make pdi either NULL or a valid instance pointer. note that dwId
  2536. // is 0 for several of the DRV_* messages (ie DRV_LOAD, DRV_OPEN...)
  2537. // see acmdDriverOpen for information on what dwId is for other
  2538. // messages (instance data).
  2539. //
  2540. #ifdef DEBUG
  2541. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2542. TTDBG(ghISRInst,TT_TRACE,"DriverProc uMsg=%x lParam1=%lx lParam2=%lx",uMsg,lParam1,lParam2);
  2543. #endif // } NO_DEBUGGING_OUTPUT
  2544. #endif
  2545. pdi = (PDRIVERINSTANCE)(UINT)dwId;
  2546. switch (uMsg)
  2547. {
  2548. //
  2549. // lParam1: Unused.
  2550. //
  2551. // lParam2: Unused.
  2552. //
  2553. case DRV_LOAD:
  2554. #ifdef _WIN32
  2555. DbgInitialize(TRUE);
  2556. #endif
  2557. return(1L);
  2558. //
  2559. // lParam1: Unused.
  2560. //
  2561. // lParam2: Unused.
  2562. //
  2563. case DRV_FREE:
  2564. return (1L);
  2565. //
  2566. // lParam1: Not used. Ignore this argument.
  2567. //
  2568. // lParam2: Pointer to ACMDRVOPENDESC (or NULL).
  2569. //
  2570. case DRV_OPEN:
  2571. lr = acmdDriverOpen(hdrvr, (LPACMDRVOPENDESC)lParam2);
  2572. return (lr);
  2573. //
  2574. // lParam1: Unused.
  2575. //
  2576. // lParam2: Unused.
  2577. //
  2578. case DRV_CLOSE:
  2579. #ifdef DEBUG
  2580. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2581. TTDBG(ghISRInst,TT_TRACE,"Driver Closed");
  2582. #endif // } NO_DEBUGGING_OUTPUT
  2583. #endif
  2584. lr = acmdDriverClose(pdi);
  2585. return (lr);
  2586. //
  2587. // lParam1: Unused.
  2588. //
  2589. // lParam2: Unused.
  2590. //
  2591. case DRV_INSTALL:
  2592. return ((LRESULT)DRVCNF_RESTART);
  2593. //
  2594. // lParam1: Unused.
  2595. //
  2596. // lParam2: Unused.
  2597. //
  2598. case DRV_REMOVE:
  2599. return ((LRESULT)DRVCNF_RESTART);
  2600. //
  2601. // lParam1: Not used.
  2602. //
  2603. // lParam2: Not used.
  2604. //
  2605. case DRV_QUERYCONFIGURE:
  2606. //
  2607. // set up lParam1 and lParam2 to values that can be used by
  2608. // acmdDriverConfigure to know that it is being 'queried'
  2609. // for configuration support.
  2610. //
  2611. lParam1 = -1L;
  2612. lParam2 = 0L;
  2613. //--fall through--//
  2614. //
  2615. // lParam1: Handle to parent window for the configuration dialog
  2616. // box.
  2617. //
  2618. // lParam2: Optional pointer to DRVCONFIGINFO structure.
  2619. //
  2620. case DRV_CONFIGURE:
  2621. lr = acmdDriverConfigure(pdi, (HWND)lParam1, (LPDRVCONFIGINFO)lParam2);
  2622. return (lr);
  2623. //
  2624. // lParam1: Pointer to ACMDRIVERDETAILS structure.
  2625. //
  2626. // lParam2: Size in bytes of ACMDRIVERDETAILS stucture passed.
  2627. //
  2628. case ACMDM_DRIVER_DETAILS:
  2629. lr = acmdDriverDetails(pdi, (LPACMDRIVERDETAILS)lParam1);
  2630. return (lr);
  2631. //
  2632. // lParam1: Handle to parent window to use if displaying your own
  2633. // about box.
  2634. //
  2635. // lParam2: Not used.
  2636. //
  2637. case ACMDM_DRIVER_ABOUT:
  2638. lr = acmdDriverAbout(pdi, (HWND)lParam1);
  2639. return (lr);
  2640. //--------------------------------------------------------------------------;
  2641. //--------------------------------------------------------------------------;
  2642. //
  2643. // lParam1: Pointer to ACMDRVFORMATSUGGEST structure.
  2644. //
  2645. // lParam2: Not used.
  2646. //
  2647. case ACMDM_FORMAT_SUGGEST:
  2648. lr = acmdFormatSuggest(pdi, (LPACMDRVFORMATSUGGEST)lParam1);
  2649. return (lr);
  2650. //
  2651. // lParam1: Pointer to FORMATTAGDETAILS structure.
  2652. //
  2653. // lParam2: fdwDetails
  2654. //
  2655. case ACMDM_FORMATTAG_DETAILS:
  2656. lr = acmdFormatTagDetails(pdi, (LPACMFORMATTAGDETAILS)lParam1, lParam2);
  2657. return (lr);
  2658. //
  2659. // lParam1: Pointer to FORMATDETAILS structure.
  2660. //
  2661. // lParam2: fdwDetails
  2662. //
  2663. case ACMDM_FORMAT_DETAILS:
  2664. lr = acmdFormatDetails(pdi, (LPACMFORMATDETAILS)lParam1, lParam2);
  2665. return (lr);
  2666. //--------------------------------------------------------------------------;
  2667. //--------------------------------------------------------------------------;
  2668. //
  2669. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2670. //
  2671. // lParam2: Not used.
  2672. //
  2673. case ACMDM_STREAM_OPEN:
  2674. lr = acmdStreamOpen(pdi, (LPACMDRVSTREAMINSTANCE)lParam1);
  2675. #ifdef DEBUG
  2676. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2677. TTDBG(ghISRInst,TT_TRACE,"Stream open result: %d",lr);
  2678. #endif // } NO_DEBUGGING_OUTPUT
  2679. #endif
  2680. return (lr);
  2681. //
  2682. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2683. //
  2684. // lParam2: Not Used.
  2685. //
  2686. case ACMDM_STREAM_CLOSE:
  2687. lr = acmdStreamClose((LPACMDRVSTREAMINSTANCE)lParam1);
  2688. #ifdef DEBUG
  2689. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2690. TTDBG(ghISRInst,TT_TRACE,"Stream close result: %d",lr);
  2691. #endif // } NO_DEBUGGING_OUTPUT
  2692. #endif
  2693. return (lr);
  2694. //
  2695. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2696. //
  2697. // lParam2: Pointer to ACMDRVSTREAMSIZE structure.
  2698. //
  2699. case ACMDM_STREAM_SIZE:
  2700. lr = acmdStreamSize((LPACMDRVSTREAMINSTANCE)lParam1,
  2701. (LPACMDRVSTREAMSIZE)lParam2);
  2702. return (lr);
  2703. //
  2704. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2705. //
  2706. // lParam2: Pointer to ACMDRVSTREAMHEADER structure.
  2707. //
  2708. case ACMDM_STREAM_CONVERT:
  2709. if (pdi->enabled)
  2710. {
  2711. lr = acmdStreamConvert(pdi, (LPACMDRVSTREAMINSTANCE)lParam1,
  2712. (LPACMDRVSTREAMHEADER)lParam2);
  2713. return (lr);
  2714. }
  2715. else return(MMSYSERR_NOTSUPPORTED);
  2716. //
  2717. // lParam1: Setting for Silence detector threashold.
  2718. //
  2719. // lParam2: Not used. Ignore this argument.
  2720. //
  2721. case DRV_USER:
  2722. k = (int)SDThreashold;
  2723. #ifdef DEBUG
  2724. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2725. TTDBG(ghISRInst,TT_TRACE,"Old Threashold = %d",k);
  2726. #endif // } NO_DEBUGGING_OUTPUT
  2727. #endif
  2728. SDThreashold = (float)lParam1;
  2729. #ifdef DEBUG
  2730. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2731. TTDBG(ghISRInst,TT_TRACE,"Setting Threashold to %ld",lParam1);
  2732. #endif // } NO_DEBUGGING_OUTPUT
  2733. #endif
  2734. return (lParam1);
  2735. #ifndef NOTPRODUCT
  2736. //
  2737. // DRV_USER+1
  2738. //
  2739. // lParam1: Pointer to ACMDRVSTREAMINSTANCE structure.
  2740. //
  2741. // lParam2: 0 = PCM stream, 1 = G.723.1 stream
  2742. //
  2743. case DRV_USER+1:
  2744. if (lParam1 == G723MAGICWORD1 && lParam2 == G723MAGICWORD2)
  2745. pdi->enabled = TRUE;
  2746. else
  2747. pdi->enabled = FALSE;
  2748. return (MMSYSERR_NOERROR);
  2749. #endif // NOTPRODUCT
  2750. }
  2751. //
  2752. // if we are executing the following code, then this ACM driver does not
  2753. // handle the message that was sent. there are two ranges of messages
  2754. // we need to deal with:
  2755. //
  2756. // o ACM specific driver messages: if an ACM driver does not answer a
  2757. // message sent in the ACM driver message range, then it must
  2758. // return MMSYSERR_NOTSUPPORTED. this applies to the 'user'
  2759. // range as well (for consistency).
  2760. //
  2761. // o other installable driver messages: if an ACM driver does not
  2762. // answer a message that is NOT in the ACM driver message range,
  2763. // then it must call DefDriverProc and return that result.
  2764. // the exception to this is ACM driver procedures installed as
  2765. // ACM_DRIVERADDF_FUNCTION through acmDriverAdd. in this case,
  2766. // the driver procedure should conform to the ACMDRIVERPROC
  2767. // prototype and also return zero instead of calling DefDriverProc.
  2768. //
  2769. #ifdef DEBUG
  2770. #ifndef NO_DEBUGGING_OUTPUT // { NO_DEBUGGING_OUTPUT
  2771. TTDBG(ghISRInst,TT_TRACE,"Unknown command %d / %d",uMsg,DRV_USER);
  2772. #endif // } NO_DEBUGGING_OUTPUT
  2773. #endif
  2774. if (uMsg >= ACMDM_USER)
  2775. return (MMSYSERR_NOTSUPPORTED);
  2776. else
  2777. return (DefDriverProc(dwId, hdrvr, uMsg, lParam1, lParam2));
  2778. } // DriverProc()