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.

916 lines
23 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. // vox.c - vox file format (OKI ADPCM) functions
  24. ////
  25. #include "winlocal.h"
  26. #include "vox.h"
  27. #include "wav.h"
  28. #include "mem.h"
  29. #include "mmio.h"
  30. #include "sys.h"
  31. #include "trace.h"
  32. ////
  33. // private definitions
  34. ////
  35. // step size type
  36. //
  37. typedef __int16 ss_type;
  38. // vox engine control structure
  39. //
  40. typedef struct VOX
  41. {
  42. DWORD dwVersion;
  43. HINSTANCE hInst;
  44. HTASK hTask;
  45. DWORD dwFlags;
  46. ss_type ssDecoder; // decoder step size
  47. ss_type ssEncoder; // encoder step size
  48. PCM16 iVoxDecode; // previous decoded sample
  49. } VOX, FAR *LPVOX;
  50. // macros to convert vox 12 bit samples to/from other size samples
  51. //
  52. #define _Vox12To16(intx) ((PCM16) ((PCM16) (intx) << 4))
  53. #define _Vox12To8(intx) ((BYTE) (((PCM16) (intx) >> 4) + 128))
  54. #define _Vox8To12(bytex) (((PCM16) (bytex) - 128) << 4)
  55. #define _Vox16To12(intx) ((PCM16) (intx) >> 4)
  56. // helper functions
  57. //
  58. static LPVOX VoxGetPtr(HVOX hVox);
  59. static HVOX VoxGetHandle(LPVOX lpVox);
  60. static void ReverseIndexTableInit(void);
  61. static PCM16 DecodeSample(BYTE bVoxEncode, ss_type FAR *lpss, PCM16 iVoxDecodePrev);
  62. static BYTE EncodeSample(__int16 iDelta, ss_type FAR *lpss);
  63. static LRESULT VoxIOOpen(LPMMIOINFO lpmmioinfo, LPTSTR lpszFileName);
  64. static LRESULT VoxIOClose(LPMMIOINFO lpmmioinfo, UINT uFlags);
  65. static LRESULT VoxIORead(LPMMIOINFO lpmmioinfo, HPSTR pch, LONG cch);
  66. static LRESULT VoxIOWrite(LPMMIOINFO lpmmioinfo, const HPSTR pch, LONG cch, BOOL fFlush);
  67. static LRESULT VoxIOSeek(LPMMIOINFO lpmmioinfo, LONG lOffset, int iOrigin);
  68. static LRESULT VoxIORename(LPMMIOINFO lpmmioinfo, LPCTSTR lpszFileName, LPCTSTR lpszNewFileName);
  69. static LRESULT VoxIOGetInfo(LPMMIOINFO lpmmioinfo, int iInfo);
  70. static LRESULT VoxIOChSize(LPMMIOINFO lpmmioinfo, long lSize);
  71. ////
  72. // public functions
  73. ////
  74. // VoxInit - initialize vox engine
  75. // <dwVersion> (i) must be VOX_VERSION
  76. // <hInst> (i) instance handle of calling module
  77. // <dwFlags> (i) reserved; must be 0
  78. // return handle (NULL if error)
  79. //
  80. HVOX DLLEXPORT WINAPI VoxInit(DWORD dwVersion, HINSTANCE hInst, DWORD dwFlags)
  81. {
  82. BOOL fSuccess = TRUE;
  83. LPVOX lpVox = NULL;
  84. if (dwVersion != VOX_VERSION)
  85. fSuccess = TraceFALSE(NULL);
  86. else if (hInst == NULL)
  87. fSuccess = TraceFALSE(NULL);
  88. else if ((lpVox = (LPVOX) MemAlloc(NULL, sizeof(VOX), 0)) == NULL)
  89. fSuccess = TraceFALSE(NULL);
  90. else
  91. {
  92. // initialize engine structure
  93. //
  94. lpVox->dwVersion = dwVersion;
  95. lpVox->hInst = hInst;
  96. lpVox->hTask = GetCurrentTask();
  97. lpVox->dwFlags = dwFlags;
  98. ReverseIndexTableInit();
  99. if (VoxReset(VoxGetHandle(lpVox)) != 0)
  100. fSuccess = TraceFALSE(NULL);
  101. }
  102. if (!fSuccess)
  103. {
  104. VoxTerm(VoxGetHandle(lpVox));
  105. lpVox = NULL;
  106. }
  107. return fSuccess ? VoxGetHandle(lpVox) : NULL;
  108. }
  109. // VoxTerm - shut down vox engine
  110. // <hVox> (i) handle returned from VoxInit
  111. // return 0 if success
  112. //
  113. int DLLEXPORT WINAPI VoxTerm(HVOX hVox)
  114. {
  115. BOOL fSuccess = TRUE;
  116. LPVOX lpVox;
  117. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  118. fSuccess = TraceFALSE(NULL);
  119. else if ((lpVox = MemFree(NULL, lpVox)) != NULL)
  120. fSuccess = TraceFALSE(NULL);
  121. return fSuccess ? 0 : -1;
  122. }
  123. // VoxReset - reset vox engine
  124. // <hVox> (i) handle returned from VoxInit
  125. // return 0 if success
  126. //
  127. int DLLEXPORT WINAPI VoxReset(HVOX hVox)
  128. {
  129. BOOL fSuccess = TRUE;
  130. LPVOX lpVox;
  131. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  132. fSuccess = TraceFALSE(NULL);
  133. else
  134. {
  135. lpVox->ssDecoder = 16;
  136. lpVox->ssEncoder = 16;
  137. lpVox->iVoxDecode = 0;
  138. }
  139. return fSuccess ? 0 : -1;
  140. }
  141. // VoxDecode_16BitMono - decode vox samples
  142. // <hVox> (i) handle returned from VoxInit
  143. // <lpabVox> (i) array of encoded samples
  144. // <lpaiPcm> (o) array of decoded samples
  145. // <uSamples> (i) number of samples to decode
  146. // return 0 if success
  147. //
  148. // NOTE: each BYTE in <lpabVox> contains 2 12-bit encoded samples
  149. // in OKI ADPCM Vox format, as described by Dialogic
  150. // Each PCM16 in <lpaiPcm> contains 1 16-bit decoded sample
  151. // in standard PCM format.
  152. //
  153. int DLLEXPORT WINAPI VoxDecode_16BitMono(HVOX hVox, LPBYTE lpabVox, LPPCM16 lpaiPcm, UINT uSamples)
  154. {
  155. BOOL fSuccess = TRUE;
  156. LPVOX lpVox;
  157. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  158. fSuccess = TraceFALSE(NULL);
  159. else if (lpaiPcm == NULL || lpabVox == NULL)
  160. fSuccess = TraceFALSE(NULL);
  161. // since there are two samples per Vox data byte,
  162. // we will decode two samples each time through the loop
  163. //
  164. else while (uSamples > 1)
  165. {
  166. BYTE bData;
  167. bData = *lpabVox++;
  168. lpVox->iVoxDecode = DecodeSample((BYTE)
  169. (0xFF & ((BYTE) (bData >> 4) & (BYTE) 0x0F)),
  170. &lpVox->ssDecoder, lpVox->iVoxDecode);
  171. *lpaiPcm++ = _Vox12To16(lpVox->iVoxDecode);
  172. lpVox->iVoxDecode = DecodeSample((BYTE)
  173. (0xFF & (bData & (BYTE) 0x0F)),
  174. &lpVox->ssDecoder, lpVox->iVoxDecode);
  175. *lpaiPcm++ = _Vox12To16(lpVox->iVoxDecode);
  176. uSamples -= 2;
  177. }
  178. return fSuccess ? 0 : -1;
  179. }
  180. // VoxEncode_16BitMono - encode vox samples
  181. // <hVox> (i) handle returned from VoxInit
  182. // <lpaiPcm> (i) array of decoded samples
  183. // <lpabVox> (o) array of encoded samples
  184. // <uSamples> (i) number of samples to encode
  185. // return 0 if success
  186. //
  187. // NOTE: each BYTE in <lpabVox> contains 2 12-bit encoded samples
  188. // in OKI ADPCM Vox format, as described by Dialogic
  189. // Each PCM16 in <lpaiPcm> contains 1 16-bit decoded sample
  190. // in standard PCM format.
  191. //
  192. int DLLEXPORT WINAPI VoxEncode_16BitMono(HVOX hVox, LPPCM16 lpaiPcm, LPBYTE lpabVox, UINT uSamples)
  193. {
  194. BOOL fSuccess = TRUE;
  195. LPVOX lpVox;
  196. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  197. fSuccess = TraceFALSE(NULL);
  198. else if (lpaiPcm == NULL || lpabVox == NULL)
  199. fSuccess = TraceFALSE(NULL);
  200. // since there are two samples per Vox data byte,
  201. // we will encode two samples each time through the loop
  202. //
  203. else while (uSamples > 1)
  204. {
  205. __int16 iDelta;
  206. PCM16 iVoxDecode;
  207. BYTE bVoxEncode1;
  208. BYTE bVoxEncode2;
  209. iVoxDecode = _Vox16To12(*lpaiPcm++);
  210. iDelta = iVoxDecode - lpVox->iVoxDecode;
  211. bVoxEncode1 = EncodeSample(iDelta, &lpVox->ssEncoder);
  212. lpVox->iVoxDecode = DecodeSample(bVoxEncode1, &lpVox->ssDecoder, lpVox->iVoxDecode);
  213. iVoxDecode = _Vox16To12(*lpaiPcm++);
  214. iDelta = iVoxDecode - lpVox->iVoxDecode;
  215. bVoxEncode2 = EncodeSample(iDelta, &lpVox->ssEncoder);
  216. lpVox->iVoxDecode = DecodeSample(bVoxEncode2, &lpVox->ssDecoder, lpVox->iVoxDecode);
  217. *lpabVox++ = (BYTE) (((BYTE) (bVoxEncode1 << 4) & (BYTE) 0xF0) | bVoxEncode2);
  218. uSamples -= 2;
  219. }
  220. return fSuccess ? 0 : -1;
  221. }
  222. // VoxDecode_8BitMono - decode vox samples
  223. // <hVox> (i) handle returned from VoxInit
  224. // <lpabVox> (i) array of encoded samples
  225. // <lpabPcm> (o) array of decoded samples
  226. // <uSamples> (i) number of samples to decode
  227. // return 0 if success
  228. //
  229. // NOTE: each BYTE in <lpabVox> contains 2 12-bit encoded samples
  230. // in OKI ADPCM Vox format, as described by Dialogic
  231. // Each PCM8 in <lpabPcm> contains 1 8-bit decoded sample
  232. // in standard PCM format.
  233. //
  234. int DLLEXPORT WINAPI VoxDecode_8BitMono(HVOX hVox, LPBYTE lpabVox, LPPCM8 lpabPcm, UINT uSamples)
  235. {
  236. BOOL fSuccess = TRUE;
  237. LPVOX lpVox;
  238. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  239. fSuccess = TraceFALSE(NULL);
  240. else if (lpabPcm == NULL || lpabVox == NULL)
  241. fSuccess = TraceFALSE(NULL);
  242. // since there are two samples per Vox data byte,
  243. // we will decode two samples each time through the loop
  244. //
  245. else while (uSamples > 1)
  246. {
  247. BYTE bData;
  248. bData = *lpabVox++;
  249. lpVox->iVoxDecode = DecodeSample((BYTE)
  250. (0xFF & ((BYTE) (bData >> 4) & (BYTE) 0x0F)),
  251. &lpVox->ssDecoder, lpVox->iVoxDecode);
  252. *lpabPcm++ = _Vox12To8(lpVox->iVoxDecode);
  253. lpVox->iVoxDecode = DecodeSample((BYTE)
  254. (0xFF & (bData & (BYTE) 0x0F)),
  255. &lpVox->ssDecoder, lpVox->iVoxDecode);
  256. *lpabPcm++ = _Vox12To8(lpVox->iVoxDecode);
  257. uSamples -= 2;
  258. }
  259. return fSuccess ? 0 : -1;
  260. }
  261. // VoxEncode_8BitMono - encode vox samples
  262. // <hVox> (i) handle returned from VoxInit
  263. // <lpabPcm> (i) array of decoded samples
  264. // <lpabVox> (o) array of encoded samples
  265. // <uSamples> (i) number of samples to encode
  266. // return 0 if success
  267. //
  268. // NOTE: each BYTE in <lpabVox> contains 2 12-bit encoded samples
  269. // in OKI ADPCM Vox format, as described by Dialogic
  270. // Each PCM8 in <lpabPcm> contains 1 8-bit decoded sample
  271. // in standard PCM format.
  272. //
  273. int DLLEXPORT WINAPI VoxEncode_8BitMono(HVOX hVox, LPPCM8 lpabPcm, LPBYTE lpabVox, UINT uSamples)
  274. {
  275. BOOL fSuccess = TRUE;
  276. LPVOX lpVox;
  277. if ((lpVox = VoxGetPtr(hVox)) == NULL)
  278. fSuccess = TraceFALSE(NULL);
  279. else if (lpabPcm == NULL || lpabVox == NULL)
  280. fSuccess = TraceFALSE(NULL);
  281. // since there are two samples per Vox data byte,
  282. // we will encode two samples each time through the loop
  283. //
  284. else while (uSamples > 1)
  285. {
  286. __int16 iDelta;
  287. PCM16 iVoxDecode;
  288. BYTE bVoxEncode1;
  289. BYTE bVoxEncode2;
  290. iVoxDecode = _Vox8To12(*lpabPcm++);
  291. iDelta = iVoxDecode - lpVox->iVoxDecode;
  292. bVoxEncode1 = EncodeSample(iDelta, &lpVox->ssEncoder);
  293. lpVox->iVoxDecode = DecodeSample(bVoxEncode1, &lpVox->ssDecoder, lpVox->iVoxDecode);
  294. iVoxDecode = _Vox8To12(*lpabPcm++);
  295. iDelta = iVoxDecode - lpVox->iVoxDecode;
  296. bVoxEncode2 = EncodeSample(iDelta, &lpVox->ssEncoder);
  297. lpVox->iVoxDecode = DecodeSample(bVoxEncode2, &lpVox->ssDecoder, lpVox->iVoxDecode);
  298. *lpabVox++ = (BYTE) (((BYTE) (bVoxEncode1 << 4) & (BYTE) 0xF0) | bVoxEncode2);
  299. uSamples -= 2;
  300. }
  301. return fSuccess ? 0 : -1;
  302. }
  303. // VoxIOProc - i/o procedure for vox format file data
  304. // <lpmmioinfo> (i/o) information about open file
  305. // <uMessage> (i) message indicating the requested I/O operation
  306. // <lParam1> (i) message specific parameter
  307. // <lParam2> (i) message specific parameter
  308. // returns 0 if message not recognized, otherwise message specific value
  309. //
  310. // NOTE: the address of this function should be passed to the WavOpen()
  311. // or mmioInstallIOProc() functions for accessing vox format file data.
  312. //
  313. LRESULT DLLEXPORT CALLBACK VoxIOProc(LPTSTR lpmmioinfo,
  314. UINT uMessage, LPARAM lParam1, LPARAM lParam2)
  315. {
  316. BOOL fSuccess = TRUE;
  317. LRESULT lResult = 0;
  318. if (lpmmioinfo == NULL)
  319. fSuccess = TraceFALSE(NULL);
  320. else switch (uMessage)
  321. {
  322. case MMIOM_OPEN:
  323. lResult = VoxIOOpen((LPMMIOINFO) lpmmioinfo,
  324. (LPTSTR) lParam1);
  325. break;
  326. case MMIOM_CLOSE:
  327. lResult = VoxIOClose((LPMMIOINFO) lpmmioinfo,
  328. (UINT) lParam1);
  329. break;
  330. case MMIOM_READ:
  331. lResult = VoxIORead((LPMMIOINFO) lpmmioinfo,
  332. (HPSTR) lParam1, (LONG) lParam2);
  333. break;
  334. case MMIOM_WRITE:
  335. lResult = VoxIOWrite((LPMMIOINFO) lpmmioinfo,
  336. (const HPSTR) lParam1, (LONG) lParam2, FALSE);
  337. break;
  338. case MMIOM_WRITEFLUSH:
  339. lResult = VoxIOWrite((LPMMIOINFO) lpmmioinfo,
  340. (const HPSTR) lParam1, (LONG) lParam2, TRUE);
  341. break;
  342. case MMIOM_SEEK:
  343. lResult = VoxIOSeek((LPMMIOINFO) lpmmioinfo,
  344. (LONG) lParam1, (int) lParam2);
  345. break;
  346. case MMIOM_RENAME:
  347. lResult = VoxIORename((LPMMIOINFO) lpmmioinfo,
  348. (LPCTSTR) lParam1, (LPCTSTR) lParam2);
  349. break;
  350. case MMIOM_GETINFO:
  351. lResult = VoxIOGetInfo((LPMMIOINFO) lpmmioinfo,
  352. (int) lParam1);
  353. break;
  354. case MMIOM_CHSIZE:
  355. lResult = VoxIOChSize((LPMMIOINFO) lpmmioinfo,
  356. (long) lParam1);
  357. break;
  358. default:
  359. lResult = 0;
  360. break;
  361. }
  362. return lResult;
  363. }
  364. ////
  365. // private functions
  366. ////
  367. // VoxGetPtr - verify that vox handle is valid,
  368. // <hVox> (i) handle returned from VoxInit
  369. // return corresponding vox pointer (NULL if error)
  370. //
  371. static LPVOX VoxGetPtr(HVOX hVox)
  372. {
  373. BOOL fSuccess = TRUE;
  374. LPVOX lpVox;
  375. if ((lpVox = (LPVOX) hVox) == NULL)
  376. fSuccess = TraceFALSE(NULL);
  377. else if (IsBadWritePtr(lpVox, sizeof(VOX)))
  378. fSuccess = TraceFALSE(NULL);
  379. #ifdef CHECKTASK
  380. // make sure current task owns the vox engine handle
  381. //
  382. else if (lpVox->hTask != GetCurrentTask())
  383. fSuccess = TraceFALSE(NULL);
  384. #endif
  385. return fSuccess ? lpVox : NULL;
  386. }
  387. // VoxGetHandle - verify that vox pointer is valid,
  388. // <lpVox> (i) pointer to VOX structure
  389. // return corresponding vox handle (NULL if error)
  390. //
  391. static HVOX VoxGetHandle(LPVOX lpVox)
  392. {
  393. BOOL fSuccess = TRUE;
  394. HVOX hVox;
  395. if ((hVox = (HVOX) lpVox) == NULL)
  396. fSuccess = TraceFALSE(NULL);
  397. return fSuccess ? hVox : NULL;
  398. }
  399. ////
  400. // low-level ADPCM stuff
  401. ////
  402. static ss_type const ss_table[] =
  403. {
  404. 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
  405. 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
  406. 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
  407. 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
  408. 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
  409. };
  410. static __int16 delta_index_table[] =
  411. {
  412. -1, -1, -1, -1, +2, +4, +6, +8, -1, -1, -1, -1, +2, +4, +6, +8
  413. };
  414. ////
  415. // The reverse index table is designed so that given a step size, we
  416. // can get back out the index that generated it.
  417. ////
  418. static BYTE reverse_index_table[1553];
  419. // initialize reverse index table
  420. //
  421. static void ReverseIndexTableInit(void)
  422. {
  423. __int16 i;
  424. for (i = 0; i < 49; ++i)
  425. reverse_index_table[ss_table[i]] = (BYTE) i;
  426. }
  427. #if 0
  428. static ss_type new_ss(ss_type ss, BYTE bVoxEncode);
  429. static ss_type new_ss(ss_type ss, BYTE bVoxEncode)
  430. {
  431. __int16 index;
  432. // find out what our old index into the step size table was
  433. //
  434. index = reverse_index_table[ss];
  435. // modify our index based on the present value of the ADPCM nibble
  436. //
  437. index += delta_index_table[bVoxEncode];
  438. // limit ourselves to the maximum size of the table in case of overflow
  439. //
  440. index = max(0, min(48, index));
  441. // and return our new step size out of the table
  442. //
  443. return ss_table[index];
  444. }
  445. #else
  446. #define new_ss(ss, bVoxEncode) ss_table[max(0, min(48, \
  447. reverse_index_table[ss] + delta_index_table[bVoxEncode]))]
  448. #endif
  449. // DECODE - ADPCM to linear
  450. //
  451. static PCM16 DecodeSample(BYTE bVoxEncode, ss_type FAR *lpss, PCM16 iVoxDecodePrev)
  452. {
  453. __int16 iDelta;
  454. PCM16 iVoxDecode;
  455. ss_type ss;
  456. ss = *lpss;
  457. // iDelta = (((nibble * 2) + 1) / 8 ) * ss;
  458. //
  459. iDelta = ((((bVoxEncode & 0x07) << 1) + 1) * ss ) >> 3;
  460. if ((bVoxEncode & 0x08) == 0x08)
  461. iDelta = -iDelta;
  462. *lpss = new_ss(ss, bVoxEncode);
  463. iVoxDecode = iVoxDecodePrev + iDelta;
  464. // limit ourselves to 12 bits of resolution
  465. //
  466. if (iVoxDecode > 2047)
  467. return 2047;
  468. else if (iVoxDecode < -2048)
  469. return -2048;
  470. else
  471. return iVoxDecode;
  472. }
  473. // ENCODE - linear to ADPCM
  474. //
  475. static BYTE EncodeSample(__int16 iDelta, ss_type FAR *lpss)
  476. {
  477. BYTE bVoxEncode;
  478. ss_type ss;
  479. __int16 iDeltaTmp;
  480. ss = *lpss;
  481. iDeltaTmp = iDelta;
  482. if (iDeltaTmp < 0)
  483. {
  484. iDeltaTmp = -iDeltaTmp;
  485. bVoxEncode = 0x08;
  486. }
  487. else
  488. bVoxEncode = 0;
  489. if (iDeltaTmp >= ss)
  490. {
  491. bVoxEncode |= 0x04;
  492. iDeltaTmp -= ss;
  493. }
  494. if (iDeltaTmp >= (ss >> 1))
  495. {
  496. bVoxEncode |= 0x02;
  497. iDeltaTmp -= (ss >> 1);
  498. }
  499. if (iDeltaTmp >= (ss >> 2))
  500. {
  501. bVoxEncode |= 0x01;
  502. }
  503. *lpss = new_ss(ss, bVoxEncode);
  504. return (BYTE) (bVoxEncode & (BYTE) 0x0F);
  505. // format of return nibble is
  506. // S W F F
  507. // | | | |
  508. // | | | +--- 1/4 of delta/step
  509. // | | +----- 1/2 of delta/step
  510. // | +------- whole part of delta/step
  511. // +--------- sign bit
  512. }
  513. ////
  514. // installable file i/o procedures
  515. ////
  516. static LRESULT VoxIOOpen(LPMMIOINFO lpmmioinfo, LPTSTR lpszFileName)
  517. {
  518. BOOL fSuccess = TRUE;
  519. HMMIO hmmio = NULL;
  520. MMIOINFO mmioinfo;
  521. HVOX hVox = NULL;
  522. HINSTANCE hInst;
  523. TracePrintf_1(NULL, 5,
  524. TEXT("VoxIOOpen (%s)\n"),
  525. (LPTSTR) lpszFileName);
  526. MemSet(&mmioinfo, 0, sizeof(mmioinfo));
  527. // interpret first value passed as pointer to next i/o procedure in chain
  528. //
  529. mmioinfo.pIOProc = (LPMMIOPROC) lpmmioinfo->adwInfo[0];
  530. // pass along second and third values to next i/o procedure
  531. //
  532. mmioinfo.adwInfo[0] = lpmmioinfo->adwInfo[1];
  533. mmioinfo.adwInfo[1] = lpmmioinfo->adwInfo[2];
  534. mmioinfo.adwInfo[2] = 0L;
  535. // get instance handle of current task
  536. //
  537. if ((hInst = SysGetTaskInstance(NULL)) == NULL)
  538. fSuccess = TraceFALSE(NULL);
  539. else if ((hVox = VoxInit(VOX_VERSION, hInst, 0)) == NULL)
  540. fSuccess = TraceFALSE(NULL);
  541. else if ((hmmio = mmioOpen(lpszFileName, &mmioinfo, lpmmioinfo->dwFlags)) == NULL)
  542. fSuccess = TraceFALSE(NULL);
  543. else
  544. {
  545. // save stuff for use in other i/o routines
  546. //
  547. lpmmioinfo->adwInfo[0] = (DWORD) (LPVOID) hmmio;
  548. lpmmioinfo->adwInfo[1] = (DWORD) (LPVOID) hVox;
  549. }
  550. // clean up after error
  551. //
  552. if (!fSuccess && hVox != NULL && VoxTerm(hVox) != 0)
  553. fSuccess = TraceFALSE(NULL);
  554. if (!fSuccess && hmmio != NULL && mmioClose(hmmio, 0) != 0)
  555. fSuccess = TraceFALSE(NULL);
  556. // return the same error code given by mmioOpen
  557. //
  558. return fSuccess ? lpmmioinfo->wErrorRet = mmioinfo.wErrorRet : MMIOERR_CANNOTOPEN;
  559. }
  560. static LRESULT VoxIOClose(LPMMIOINFO lpmmioinfo, UINT uFlags)
  561. {
  562. BOOL fSuccess = TRUE;
  563. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  564. HVOX hVox = (HVOX) lpmmioinfo->adwInfo[1];
  565. UINT uRet = MMIOERR_CANNOTCLOSE;
  566. TracePrintf_0(NULL, 5,
  567. TEXT("VoxIOClose\n"));
  568. if (VoxTerm(hVox) != 0)
  569. fSuccess = TraceFALSE(NULL);
  570. else if ((uRet = mmioClose(hmmio, uFlags)) != 0)
  571. fSuccess = TraceFALSE(NULL);
  572. else
  573. {
  574. lpmmioinfo->adwInfo[0] = (DWORD) NULL;
  575. lpmmioinfo->adwInfo[1] = (DWORD) NULL;
  576. }
  577. return fSuccess ? 0 : uRet;
  578. }
  579. static LRESULT VoxIORead(LPMMIOINFO lpmmioinfo, HPSTR pch, LONG cch)
  580. {
  581. BOOL fSuccess = TRUE;
  582. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  583. HVOX hVox = (HVOX) lpmmioinfo->adwInfo[1];
  584. LONG cchVox;
  585. LONG lBytesRead;
  586. HPSTR pchVox = NULL;
  587. TracePrintf_1(NULL, 5,
  588. TEXT("VoxIORead (%ld)\n"),
  589. (long) cch);
  590. // vox format files contain 4 bit samples,
  591. // but we must simulate access to 16 bit samples.
  592. //
  593. cchVox = cch / 4L;
  594. if (cchVox <= 0)
  595. lBytesRead = 0; // nothing to do
  596. // allocate temporary buffer to hold the vox format samples
  597. //
  598. if ((pchVox = (HPSTR) MemAlloc(NULL, cchVox, 0)) == NULL)
  599. fSuccess = TraceFALSE(NULL);
  600. // read vox format samples
  601. //
  602. else if ((lBytesRead = mmioRead(hmmio, pchVox, cchVox)) == -1)
  603. fSuccess = TraceFALSE(NULL);
  604. // decode vox format samples into pcm format samples
  605. // (there are 2 samples encoded in each vox byte)
  606. //
  607. else if (VoxDecode_16BitMono(hVox, (LPBYTE) pchVox, (LPPCM16) pch, (UINT) (lBytesRead * 2L)) != 0)
  608. fSuccess = TraceFALSE(NULL);
  609. // update simulated file position
  610. //
  611. if (fSuccess)
  612. lpmmioinfo->lDiskOffset += lBytesRead * 4L;
  613. TracePrintf_2(NULL, 5,
  614. TEXT("VoxIO: lpmmioinfo->lDiskOffset=%ld, lBytesRead=%ld\n"),
  615. (long) lpmmioinfo->lDiskOffset,
  616. (long) lBytesRead);
  617. // clean up
  618. //
  619. if (pchVox != NULL &&
  620. (pchVox = MemFree(NULL, pchVox)) != NULL)
  621. fSuccess = TraceFALSE(NULL);
  622. // return number of bytes read/decoded into pch
  623. //
  624. return fSuccess ? lBytesRead * 4L : -1;
  625. }
  626. static LRESULT VoxIOWrite(LPMMIOINFO lpmmioinfo, const HPSTR pch, LONG cch, BOOL fFlush)
  627. {
  628. BOOL fSuccess = TRUE;
  629. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  630. HVOX hVox = (HVOX) lpmmioinfo->adwInfo[1];
  631. HPSTR pchVox = NULL;
  632. LONG cchVox;
  633. LONG lBytesWritten;
  634. TracePrintf_1(NULL, 5,
  635. TEXT("VoxIOWrite (%ld)\n"),
  636. (long) cch);
  637. // vox format files contain 4 bit samples,
  638. // but we must simulate access to 16 bit samples.
  639. //
  640. cchVox = cch / 4L;
  641. if (cchVox <= 0)
  642. lBytesWritten = 0; // nothing to do
  643. // allocate temporary buffer to hold the vox format samples
  644. //
  645. else if ((pchVox = (HPSTR) MemAlloc(NULL, cchVox, 0)) == NULL)
  646. fSuccess = TraceFALSE(NULL);
  647. // encode pcm format samples into vox format samples
  648. // (there are 2 bytes required for each pcm sample)
  649. //
  650. else if (VoxEncode_16BitMono(hVox, (LPPCM16) pch, (LPBYTE) pchVox, (UINT) (cch / 2L)) != 0)
  651. fSuccess = TraceFALSE(NULL);
  652. // write vox format samples
  653. //
  654. else if ((lBytesWritten = mmioWrite(hmmio, pchVox, cchVox)) == -1)
  655. fSuccess = TraceFALSE(NULL);
  656. // update simulated file position
  657. //
  658. else
  659. lpmmioinfo->lDiskOffset += lBytesWritten * 4L;
  660. // clean up
  661. //
  662. if (pchVox != NULL &&
  663. (pchVox = MemFree(NULL, pchVox)) != NULL)
  664. fSuccess = TraceFALSE(NULL);
  665. TracePrintf_2(NULL, 5,
  666. TEXT("VoxIO: lpmmioinfo->lDiskOffset=%ld, lBytesWritten=%ld\n"),
  667. (long) lpmmioinfo->lDiskOffset,
  668. (long) lBytesWritten);
  669. // return number of bytes encoded/written from pch
  670. //
  671. return fSuccess ? lBytesWritten * 4L : -1;
  672. }
  673. static LRESULT VoxIOSeek(LPMMIOINFO lpmmioinfo, LONG lOffset, int iOrigin)
  674. {
  675. BOOL fSuccess = TRUE;
  676. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  677. LONG lPosNew;
  678. TracePrintf_2(NULL, 5,
  679. TEXT("VoxIOSeek (%ld, %d)\n"),
  680. (long) lOffset,
  681. (int) iOrigin);
  682. // vox format files contain 4 bit samples,
  683. // but we must simulate access to 16 bit samples.
  684. //
  685. if ((lPosNew = mmioSeek(hmmio, lOffset / 4L, iOrigin)) == -1)
  686. fSuccess = TraceFALSE(NULL);
  687. // update simulated file position
  688. //
  689. else
  690. lpmmioinfo->lDiskOffset = lPosNew * 4L;
  691. TracePrintf_1(NULL, 5,
  692. TEXT("VoxIO: lpmmioinfo->lDiskOffset=%ld\n"),
  693. (long) lpmmioinfo->lDiskOffset);
  694. return fSuccess ? lpmmioinfo->lDiskOffset : -1;
  695. }
  696. static LRESULT VoxIORename(LPMMIOINFO lpmmioinfo, LPCTSTR lpszFileName, LPCTSTR lpszNewFileName)
  697. {
  698. BOOL fSuccess = TRUE;
  699. UINT uRet = MMIOERR_FILENOTFOUND;
  700. TracePrintf_2(NULL, 5,
  701. TEXT("VoxIORename (%s, %s)\n"),
  702. (LPTSTR) lpszFileName,
  703. (LPTSTR) lpszNewFileName);
  704. if ((uRet = mmioRename(lpszFileName, lpszNewFileName, lpmmioinfo, 0)) != 0)
  705. fSuccess = TraceFALSE(NULL);
  706. return fSuccess ? 0 : uRet;
  707. }
  708. static LRESULT VoxIOGetInfo(LPMMIOINFO lpmmioinfo, int iInfo)
  709. {
  710. BOOL fSuccess = TRUE;
  711. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  712. LRESULT lResult;
  713. TracePrintf_1(NULL, 5,
  714. TEXT("VoxIOGetInfo (%d)\n"),
  715. (int) iInfo);
  716. lResult = mmioSendMessage(hmmio, MMIOM_GETINFO, iInfo, 0);
  717. #if 1
  718. if (iInfo == 1)
  719. {
  720. // vox format files contain 4 bit samples,
  721. // but we must simulate access to 16 bit samples.
  722. //
  723. lResult *= 4;
  724. }
  725. #endif
  726. return fSuccess ? lResult : 0;
  727. }
  728. static LRESULT VoxIOChSize(LPMMIOINFO lpmmioinfo, long lSize)
  729. {
  730. BOOL fSuccess = TRUE;
  731. HMMIO hmmio = (HMMIO) lpmmioinfo->adwInfo[0];
  732. LRESULT lResult;
  733. TracePrintf_1(NULL, 5,
  734. TEXT("VoxIOChSize (%ld)\n"),
  735. (long) lSize);
  736. lResult = mmioSendMessage(hmmio, MMIOM_CHSIZE, lSize, 0);
  737. return fSuccess ? lResult : -1;
  738. }