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.

859 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: wave.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #define DIRECTSOUND_VERSION 0x600
  11. #include "stdafx.h"
  12. #include "Direct.h"
  13. #include "dSound.h"
  14. #include "dms.h"
  15. #include <mmreg.h>
  16. #include <msacm.h>
  17. // FOURCC codes
  18. #undef FOURCC_RIFF
  19. #define FOURCC_RIFF 'FFIR'
  20. #undef FOURCC_MEM
  21. #define FOURCC_MEM ' MEM'
  22. #undef FOURCC_WAVE
  23. #define FOURCC_WAVE 'EVAW'
  24. #undef FOURCC_FORMAT
  25. #define FOURCC_FORMAT ' tmf'
  26. #undef FOURCC_DATA
  27. #define FOURCC_DATA 'atad'
  28. #define RPF(level,str,err) \
  29. { char outBuf[MAX_PATH]; \
  30. wsprintf(outBuf,str,err); \
  31. OutputDebugString(outBuf); \
  32. }
  33. #define DPFLVL_ERROR 1
  34. /***************************************************************************
  35. *
  36. * FillWfx
  37. *
  38. * Description:
  39. * Fills a WAVEFORMATEX structure, given only the necessary values.
  40. *
  41. * Arguments:
  42. * LPWAVEFORMATEX [out]: structure to fill.
  43. * WORD [in]: number of channels.
  44. * DWORD [in]: samples per second.
  45. * WORD [in]: bits per sample.
  46. *
  47. * Returns:
  48. * (void)
  49. *
  50. ***************************************************************************/
  51. #undef DPF_FNAME
  52. void FillWfx(LPWAVEFORMATEX pwfx, WORD wChannels, DWORD dwSamplesPerSec, WORD wBitsPerSample)
  53. {
  54. pwfx->wFormatTag = WAVE_FORMAT_PCM;
  55. pwfx->nChannels = min(2, max(1, wChannels));
  56. pwfx->nSamplesPerSec = min(DSBFREQUENCY_MAX, max(DSBFREQUENCY_MIN, dwSamplesPerSec));
  57. if(wBitsPerSample < 12)
  58. {
  59. pwfx->wBitsPerSample = 8;
  60. }
  61. else
  62. {
  63. pwfx->wBitsPerSample = 16;
  64. }
  65. pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
  66. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  67. pwfx->cbSize = 0;
  68. }
  69. #if 0
  70. HRESULT InternalCreateSoundBuffer(LPDSBUFFERDESC pDsbDesc, byte *pbWaveData,DWORD cbWaveData,LPDIRECTSOUND lpDirectSound, LPDIRECTSOUNDBUFFER *lplpDirectSoundBuffer)
  71. {
  72. HRESULT hr = DS_OK;
  73. HACMSTREAM has = NULL;
  74. BOOL fPrep = FALSE;
  75. ACMSTREAMHEADER ash;
  76. DWORD dwBufferBytes;
  77. LPVOID pvWrite;
  78. DWORD cbWrite;
  79. HMMIO hmm = NULL;
  80. MMRESULT mmr;
  81. MMIOINFO mmioinfo;
  82. MMCKINFO ckiRiff;
  83. MMCKINFO cki;
  84. LPWAVEFORMATEX pwfxSrcFormat = NULL;
  85. LPWAVEFORMATEX pwfxDestFormat = NULL;
  86. BOOL bNULLFORMAT = FALSE;
  87. ZeroMemory(&mmioinfo, sizeof(mmioinfo));
  88. if(SUCCEEDED(hr)){
  89. mmioinfo.fccIOProc = FOURCC_MEM;
  90. mmioinfo.pchBuffer = (HPSTR)pbWaveData;
  91. mmioinfo.cchBuffer = cbWaveData;
  92. hmm = mmioOpen(NULL, &mmioinfo, MMIO_READ);
  93. if(!hmm)
  94. {
  95. DPF1(1, "Unable to open file via MMIO. Error %lu", mmioinfo.wErrorRet);
  96. hr = E_FAIL;
  97. }
  98. }
  99. // Decend into the RIFF chunk
  100. if(SUCCEEDED(hr))
  101. {
  102. ckiRiff.ckid = FOURCC_RIFF;
  103. mmr = mmioDescend(hmm, &ckiRiff, NULL, MMIO_FINDCHUNK);
  104. if(MMSYSERR_NOERROR != mmr)
  105. {
  106. DPF1(1, "Unable to descend into RIFF chunk. Error %lu", mmr);
  107. hr = E_FAIL;
  108. }
  109. }
  110. // Verify that this is a wave file
  111. if(SUCCEEDED(hr) && FOURCC_WAVE != ckiRiff.fccType)
  112. {
  113. DPF1(1, "File is not type WAVE %d",GetLastError());
  114. hr = DSERR_BADFORMAT;
  115. }
  116. // Decend into the format chunk
  117. if(SUCCEEDED(hr))
  118. {
  119. cki.ckid = FOURCC_FORMAT;
  120. mmr = mmioDescend(hmm, &cki, &ckiRiff, MMIO_FINDCHUNK);
  121. if(MMSYSERR_NOERROR != mmr)
  122. {
  123. DPF1(1, "Unable to descend into format chunk. Error %lu", mmr);
  124. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  125. }
  126. if(SUCCEEDED(hr))
  127. {
  128. pwfxSrcFormat = (LPWAVEFORMATEX)(pbWaveData + cki.dwDataOffset);
  129. }
  130. }
  131. // Ascend out of the format chunk
  132. if(SUCCEEDED(hr))
  133. {
  134. mmr = mmioAscend(hmm, &cki, 0);
  135. if(MMSYSERR_NOERROR != mmr)
  136. {
  137. DPF(1, "Unable to ascend out of format chunk. Error %lu", mmr);
  138. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  139. }
  140. }
  141. // Descend into the data chunk
  142. if(SUCCEEDED(hr))
  143. {
  144. cki.ckid = FOURCC_DATA;
  145. mmr = mmioDescend(hmm, &cki, &ckiRiff, MMIO_FINDCHUNK);
  146. if(MMSYSERR_NOERROR != mmr)
  147. {
  148. RPF(DPFLVL_ERROR, "Unable to descend into data chunk. Error %lu", mmr);
  149. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  150. }
  151. }
  152. // Prepare PCM conversion
  153. if(SUCCEEDED(hr))
  154. {
  155. if(WAVE_FORMAT_PCM == pwfxSrcFormat->wFormatTag)
  156. {
  157. // Populate the buffer description
  158. dwBufferBytes = cki.cksize;
  159. pwfxDestFormat = pwfxSrcFormat;
  160. }
  161. else
  162. {
  163. // Open an ACM conversion stream
  164. mmr = acmStreamOpen(&has, NULL, (LPWAVEFORMATEX)pwfxSrcFormat, pwfxDestFormat, NULL, 0, 0, 0);
  165. if(MMSYSERR_NOERROR != mmr)
  166. {
  167. RPF(DPFLVL_ERROR, "Unable to open an ACM stream. Error %lu", mmr);
  168. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  169. }
  170. // Get the size of the PCM data
  171. if(SUCCEEDED(hr))
  172. {
  173. mmr = acmStreamSize(has, cki.cksize, &dwBufferBytes, ACM_STREAMSIZEF_SOURCE);
  174. if(MMSYSERR_NOERROR != mmr)
  175. {
  176. RPF(DPFLVL_ERROR, "Unable to determine converted data size. Error %lu", mmr);
  177. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  178. }
  179. }
  180. // Create the destination format
  181. if(SUCCEEDED(hr))
  182. {
  183. pwfxDestFormat = (WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));
  184. if (pwfxDestFormat==NULL) hr=E_OUTOFMEMORY;
  185. }
  186. if(SUCCEEDED(hr))
  187. {
  188. FillWfx(pwfxDestFormat, pwfxSrcFormat->nChannels, pwfxSrcFormat->nSamplesPerSec, pwfxSrcFormat->wBitsPerSample);
  189. }
  190. }
  191. }
  192. LPDIRECTSOUNDBUFFER lpDirectSoundBuffer=NULL;
  193. if(SUCCEEDED(hr))
  194. {
  195. //hr = InitializeEmpty(pDsbDesc->dwFlags, dwBufferBytes, pwfxDestFormat, NULL);
  196. pDsbDesc->dwBufferBytes=dwBufferBytes;
  197. if (pDsbDesc->lpwfxFormat){
  198. memcpy(pDsbDesc->lpwfxFormat,pwfxDestFormat,sizeof(WAVEFORMATEX));
  199. }
  200. else {
  201. pDsbDesc->lpwfxFormat=pwfxDestFormat;
  202. }
  203. hr=lpDirectSound->CreateSoundBuffer(pDsbDesc,lplpDirectSoundBuffer,NULL);
  204. if (*lplpDirectSoundBuffer==NULL) hr= E_FAIL;
  205. lpDirectSoundBuffer=*lplpDirectSoundBuffer;
  206. }
  207. // Lock the buffer in order to write the PCM data to it
  208. if(SUCCEEDED(hr))
  209. {
  210. hr = lpDirectSoundBuffer->Lock(0, dwBufferBytes, &pvWrite, &cbWrite, NULL, NULL,0);
  211. }
  212. // Convert to PCM
  213. if(SUCCEEDED(hr))
  214. {
  215. if(WAVE_FORMAT_PCM == pwfxSrcFormat->wFormatTag)
  216. {
  217. CopyMemory(pvWrite, pbWaveData + cki.dwDataOffset, cbWrite);
  218. }
  219. else
  220. {
  221. // Prepare the conversion header
  222. ZeroMemory(&ash, sizeof(ash));
  223. ash.cbStruct = sizeof(ash);
  224. ash.pbSrc = pbWaveData + cki.dwDataOffset;
  225. ash.cbSrcLength = cki.cksize;
  226. ash.pbDst = (LPBYTE)pvWrite;
  227. ash.cbDstLength = cbWrite;
  228. mmr = acmStreamPrepareHeader(has, &ash, 0);
  229. if(MMSYSERR_NOERROR != mmr)
  230. {
  231. RPF(DPFLVL_ERROR, "Unable to prepare ACM stream header. Error %lu", mmr);
  232. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  233. }
  234. fPrep = SUCCEEDED(hr);
  235. // Convert the buffer
  236. if(SUCCEEDED(hr))
  237. {
  238. mmr = acmStreamConvert(has, &ash, 0);
  239. if(MMSYSERR_NOERROR != mmr)
  240. {
  241. RPF(DPFLVL_ERROR, "Unable to convert wave data. Error %lu", mmr);
  242. hr = E_FAIL; //MMRESULTtoHRESULT(mmr);
  243. }
  244. }
  245. }
  246. }
  247. // Unlock the buffer
  248. if(SUCCEEDED(hr))
  249. {
  250. hr = lpDirectSoundBuffer->Unlock(pvWrite, cbWrite, NULL, 0);
  251. }
  252. // Clean up
  253. if(fPrep)
  254. {
  255. acmStreamUnprepareHeader(has, &ash, 0);
  256. }
  257. if(has)
  258. {
  259. acmStreamClose(has, 0);
  260. }
  261. if(hmm)
  262. {
  263. mmioClose(hmm, 0);
  264. }
  265. if(pwfxDestFormat != pwfxSrcFormat)
  266. {
  267. free(pwfxDestFormat);
  268. }
  269. return hr;
  270. }
  271. #endif
  272. ///////////////////////////////////////////////////////////////////////////////////////////
  273. HRESULT InternalCreateSoundBuffer(LPDSBUFFERDESC pDsbDesc, byte *pbWaveData, DWORD cbWaveData,LPDIRECTSOUND lpDirectSound, LPDIRECTSOUNDBUFFER *lplpDirectSoundBuffer)
  274. {
  275. HRESULT hr = DS_OK;
  276. HACMSTREAM has = NULL;
  277. BOOL fPrep = FALSE;
  278. DWORD dwBufferBytes = 0;
  279. LPVOID pvWrite = NULL;
  280. DWORD cbWrite = 0;
  281. LPWAVEFORMATEX pwfxFormat = NULL;
  282. LPWAVEFORMATEX pwfxSrcFormat = NULL;
  283. LPWAVEFORMATEX pwfxDestFormat = NULL;
  284. MMRESULT mmr = 0;
  285. DWORD dwDataLength = 0;
  286. DWORD dwOffset = 0;
  287. char *pChunk = NULL;
  288. LPDIRECTSOUNDBUFFER lpDirectSoundBuffer = NULL;
  289. ACMSTREAMHEADER ash;
  290. BOOL bNULLFORMAT =FALSE;
  291. BOOL bDirty =FALSE;
  292. struct tag_FileHeader
  293. {
  294. DWORD dwRiff;
  295. DWORD dwFileSize;
  296. DWORD dwWave;
  297. DWORD dwFormat;
  298. DWORD dwFormatLength;
  299. } FileHeader;
  300. ZeroMemory(&FileHeader,sizeof(struct tag_FileHeader));
  301. // If our file is big enough to have a header copy it over
  302. // other wise error out
  303. if (cbWaveData>sizeof(struct tag_FileHeader))
  304. {
  305. memcpy(&FileHeader,pbWaveData,sizeof(struct tag_FileHeader));
  306. }
  307. else
  308. {
  309. hr= E_INVALIDARG;
  310. }
  311. // File must be a riff file ( 52 R, 49 I, 46 F, 46 F)
  312. if (FileHeader.dwRiff != 0x46464952)
  313. {
  314. DPF(1, "DXVB: not a RIFF file\n");
  315. return E_INVALIDARG;
  316. }
  317. // must be a WAVE format ( 57 W, 41 A, 56 V, 45 E )
  318. if (FileHeader.dwWave != 0x45564157)
  319. {
  320. DPF(1, "DXVB: not a WAVE file\n");
  321. return E_INVALIDARG;
  322. }
  323. // check for odd stuff
  324. // note 18bytes is a typical WAVEFORMATEX
  325. if (FileHeader.dwFormatLength <= 14) return E_INVALIDARG;
  326. if (FileHeader.dwFormatLength > 1000) return E_INVALIDARG;
  327. //allocate the waveformat
  328. __try { pwfxFormat=(WAVEFORMATEX*)alloca(FileHeader.dwFormatLength); } __except(EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
  329. if (!pwfxFormat) return E_OUTOFMEMORY;
  330. //copy it to our own data structure
  331. pChunk=(char*)(pbWaveData+sizeof (struct tag_FileHeader));
  332. memcpy(pwfxFormat,pChunk,FileHeader.dwFormatLength);
  333. // Now look for the next chunk after the WaveFormat
  334. pChunk=(char*)(pChunk+FileHeader.dwFormatLength);
  335. // Look for option FACT chunk and skip it
  336. // (66 F, 61 A, 63 C, 74 T)
  337. // this chunk is required for compressed wave files
  338. // but is optional for PCM
  339. //
  340. if ( ((DWORD*)pChunk)[0]==0x74636166)
  341. {
  342. dwOffset=((DWORD*)pChunk)[1];
  343. dwBufferBytes=((DWORD*)pChunk)[2]; //number of bytes of PCM data
  344. pChunk =(char*)(pChunk+ dwOffset+8);
  345. }
  346. //Look for required data chunk
  347. // (64 D, 61 A, 74 T, 61 A)
  348. if (((DWORD*)pChunk)[0]!=0x61746164)
  349. {
  350. DPF(1, "DXVB: no DATA chunk in wave file\n");
  351. return E_INVALIDARG;
  352. }
  353. dwDataLength=((DWORD*)pChunk)[1];
  354. pChunk=(char*)(pChunk+8);
  355. //IF we assume PCM
  356. //pcm files are not required to have their fact chunk
  357. //so be ware they may missreport the data length
  358. dwBufferBytes=dwDataLength;
  359. pwfxDestFormat=pwfxSrcFormat=pwfxFormat;
  360. // if we are not PCM then we need to do some things first
  361. if (pwfxFormat->wFormatTag!=WAVE_FORMAT_PCM)
  362. {
  363. // source format is from the file
  364. pwfxSrcFormat=pwfxFormat; //from file
  365. pwfxDestFormat=pDsbDesc->lpwfxFormat ; //from user
  366. //pick the format of the file passed in
  367. FillWfx(pwfxDestFormat, pwfxSrcFormat->nChannels, pwfxSrcFormat->nSamplesPerSec, pwfxSrcFormat->wBitsPerSample);
  368. // Open an ACM conversion stream
  369. mmr = acmStreamOpen(&has, NULL, (LPWAVEFORMATEX)pwfxSrcFormat, pwfxDestFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
  370. if(MMSYSERR_NOERROR != mmr)
  371. {
  372. DPF1(1, "Unable to open an ACM stream. Error %lu\n", mmr);
  373. return E_FAIL;
  374. }
  375. // Get the size of the PCM data
  376. mmr = acmStreamSize(has, dwDataLength, &dwBufferBytes, ACM_STREAMSIZEF_SOURCE);
  377. if(MMSYSERR_NOERROR != mmr)
  378. {
  379. DPF1(1, "Unable to determine converted data size. Error %lu\n", mmr);
  380. return E_FAIL; //MMRESULTtoHRESULT(mmr);
  381. }
  382. // Allocate a DestFormat struct
  383. //pwfxDestFormat = (WAVEFORMATEX*)alloca(sizeof(WAVEFORMATEX));
  384. //if (!pwfxDestFormat) return E_OUTOFMEMORY;
  385. // Fill the format with information from the source but
  386. // FillWfx sets the format to PCM
  387. //FillWfx(pwfxDestFormat, pwfxSrcFormat->nChannels, pwfxSrcFormat->nSamplesPerSec, pwfxSrcFormat->wBitsPerSample);
  388. }
  389. // fill the buffer desc the user passed in with the buffer bytes
  390. // this is the number of PCM bytes
  391. pDsbDesc->dwBufferBytes=dwBufferBytes;
  392. // if they provide us a pointer to a waveformatex
  393. // copy over the format to the input desc and use it
  394. // otherwise have it point to our data format temprarily
  395. if (pDsbDesc->lpwfxFormat){
  396. memcpy(pDsbDesc->lpwfxFormat,pwfxDestFormat,sizeof(WAVEFORMATEX));
  397. }
  398. else {
  399. pDsbDesc->lpwfxFormat=pwfxDestFormat;
  400. //make sure we null out the format before passing it back to the user
  401. //NOTE: consider the problems in a multithreaded enviroment
  402. //where the users data structures are being accesed by multiple
  403. //threads... on the other hand if thats going on..
  404. //then the user would need to syncronize things on his or her own
  405. //for everything else including calling into apis that fill structures..
  406. bNULLFORMAT=TRUE;
  407. }
  408. // Create the buffer
  409. hr=lpDirectSound->CreateSoundBuffer(pDsbDesc,lplpDirectSoundBuffer,NULL);
  410. if FAILED(hr) return hr;
  411. if (*lplpDirectSoundBuffer==NULL) return E_FAIL; //todo ASSERT this instead..
  412. // for more convenient referencing...
  413. lpDirectSoundBuffer=*lplpDirectSoundBuffer;
  414. // Lock the buffer in order to write the PCM data to it
  415. // cbWrite will contain the number of locked bytes
  416. hr = lpDirectSoundBuffer->Lock(0, dwBufferBytes, &pvWrite, &cbWrite, NULL, NULL,0);
  417. if FAILED(hr) return hr;
  418. // If the sorce format was pcm then copy from the file to the buffer
  419. if(WAVE_FORMAT_PCM == pwfxSrcFormat->wFormatTag)
  420. {
  421. CopyMemory(pvWrite, pChunk, cbWrite);
  422. // Unlock the buffer
  423. hr = lpDirectSoundBuffer->Unlock(pvWrite, cbWrite, NULL, 0);
  424. if (FAILED(hr))
  425. {
  426. DPF(1, "DXVB: lpDirectSoundBuffer->Unlock failed.. \n");
  427. return hr;
  428. }
  429. }
  430. // if the source format is compressed then convert first then copy
  431. else
  432. {
  433. // Prepare the conversion header
  434. ZeroMemory(&ash, sizeof(ash));
  435. ash.cbStruct = sizeof(ash);
  436. ash.pbSrc = (unsigned char*)pChunk; //start of compressed data
  437. ash.cbSrcLength = dwDataLength; //number of bytes of compressed data
  438. ash.pbDst = (LPBYTE)pvWrite; //where to put the decompressed data
  439. ash.cbDstLength = cbWrite; //how big is that buffer
  440. mmr = acmStreamPrepareHeader(has, &ash, 0);
  441. if(MMSYSERR_NOERROR != mmr)
  442. {
  443. DPF1(1, "DXVB: Unable to prepare ACM stream header. Error %lu \n", mmr);
  444. return E_FAIL;
  445. }
  446. mmr = acmStreamConvert(has, &ash, 0);
  447. if(MMSYSERR_NOERROR != mmr)
  448. {
  449. DPF1(1, "DXVB: Unable to convert wave data. Error %lu \n", mmr);
  450. return hr;
  451. }
  452. // Unlock the buffer
  453. hr = lpDirectSoundBuffer->Unlock(pvWrite, cbWrite, NULL, 0);
  454. if (FAILED(hr))
  455. {
  456. DPF(1, "DXVB: lpDirectSoundBuffer->Unlock failed.. \n");
  457. return hr;
  458. }
  459. acmStreamUnprepareHeader(has, &ash, 0);
  460. acmStreamClose(has, 0);
  461. }
  462. if (bNULLFORMAT){
  463. pDsbDesc->lpwfxFormat=NULL;
  464. }
  465. return hr;
  466. }
  467. HRESULT InternalCreateSoundBufferFromFile(LPDIRECTSOUND lpDirectSound,LPDSBUFFERDESC pDesc,WCHAR *file,LPDIRECTSOUNDBUFFER *lplpDirectSoundBuffer)
  468. {
  469. HRESULT hr=S_OK;
  470. HANDLE hFile = NULL;
  471. HANDLE hFileMapping = NULL;
  472. DWORD cbWaveData;
  473. LPBYTE pbWaveData = NULL;
  474. #pragma message("CreateFileW should be used for localization why wont it work")
  475. //hFile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  476. USES_CONVERSION;
  477. LPSTR pStrA = NULL;
  478. __try { pStrA = W2T(file); /* Now convert to ANSI */ } __except(EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
  479. if (!pStrA) return E_INVALIDARG;
  480. hFile = CreateFileA(pStrA, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  481. if(INVALID_HANDLE_VALUE == hFile)
  482. {
  483. hFile = NULL;
  484. }
  485. if(!hFile)
  486. {
  487. RPF(DPFLVL_ERROR, "Unable to open file. Error %lu", GetLastError());
  488. hr=STG_E_FILENOTFOUND;
  489. return hr;
  490. }
  491. if(hFile)
  492. {
  493. cbWaveData = GetFileSize(hFile, NULL);
  494. if(-1 == cbWaveData)
  495. {
  496. RPF(DPFLVL_ERROR, "Unable to get file size. Error %lu", GetLastError());
  497. hr = E_FAIL; //DSERR_FILEREADFAULT;
  498. }
  499. }
  500. if(SUCCEEDED(hr))
  501. {
  502. hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, cbWaveData, NULL);
  503. if(INVALID_HANDLE_VALUE == hFileMapping)
  504. {
  505. hFileMapping = NULL;
  506. }
  507. if(!hFileMapping)
  508. {
  509. RPF(DPFLVL_ERROR, "Unable to create file mapping. Error %lu", GetLastError());
  510. hr = E_FAIL; //DSERR_FILEREADFAULT;
  511. }
  512. }
  513. if(SUCCEEDED(hr))
  514. {
  515. pbWaveData = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, cbWaveData);
  516. if(!pbWaveData)
  517. {
  518. RPF(DPFLVL_ERROR, "Unable to map view of file. Error %lu", GetLastError());
  519. hr = E_FAIL; //DSERR_FILEREADFAULT;
  520. }
  521. }
  522. if(SUCCEEDED(hr)) {
  523. hr=InternalCreateSoundBuffer(pDesc, pbWaveData, cbWaveData,lpDirectSound, lplpDirectSoundBuffer);
  524. }
  525. if(pbWaveData)
  526. {
  527. UnmapViewOfFile(pbWaveData);
  528. }
  529. if(hFileMapping)
  530. {
  531. CloseHandle(hFileMapping);
  532. }
  533. if(hFile)
  534. {
  535. CloseHandle(hFile);
  536. }
  537. return hr;
  538. }
  539. HRESULT InternalCreateSoundBufferFromResource(LPDIRECTSOUND lpDirectSound,LPDSBUFFERDESC pDesc,HANDLE resHandle,WCHAR *resName,LPDIRECTSOUNDBUFFER *lplpDirectSoundBuffer)
  540. {
  541. const LPCSTR apszResourceTypeA[] = { "WAVE", "WAV" };
  542. const LPCWSTR apszResourceTypeW[] = { L"WAVE", L"WAV" };
  543. UINT cResourceType = 2;
  544. HRSRC hRsrc = NULL;
  545. DWORD cbWaveData;
  546. LPBYTE pbWaveData = NULL;
  547. HRESULT hr=S_OK;
  548. LPCDSBUFFERDESC pDsbDesc=pDesc;
  549. while(!hRsrc && cResourceType--)
  550. {
  551. hRsrc = FindResourceW((HINSTANCE)resHandle, resName, apszResourceTypeW[cResourceType]);
  552. }
  553. if(!hRsrc)
  554. {
  555. RPF(DPFLVL_ERROR,"Unable to find resource. Error %lu", GetLastError());
  556. hr = STG_E_FILENOTFOUND;
  557. }
  558. if(SUCCEEDED(hr))
  559. {
  560. cbWaveData = SizeofResource((HINSTANCE)resHandle, hRsrc);
  561. if(!cbWaveData)
  562. {
  563. RPF(DPFLVL_ERROR, "Unable to get resource size. Error %lu", GetLastError());
  564. hr = E_FAIL;
  565. }
  566. }
  567. if(SUCCEEDED(hr))
  568. {
  569. pbWaveData = (LPBYTE)LoadResource((HINSTANCE)resHandle, hRsrc);
  570. if(!pbWaveData)
  571. {
  572. RPF(DPFLVL_ERROR, "Unable to load resource. Error %lu", GetLastError());
  573. hr = E_FAIL;
  574. }
  575. }
  576. if(SUCCEEDED(hr)) {
  577. hr=InternalCreateSoundBuffer(pDesc, pbWaveData, cbWaveData,lpDirectSound, lplpDirectSoundBuffer);
  578. }
  579. //loadResource
  580. return hr;
  581. }
  582. HRESULT InternalSaveToFile(IDirectSoundBuffer *pBuff,BSTR file)
  583. {
  584. WAVEFORMATEX waveFormat;
  585. DWORD dwWritten=0;
  586. DWORD dwBytes=0;
  587. LPBYTE lpByte=NULL;
  588. HRESULT hr;
  589. HANDLE hFile=NULL;
  590. if (!pBuff) return E_FAIL;
  591. if (!file) return E_INVALIDARG;
  592. pBuff->GetFormat(&waveFormat,sizeof(WAVEFORMATEX),NULL);
  593. USES_CONVERSION;
  594. LPSTR pStrA = NULL;
  595. __try { pStrA = W2T(file); /* Now convert to ANSI */ } __except(EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
  596. hFile = CreateFile
  597. (
  598. pStrA,
  599. GENERIC_WRITE,
  600. 0,
  601. NULL,
  602. CREATE_ALWAYS,
  603. FILE_ATTRIBUTE_NORMAL,
  604. NULL
  605. );
  606. if (INVALID_HANDLE_VALUE != hFile)
  607. {
  608. struct tag_FileHeader
  609. {
  610. DWORD dwRiff;
  611. DWORD dwFileSize;
  612. DWORD dwWave;
  613. DWORD dwFormat;
  614. DWORD dwFormatLength;
  615. WORD wFormatTag;
  616. WORD nChannels;
  617. DWORD nSamplesPerSec;
  618. DWORD nAvgBytesPerSec;
  619. WORD nBlockAlign;
  620. WORD wBitsPerSample;
  621. DWORD dwData;
  622. DWORD dwDataLength;
  623. } FileHeader;
  624. hr=pBuff->Lock(0,0,(void**)&lpByte,&dwBytes,NULL,NULL,DSBLOCK_ENTIREBUFFER);
  625. if FAILED(hr) {
  626. CloseHandle(hFile);
  627. return hr;
  628. }
  629. FileHeader.dwRiff = 0x46464952; // RIFF
  630. FileHeader.dwWave = 0x45564157; // WAVE
  631. FileHeader.dwFormat = 0x20746D66; // fmt_chnk
  632. FileHeader.dwFormatLength = 16;
  633. FileHeader.wFormatTag = WAVE_FORMAT_PCM;
  634. FileHeader.nChannels = waveFormat.nChannels ;
  635. FileHeader.nSamplesPerSec = waveFormat.nSamplesPerSec ;
  636. FileHeader.wBitsPerSample = waveFormat.wBitsPerSample ;
  637. FileHeader.nBlockAlign = FileHeader.wBitsPerSample / 8 * FileHeader.nChannels;
  638. FileHeader.nAvgBytesPerSec = FileHeader.nSamplesPerSec * FileHeader.nBlockAlign;
  639. FileHeader.dwData = 0x61746164; // data_chnk
  640. FileHeader.dwDataLength = dwBytes;
  641. FileHeader.dwFileSize = dwBytes + sizeof(FileHeader);
  642. WriteFile(hFile, &FileHeader, sizeof(FileHeader), &dwWritten, NULL);
  643. WriteFile(hFile, lpByte, dwBytes, &dwWritten, NULL);
  644. hr=pBuff->Unlock(lpByte,0,NULL,0);
  645. CloseHandle(hFile);
  646. }
  647. else{
  648. return E_FAIL;
  649. }
  650. return S_OK;
  651. }