Source code of Windows XP (NT5)
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.

347 lines
8.8 KiB

  1. // File: waveio.cpp
  2. #include "precomp.h"
  3. #include "waveio.h"
  4. //==========================================================================;
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  7. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  8. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  9. // PURPOSE.
  10. //
  11. // Copyright (C) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  12. //
  13. //--------------------------------------------------------------------------;
  14. //
  15. // waveio.c
  16. //
  17. // Description:
  18. // Contains routines for opening and closing RIFF WAVE files.
  19. //
  20. //
  21. //==========================================================================;
  22. //--------------------------------------------------------------------------;
  23. //
  24. // WIOERR wioFileClose
  25. //
  26. // Description:
  27. //
  28. //
  29. // Arguments:
  30. // LPWAVEIOCB pwio:
  31. //
  32. // DWORD fdwClose:
  33. //
  34. // Return (WIOERR):
  35. //
  36. //--------------------------------------------------------------------------;
  37. WIOERR WIOAPI wioFileClose
  38. (
  39. LPWAVEIOCB pwio,
  40. DWORD fdwClose
  41. )
  42. {
  43. //
  44. // validate a couple of things...
  45. //
  46. if (NULL == pwio)
  47. return (WIOERR_BADPARAM);
  48. //
  49. // get rid of stuff...
  50. //
  51. // wioStopWave(pwio);
  52. if (NULL != pwio->hmmio)
  53. {
  54. mmioClose(pwio->hmmio, 0);
  55. }
  56. // FreeWaveHeaders(lpwio);
  57. #if 0
  58. if (pwio->pInfo)
  59. riffFreeINFO(&(lpwio->pInfo));
  60. if (pwio->pDisp)
  61. riffFreeDISP(&(lpwio->pDisp));
  62. #endif
  63. if (NULL != pwio->pwfx)
  64. GlobalFreePtr(pwio->pwfx);
  65. _fmemset(pwio, 0, sizeof(*pwio));
  66. return (WIOERR_NOERROR);
  67. } // wioFileClose()
  68. //--------------------------------------------------------------------------;
  69. //
  70. // WIOERR wioFileOpen
  71. //
  72. // Description:
  73. //
  74. //
  75. // Arguments:
  76. // LPWAVEIOCB pwio:
  77. //
  78. // LPCTSTR pszFilePath:
  79. //
  80. // DWORD fdwOpen:
  81. //
  82. // Return (WIOERR):
  83. //
  84. //
  85. //--------------------------------------------------------------------------;
  86. WIOERR WIOAPI wioFileOpen
  87. (
  88. LPWAVEIOCB pwio,
  89. LPCTSTR pszFilePath,
  90. DWORD fdwOpen
  91. )
  92. {
  93. WIOERR werr;
  94. HMMIO hmmio;
  95. MMCKINFO ckRIFF;
  96. MMCKINFO ck;
  97. DWORD dw;
  98. //
  99. // validate a couple of things...
  100. //
  101. if (NULL == pwio)
  102. return (WIOERR_BADPARAM);
  103. //
  104. // default our error return (assume the worst)
  105. //
  106. _fmemset(pwio, 0, sizeof(*pwio));
  107. werr = WIOERR_FILEERROR;
  108. pwio->dwFlags = fdwOpen;
  109. //
  110. // first try to open the file, etc.. open the given file for reading
  111. // using buffered I/O
  112. //
  113. hmmio = mmioOpen((LPTSTR)pszFilePath, NULL, MMIO_READ | MMIO_ALLOCBUF);
  114. if (NULL == hmmio)
  115. goto wio_Open_Error;
  116. pwio->hmmio = hmmio;
  117. //
  118. // locate a 'WAVE' form type...
  119. //
  120. ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  121. if (mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF))
  122. goto wio_Open_Error;
  123. //
  124. // we found a WAVE chunk--now go through and get all subchunks that
  125. // we know how to deal with...
  126. //
  127. pwio->dwDataSamples = (DWORD)-1L;
  128. #if 0
  129. if (lrt=riffInitINFO(&wio.pInfo))
  130. {
  131. lr=lrt;
  132. goto wio_Open_Error;
  133. }
  134. #endif
  135. //
  136. //
  137. //
  138. while (MMSYSERR_NOERROR == mmioDescend(hmmio, &ck, &ckRIFF, 0))
  139. {
  140. //
  141. // quickly check for corrupt RIFF file--don't ascend past end!
  142. //
  143. if ((ck.dwDataOffset + ck.cksize) > (ckRIFF.dwDataOffset + ckRIFF.cksize))
  144. {
  145. // TCHAR ach[255];
  146. // wsprintf(ach, TEXT("This wave file might be corrupt. The RIFF chunk.ckid '%.08lX' (data offset at %lu) specifies a cksize of %lu that extends beyond what the RIFF header cksize of %lu allows. Attempt to load?"),
  147. // ck.ckid, ck.dwDataOffset, ck.cksize, ckRIFF.cksize);
  148. // u = MessageBox(NULL, ach, TEXT("wioFileOpen"),
  149. // MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
  150. // if (IDNO == u)
  151. // {
  152. werr = WIOERR_BADFILE;
  153. goto wio_Open_Error;
  154. // }
  155. }
  156. switch (ck.ckid)
  157. {
  158. case mmioFOURCC('L', 'I', 'S', 'T'):
  159. if (ck.fccType == mmioFOURCC('I', 'N', 'F', 'O'))
  160. {
  161. #if 0
  162. if(lrt=riffReadINFO(hmmio, &ck, wio.pInfo))
  163. {
  164. lr=lrt;
  165. goto wio_Open_Error;
  166. }
  167. #endif
  168. }
  169. break;
  170. case mmioFOURCC('D', 'I', 'S', 'P'):
  171. #if 0
  172. riffReadDISP(hmmio, &ck, &(wio.pDisp));
  173. #endif
  174. break;
  175. case mmioFOURCC('f', 'm', 't', ' '):
  176. //
  177. // !?! another format chunk !?!
  178. //
  179. if (NULL != pwio->pwfx)
  180. break;
  181. //
  182. // get size of the format chunk, allocate and lock memory
  183. // for it. we always alloc a complete extended format header
  184. // (even for PCM headers that do not have the cbSize field
  185. // defined--we just set it to zero).
  186. //
  187. dw = ck.cksize;
  188. if (dw < sizeof(WAVEFORMATEX))
  189. dw = sizeof(WAVEFORMATEX);
  190. pwio->pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, dw);
  191. if (NULL == pwio->pwfx)
  192. {
  193. werr = WIOERR_NOMEM;
  194. goto wio_Open_Error;
  195. }
  196. //
  197. // read the format chunk
  198. //
  199. werr = WIOERR_FILEERROR;
  200. dw = ck.cksize;
  201. if (mmioRead(hmmio, (HPSTR)pwio->pwfx, dw) != (LONG)dw)
  202. goto wio_Open_Error;
  203. break;
  204. case mmioFOURCC('d', 'a', 't', 'a'):
  205. //
  206. // !?! multiple data chunks !?!
  207. //
  208. if (0L != pwio->dwDataBytes)
  209. break;
  210. //
  211. // just hang on to the total length in bytes of this data
  212. // chunk.. and the offset to the start of the data
  213. //
  214. pwio->dwDataBytes = ck.cksize;
  215. pwio->dwDataOffset = ck.dwDataOffset;
  216. break;
  217. case mmioFOURCC('f', 'a', 'c', 't'):
  218. //
  219. // !?! multiple fact chunks !?!
  220. //
  221. if (-1L != pwio->dwDataSamples)
  222. break;
  223. //
  224. // read the first dword in the fact chunk--it's the only
  225. // info we need (and is currently the only info defined for
  226. // the fact chunk...)
  227. //
  228. // if this fails, dwDataSamples will remain -1 so we will
  229. // deal with it later...
  230. //
  231. mmioRead(hmmio, (HPSTR)&pwio->dwDataSamples, sizeof(DWORD));
  232. break;
  233. }
  234. //
  235. // step up to prepare for next chunk..
  236. //
  237. mmioAscend(hmmio, &ck, 0);
  238. }
  239. //
  240. // if no fmt chunk was found, then die!
  241. //
  242. if (NULL == pwio->pwfx)
  243. {
  244. werr = WIOERR_ERROR;
  245. goto wio_Open_Error;
  246. }
  247. //
  248. // all wave files other than PCM are _REQUIRED_ to have a fact chunk
  249. // telling the number of samples that are contained in the file. it
  250. // is optional for PCM (and if not present, we compute it here).
  251. //
  252. // if the file is not PCM and the fact chunk is not found, then fail!
  253. //
  254. if (-1L == pwio->dwDataSamples)
  255. {
  256. if (WAVE_FORMAT_PCM == pwio->pwfx->wFormatTag)
  257. {
  258. pwio->dwDataSamples = pwio->dwDataBytes / pwio->pwfx->nBlockAlign;
  259. }
  260. else
  261. {
  262. //
  263. // !!! HACK HACK HACK !!!
  264. //
  265. // although this should be considered an invalid wave file, we
  266. // will bring up a message box describing the error--hopefully
  267. // people will start realizing that something is missing???
  268. //
  269. // u = MessageBox(NULL, TEXT("This wave file does not have a 'fact' chunk and requires one! This is completely invalid and MUST be fixed! Attempt to load it anyway?"),
  270. // TEXT("wioFileOpen"), MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
  271. // if (IDNO == u)
  272. // {
  273. werr = WIOERR_BADFILE;
  274. goto wio_Open_Error;
  275. // }
  276. //
  277. // !!! need to hack stuff in here !!!
  278. //
  279. pwio->dwDataSamples = 0L;
  280. }
  281. }
  282. //
  283. // cool! no problems..
  284. //
  285. return (WIOERR_NOERROR);
  286. //
  287. // return error (after minor cleanup)
  288. //
  289. wio_Open_Error:
  290. wioFileClose(pwio, 0L);
  291. return (werr);
  292. } // wioFileOpen()