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.

579 lines
16 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // wavfmt.c - wave format functions
  24. ////
  25. #include "winlocal.h"
  26. #include <stdlib.h>
  27. #include <stddef.h>
  28. #include "wavfmt.h"
  29. #include "calc.h"
  30. #include "mem.h"
  31. #include "trace.h"
  32. ////
  33. // private definitions
  34. ////
  35. #define SAMPLERATE_DEFAULT 11025
  36. #define SAMPLERATE_MAX 64000
  37. #define SAMPLERATE_MIN 1000
  38. #define SAMPLESIZE_DEFAULT 8
  39. #define SAMPLESIZE_MAX 32
  40. #define SAMPLESIZE_MIN 0
  41. #define CHANNELS_DEFAULT 1
  42. #define CHANNELS_MAX 2
  43. #define CHANNELS_MIN 1
  44. ////
  45. // public functions
  46. ////
  47. // WavFormatPcm - fill WAVEFORMATEX struct based on PCM characteristics
  48. // <nSamplesPerSec> (i) sample rate
  49. // -1 default sample rate (11025)
  50. // <nBitsPerSample> (i) sample size
  51. // -1 default sample size (8)
  52. // <nChannels> (i) number of channels (1=mono, 2=stereo)
  53. // -1 default (mono)
  54. // <lpwfx> (o) pointer to output buffer
  55. // NULL allocate new buffer to hold result
  56. // return pointer to WAVEFORMATEX struct, NULL if error
  57. //
  58. // NOTE: if <lpwfx> points to a WAVEFORMATEX struct, this struct
  59. // is filled in, and this function returns <lpwfx>.
  60. // If <lpwfx> is NULL, space is dynamically allocated for the output
  61. // buffer, and this function returns a pointer to the output buffer.
  62. // Use WavFormatFree() to free the buffer.
  63. //
  64. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatPcm(long nSamplesPerSec,
  65. WORD nBitsPerSample, WORD nChannels, LPWAVEFORMATEX lpwfx)
  66. {
  67. BOOL fSuccess = TRUE;
  68. LPWAVEFORMATEX lpwfxNew = lpwfx;
  69. if (nSamplesPerSec == -1)
  70. nSamplesPerSec = SAMPLERATE_DEFAULT;
  71. if (nBitsPerSample == -1)
  72. nBitsPerSample = SAMPLESIZE_DEFAULT;
  73. if (nChannels == -1)
  74. nChannels = CHANNELS_DEFAULT;
  75. // user passed struct to fill
  76. //
  77. if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  78. fSuccess = TraceFALSE(NULL);
  79. // we allocate struct to fill
  80. //
  81. else if (lpwfx == NULL
  82. && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL)
  83. fSuccess = TraceFALSE(NULL);
  84. // fill the struct
  85. //
  86. else
  87. {
  88. lpwfxNew->wFormatTag = WAVE_FORMAT_PCM;
  89. lpwfxNew->nChannels = nChannels;
  90. lpwfxNew->nSamplesPerSec = nSamplesPerSec;
  91. lpwfxNew->nBlockAlign = nChannels * (((nBitsPerSample - 1) / 8) + 1);
  92. lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec;
  93. lpwfxNew->wBitsPerSample = nBitsPerSample;
  94. lpwfxNew->cbSize = 0;
  95. }
  96. return fSuccess ? lpwfxNew : NULL;
  97. }
  98. // WavFormatAlloc - allocate WAVEFORMATEX struct buffer
  99. // <cbSize> (i) size of struct, including extra bytes
  100. // return pointer to WAVEFORMATEX struct, NULL if error
  101. //
  102. // NOTE: use WavFormatFree() to free the buffer.
  103. //
  104. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatAlloc(WORD cbSize)
  105. {
  106. BOOL fSuccess = TRUE;
  107. LPWAVEFORMATEX lpwfx;
  108. if (cbSize < sizeof(WAVEFORMATEX))
  109. fSuccess = TraceFALSE(NULL);
  110. // memory is allocated such that the client owns it
  111. //
  112. else if ((lpwfx = (LPWAVEFORMATEX) MemAlloc(NULL, cbSize, 0)) == NULL)
  113. fSuccess = TraceFALSE(NULL);
  114. else
  115. lpwfx->cbSize = cbSize - sizeof(WAVEFORMATEX);
  116. return fSuccess ? lpwfx : NULL;
  117. }
  118. // WavFormatDup - duplicate WAVEFORMATEX structure
  119. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  120. // return pointer to new WAVEFORMATEX struct, NULL if error
  121. //
  122. // NOTE: use WavFormatFree() to free the buffer.
  123. //
  124. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatDup(LPWAVEFORMATEX lpwfx)
  125. {
  126. BOOL fSuccess = TRUE;
  127. LPWAVEFORMATEX lpwfxNew;
  128. if (lpwfx == NULL)
  129. fSuccess = TraceFALSE(NULL);
  130. else if (IsBadReadPtr(lpwfx, WavFormatGetSize(lpwfx)))
  131. fSuccess = TraceFALSE(NULL);
  132. else if ((lpwfxNew = WavFormatAlloc((WORD)
  133. WavFormatGetSize(lpwfx))) == NULL)
  134. fSuccess = TraceFALSE(NULL);
  135. else
  136. MemCpy(lpwfxNew, lpwfx, WavFormatGetSize(lpwfx));
  137. return fSuccess ? lpwfxNew : NULL;
  138. }
  139. // WavFormatFree - free WAVEFORMATEX struct
  140. // <lpwfx> (i) pointer returned from WavFormatAlloc/Dup/Pcm
  141. // return 0 if success
  142. //
  143. int DLLEXPORT WINAPI WavFormatFree(LPWAVEFORMATEX lpwfx)
  144. {
  145. BOOL fSuccess = TRUE;
  146. if (lpwfx == NULL)
  147. fSuccess = TraceFALSE(NULL);
  148. else if ((lpwfx = MemFree(NULL, lpwfx)) != NULL)
  149. fSuccess = TraceFALSE(NULL);
  150. return fSuccess ? 0 : -1;
  151. }
  152. // WavFormatIsValid - check format for validity
  153. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  154. // return TRUE if valid format
  155. //
  156. BOOL DLLEXPORT WINAPI WavFormatIsValid(LPWAVEFORMATEX lpwfx)
  157. {
  158. BOOL fSuccess = TRUE;
  159. if (lpwfx == NULL)
  160. fSuccess = TraceFALSE(NULL);
  161. else if (IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  162. fSuccess = TraceFALSE(NULL);
  163. else if (IsBadReadPtr(lpwfx, WavFormatGetSize(lpwfx)))
  164. fSuccess = TraceFALSE(NULL);
  165. else if (lpwfx->nSamplesPerSec < SAMPLERATE_MIN ||
  166. lpwfx->nSamplesPerSec > SAMPLERATE_MAX)
  167. fSuccess = TraceFALSE(NULL);
  168. else if (lpwfx->wBitsPerSample < SAMPLESIZE_MIN ||
  169. lpwfx->wBitsPerSample > SAMPLESIZE_MAX)
  170. fSuccess = TraceFALSE(NULL);
  171. else if (lpwfx->nChannels < CHANNELS_MIN ||
  172. lpwfx->nChannels > CHANNELS_MAX)
  173. fSuccess = TraceFALSE(NULL);
  174. return fSuccess ? TRUE : FALSE;
  175. }
  176. // WavFormatCmp - compare one format with another
  177. // <lpwfx1> (i) pointer to WAVEFORMATEX struct
  178. // <lpwfx2> (i) pointer to WAVEFORMATEX struct
  179. // return 0 if identical
  180. //
  181. #if 0
  182. // NOTE: this function does NOT compare the cbSize field or the extra bytes
  183. #else
  184. // NOTE: this function does NOT compare the extra bytes beyond the cbSize field
  185. #endif
  186. //
  187. int DLLEXPORT WINAPI WavFormatCmp(LPWAVEFORMATEX lpwfx1, LPWAVEFORMATEX lpwfx2)
  188. {
  189. BOOL fSuccess = TRUE;
  190. int nCmp = 0; // assume identical
  191. if (!WavFormatIsValid(lpwfx1))
  192. fSuccess = TraceFALSE(NULL);
  193. else if (!WavFormatIsValid(lpwfx2))
  194. fSuccess = TraceFALSE(NULL);
  195. else
  196. {
  197. #if 0
  198. // compare up to (but not including) the cbSize field
  199. //
  200. nCmp = MemCmp(lpwfx1, lpwfx2,
  201. offsetof(WAVEFORMATEX, cbSize));
  202. #else
  203. // compare up to and including the cbSize field
  204. //
  205. nCmp = MemCmp(lpwfx1, lpwfx2, sizeof(WAVEFORMATEX));
  206. #endif
  207. }
  208. return fSuccess ? nCmp : -1;
  209. }
  210. // WavFormatCopy - copy one format to another
  211. // <lpwfxDst> (i) pointer to destination WAVEFORMATEX struct
  212. // <lpwfxSrc> (i) pointer to source WAVEFORMATEX struct
  213. // return 0 if success
  214. //
  215. #if 0
  216. // NOTE: this function does NOT copy the cbSize field or the extra bytes
  217. #else
  218. // NOTE: make sure lpwfxDst points to enough memory to contain the entire
  219. // WAVEFORMATEX struct plus any extra bytes beyond it
  220. #endif
  221. //
  222. int DLLEXPORT WINAPI WavFormatCopy(LPWAVEFORMATEX lpwfxDst, LPWAVEFORMATEX lpwfxSrc)
  223. {
  224. BOOL fSuccess = TRUE;
  225. if (!WavFormatIsValid(lpwfxSrc))
  226. fSuccess = TraceFALSE(NULL);
  227. else if (lpwfxDst == NULL)
  228. fSuccess = TraceFALSE(NULL);
  229. #if 0
  230. // make sure destination is at least as big as WAVEFORMATEX struct
  231. //
  232. else if (IsBadReadPtr(lpwfxDst, sizeof(WAVEFORMATEX))
  233. fSuccess = TraceFALSE(NULL);
  234. else
  235. {
  236. // copy up to (but not including) the cbSize field
  237. //
  238. MemCpy(lpwfxDst, lpwfxSrc,
  239. offsetof(WAVEFORMATEX, cbSize));
  240. }
  241. #else
  242. // make sure destination is at least as big as source
  243. //
  244. else if (IsBadReadPtr(lpwfxDst, WavFormatGetSize(lpwfxSrc)))
  245. fSuccess = TraceFALSE(NULL);
  246. else
  247. {
  248. // copy entire structure, including any extra bytes
  249. //
  250. MemCpy(lpwfxDst, lpwfxSrc, WavFormatGetSize(lpwfxSrc));
  251. }
  252. #endif
  253. return fSuccess ? 0 : -1;
  254. }
  255. // WavFormatGetSize - check size of format structure
  256. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  257. // return size of structure, 0 if error
  258. //
  259. int DLLEXPORT WINAPI WavFormatGetSize(LPWAVEFORMATEX lpwfx)
  260. {
  261. BOOL fSuccess = TRUE;
  262. int sizwfx = 0;
  263. if (lpwfx == NULL)
  264. fSuccess = TraceFALSE(NULL);
  265. // ignore cbSize value if pcm format
  266. //
  267. else if (lpwfx->wFormatTag == WAVE_FORMAT_PCM)
  268. sizwfx = sizeof(WAVEFORMATEX);
  269. else
  270. sizwfx = sizeof(WAVEFORMATEX) + lpwfx->cbSize;
  271. return fSuccess ? sizwfx : 0;
  272. }
  273. // WavFormatDump - dump WAVEFORMATEX struct to debug
  274. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  275. // return 0 if success
  276. //
  277. int DLLEXPORT WINAPI WavFormatDump(LPWAVEFORMATEX lpwfx)
  278. {
  279. BOOL fSuccess = TRUE;
  280. if (lpwfx == NULL)
  281. fSuccess = TraceFALSE(NULL);
  282. else if (IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  283. fSuccess = TraceFALSE(NULL);
  284. else
  285. {
  286. TracePrintf_7(NULL, 1,
  287. TEXT("struct tWAVEFORMATEX\n")
  288. TEXT("{\n")
  289. TEXT("\tWORD\twFormatTag = %u;\n")
  290. TEXT("\tWORD\tnChannels = %u;\n")
  291. TEXT("\tDWORD\tnSamplesPerSec = %lu;\n")
  292. TEXT("\tDWORD\tnAvgBytesPerSec = %lu;\n")
  293. TEXT("\tWORD\tnBlockAlign = %u;\n")
  294. TEXT("\tWORD\twBitsPerSample = %u;\n")
  295. TEXT("\tWORD\tcbSize = %u;\n")
  296. TEXT("} WAVEFORMATEX\n"),
  297. (unsigned int) lpwfx->wFormatTag,
  298. (unsigned int) lpwfx->nChannels,
  299. (unsigned long) lpwfx->nSamplesPerSec,
  300. (unsigned long) lpwfx->nAvgBytesPerSec,
  301. (unsigned int) lpwfx->nBlockAlign,
  302. (unsigned int) lpwfx->wBitsPerSample,
  303. (unsigned int) lpwfx->cbSize);
  304. }
  305. return fSuccess ? 0 : -1;
  306. }
  307. // WavFormatBytesToMilleseconds - convert bytes to milleseconds
  308. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  309. // <dwBytes> (i) bytes
  310. // return milleseconds
  311. //
  312. DWORD DLLEXPORT WINAPI WavFormatBytesToMilleseconds(LPWAVEFORMATEX lpwfx, DWORD dwBytes)
  313. {
  314. if (lpwfx == NULL || lpwfx->nAvgBytesPerSec == 0)
  315. return 0;
  316. else
  317. return MULDIVU32(dwBytes, 1000, (DWORD) lpwfx->nAvgBytesPerSec);
  318. }
  319. // WavFormatMillesecondsToBytes - convert milleseconds to bytes
  320. // <lpwfx> (i) pointer to WAVEFORMATEX struct
  321. // <dwMilleseconds> (i) milleseconds
  322. // return milleseconds
  323. //
  324. DWORD DLLEXPORT WINAPI WavFormatMillesecondsToBytes(LPWAVEFORMATEX lpwfx, DWORD dwMilleseconds)
  325. {
  326. if (lpwfx == NULL || lpwfx->nAvgBytesPerSec == 0)
  327. return 0;
  328. else
  329. return MULDIVU32(dwMilleseconds, (DWORD) lpwfx->nAvgBytesPerSec, 1000);
  330. }
  331. // WavFormatSpeedAdjust - adjust format to reflect specified speed
  332. // <lpwfx> (i/o) pointer to WAVEFORMATEX struct
  333. // <nLevel> (i) speed level
  334. // 50 half speed
  335. // 100 normal speed
  336. // 200 double speed, etc.
  337. // <dwFlags> (i) reserved; must be zero
  338. // return 0 if success
  339. //
  340. int DLLEXPORT WINAPI WavFormatSpeedAdjust(LPWAVEFORMATEX lpwfx, int nLevel, DWORD dwFlags)
  341. {
  342. BOOL fSuccess = TRUE;
  343. if (lpwfx == NULL)
  344. fSuccess = TraceFALSE(NULL);
  345. else if (nLevel != 100)
  346. {
  347. lpwfx->nSamplesPerSec = lpwfx->nSamplesPerSec * nLevel / 100;
  348. lpwfx->nAvgBytesPerSec = lpwfx->nBlockAlign * lpwfx->nSamplesPerSec;
  349. }
  350. return fSuccess ? 0 : -1;
  351. }
  352. // WavFormatVoxadpcm - fill WAVEFORMATEX struct for Dialogic OKI ADPCM
  353. // <lpwfx> (o) pointer to output buffer
  354. // NULL allocate new buffer to hold result
  355. // <nSamplesPerSec> (i) sample rate
  356. // -1 default sample rate (6000)
  357. // return pointer to WAVEFORMATEX struct, NULL if error
  358. //
  359. // NOTE: if <lpwfx> points to a WAVEFORMATEX struct, this struct
  360. // is filled in, and this function returns <lpwfx>.
  361. // If <lpwfx> is NULL, space is dynamically allocated for the output
  362. // buffer, and this function returns a pointer to the output buffer.
  363. // Use WavFormatFree() to free the buffer.
  364. //
  365. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatVoxadpcm(LPWAVEFORMATEX lpwfx, long nSamplesPerSec)
  366. {
  367. BOOL fSuccess = TRUE;
  368. LPWAVEFORMATEX lpwfxNew = lpwfx;
  369. WORD nBitsPerSample = 4;
  370. WORD nChannels = 1;
  371. #if 0
  372. // nBlockAlign is 4 so that chunk size of 5188 is returned from
  373. // WavCalcChunkSize(VoxFormat(NULL, 6000), 1962, TRUE);
  374. // 5188 is optimal for Dialogic buffer logic (((12 * 1024) - 512) / 2)
  375. //
  376. WORD nBlockAlign = 4;
  377. #else
  378. WORD nBlockAlign = 1;
  379. #endif
  380. if (nSamplesPerSec == -1)
  381. nSamplesPerSec = 6000;
  382. // user passed struct to fill
  383. //
  384. if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  385. fSuccess = TraceFALSE(NULL);
  386. // we allocate struct to fill
  387. //
  388. else if (lpwfx == NULL
  389. && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL)
  390. fSuccess = TraceFALSE(NULL);
  391. // fill the struct
  392. //
  393. else
  394. {
  395. lpwfxNew->wFormatTag = WAVE_FORMAT_DIALOGIC_OKI_ADPCM;
  396. lpwfxNew->nChannels = nChannels;
  397. lpwfxNew->nSamplesPerSec = nSamplesPerSec;
  398. lpwfxNew->nBlockAlign = nBlockAlign;
  399. lpwfxNew->nAvgBytesPerSec = nSamplesPerSec / 2;
  400. lpwfxNew->wBitsPerSample = nBitsPerSample;
  401. lpwfxNew->cbSize = 0;
  402. }
  403. return fSuccess ? lpwfxNew : NULL;
  404. }
  405. // WavFormatMulaw - fill WAVEFORMATEX struct for CCITT u-law format
  406. // <lpwfx> (o) pointer to output buffer
  407. // NULL allocate new buffer to hold result
  408. // <nSamplesPerSec> (i) sample rate
  409. // -1 default sample rate (8000)
  410. // return pointer to WAVEFORMATEX struct, NULL if error
  411. //
  412. // NOTE: if <lpwfx> points to a WAVEFORMATEX struct, this struct
  413. // is filled in, and this function returns <lpwfx>.
  414. // If <lpwfx> is NULL, space is dynamically allocated for the output
  415. // buffer, and this function returns a pointer to the output buffer.
  416. // Use WavFormatFree() to free the buffer.
  417. //
  418. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatMulaw(LPWAVEFORMATEX lpwfx, long nSamplesPerSec)
  419. {
  420. BOOL fSuccess = TRUE;
  421. LPWAVEFORMATEX lpwfxNew = lpwfx;
  422. WORD nBitsPerSample = 8;
  423. WORD nChannels = 1;
  424. WORD nBlockAlign = 1;
  425. if (nSamplesPerSec == -1)
  426. nSamplesPerSec = 8000;
  427. // user passed struct to fill
  428. //
  429. if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  430. fSuccess = TraceFALSE(NULL);
  431. // we allocate struct to fill
  432. //
  433. else if (lpwfx == NULL
  434. && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL)
  435. fSuccess = TraceFALSE(NULL);
  436. // fill the struct
  437. //
  438. else
  439. {
  440. lpwfxNew->wFormatTag = WAVE_FORMAT_MULAW;
  441. lpwfxNew->nChannels = nChannels;
  442. lpwfxNew->nSamplesPerSec = nSamplesPerSec;
  443. lpwfxNew->nBlockAlign = nBlockAlign;
  444. lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec;
  445. lpwfxNew->wBitsPerSample = nBitsPerSample;
  446. lpwfxNew->cbSize = 0;
  447. }
  448. return fSuccess ? lpwfxNew : NULL;
  449. }
  450. // WavFormatAlaw - fill WAVEFORMATEX struct for CCITT a-law format
  451. // <lpwfx> (o) pointer to output buffer
  452. // NULL allocate new buffer to hold result
  453. // <nSamplesPerSec> (i) sample rate
  454. // -1 default sample rate (8000)
  455. // return pointer to WAVEFORMATEX struct, NULL if error
  456. //
  457. // NOTE: if <lpwfx> points to a WAVEFORMATEX struct, this struct
  458. // is filled in, and this function returns <lpwfx>.
  459. // If <lpwfx> is NULL, space is dynamically allocated for the output
  460. // buffer, and this function returns a pointer to the output buffer.
  461. // Use WavFormatFree() to free the buffer.
  462. //
  463. LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatAlaw(LPWAVEFORMATEX lpwfx, long nSamplesPerSec)
  464. {
  465. BOOL fSuccess = TRUE;
  466. LPWAVEFORMATEX lpwfxNew = lpwfx;
  467. WORD nBitsPerSample = 8;
  468. WORD nChannels = 1;
  469. WORD nBlockAlign = 1;
  470. if (nSamplesPerSec == -1)
  471. nSamplesPerSec = 8000;
  472. // user passed struct to fill
  473. //
  474. if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX)))
  475. fSuccess = TraceFALSE(NULL);
  476. // we allocate struct to fill
  477. //
  478. else if (lpwfx == NULL
  479. && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL)
  480. fSuccess = TraceFALSE(NULL);
  481. // fill the struct
  482. //
  483. else
  484. {
  485. lpwfxNew->wFormatTag = WAVE_FORMAT_ALAW;
  486. lpwfxNew->nChannels = nChannels;
  487. lpwfxNew->nSamplesPerSec = nSamplesPerSec;
  488. lpwfxNew->nBlockAlign = nBlockAlign;
  489. lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec;
  490. lpwfxNew->wBitsPerSample = nBitsPerSample;
  491. lpwfxNew->cbSize = 0;
  492. }
  493. return fSuccess ? lpwfxNew : NULL;
  494. }