Windows NT 4.0 source code leak
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.

423 lines
11 KiB

4 years ago
  1. //--------------------------------------------------------------------------;
  2. //
  3. // File: idsi.c
  4. //
  5. // Copyright (c) 1995 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Abstract:
  8. // This file contains worker functions called internally by
  9. // IDirectSound member functions. These functions operate on
  10. // DSOUND objects (i.e., internal direct sound objects) and
  11. // do not perform parameter validation nor do they take the
  12. // DLL critical sections. In all cases, the calling function
  13. // is responsible for doing this.
  14. //
  15. // Contents:
  16. // IDsCreateSoundBufferI
  17. //
  18. //--------------------------------------------------------------------------;
  19. #include "dsoundpr.h"
  20. //--------------------------------------------------------------------------;
  21. //
  22. // HRESULT DsInitializeDefaultFormat
  23. //
  24. // Description:
  25. // Fills in the wfxDefault member of the ds object. The format
  26. // is based on the system default stored in the dsinfo but may
  27. // deviate depending on the capabilities of the ds object.
  28. //
  29. // Note that this may be called before the ds object has been
  30. // completely constructed, as it is called from DirectSoundCreate.
  31. //
  32. // Arguments:
  33. // LPDSOUND pds
  34. //
  35. // Return (DSVAL):
  36. //
  37. // History:
  38. // 07/17/95 FrankYe Created
  39. //
  40. //--------------------------------------------------------------------------;
  41. #define FNAME "DsInitializeDefaultFormat: "
  42. HRESULT DsInitializeDefaultFormat(LPDSOUND pds)
  43. {
  44. LPWAVEFORMATEX pwfx;
  45. DSDRIVERCAPS dsDrvCaps;
  46. HRESULT hr;
  47. // DirectSound supports only PCM formats for now.
  48. // This function assumes PCM formats.
  49. ASSERT(WAVE_FORMAT_PCM == gpdsinfo->pwfxUserDefault->wFormatTag);
  50. pwfx = &pds->wfxDefault;
  51. //
  52. // Handle wave emulated ds objects
  53. //
  54. if (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal) {
  55. BOOL fBreak;
  56. MMRESULT mmr;
  57. int i, j, k;
  58. //
  59. // Start with the user default
  60. //
  61. CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
  62. // We search for a format that works.
  63. //
  64. // i loop cycles through nChannels
  65. // j loop cycles through sample rate
  66. // k loop cycles through bit resolution
  67. //
  68. // We loop like this so that the number of channels is least likely
  69. // to deviate from the user format, sample rate is next least likely.
  70. //
  71. i = 0;
  72. do {
  73. j = 0;
  74. do {
  75. k = 0;
  76. do {
  77. // Fix up nBlockAlign and nAvgBytesPerSec
  78. pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8;
  79. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  80. mmr = waveOutOpen(NULL, pds->uDeviceID, pwfx, 0, 0, WAVE_FORMAT_QUERY);
  81. fBreak = (MMSYSERR_NOERROR == mmr);
  82. if (fBreak) break;
  83. if (pwfx->wBitsPerSample == 16) {
  84. pwfx->wBitsPerSample = 8;
  85. } else {
  86. pwfx->wBitsPerSample = 16;
  87. }
  88. } while (++k < 2);
  89. if (fBreak) break;
  90. if (pwfx->nSamplesPerSec == 44100) {
  91. pwfx->nSamplesPerSec = 22050;
  92. } else if (pwfx->nSamplesPerSec == 22050) {
  93. pwfx->nSamplesPerSec = 11025;
  94. } else if (pwfx->nSamplesPerSec == 11025) {
  95. pwfx->nSamplesPerSec = 8000;
  96. } else {
  97. pwfx->nSamplesPerSec = 44100;
  98. }
  99. } while (++j < 4);
  100. if (fBreak) break;
  101. if (pwfx->nChannels == 2) {
  102. pwfx->nChannels = 1;
  103. } else {
  104. pwfx->nChannels = 2;
  105. }
  106. } while (++i < 2);
  107. if (MMSYSERR_NOERROR != mmr) {
  108. DPF(0, FNAME "error: waveOutOpen.Query returned %08Xh", mmr);
  109. // Couldn't come up with anything. Put back user default.
  110. CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
  111. return DSERR_GENERIC;
  112. }
  113. return DS_OK;
  114. }
  115. // If we fall through, we are not on a wave emulated object
  116. ASSERT(0 == (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal));
  117. //
  118. // Handle non-wave emulated ds objects
  119. //
  120. FillMemory(&dsDrvCaps, sizeof(dsDrvCaps), 0);
  121. hr = vxdDrvGetCaps(pds->hHal, &dsDrvCaps);
  122. if (DS_OK != hr) {
  123. DPF(0, FNAME "error: vxdDrvGetDriverCaps returned %08Xh", hr);
  124. return hr;
  125. }
  126. //
  127. // Start with the user default
  128. //
  129. CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
  130. // Adjust resolution
  131. if (pwfx->wBitsPerSample == 16) {
  132. if (!(DSCAPS_PRIMARY16BIT & dsDrvCaps.dwFlags)) {
  133. // Try 8-bit
  134. pwfx->wBitsPerSample = 8;
  135. ASSERT(DSCAPS_PRIMARY8BIT & dsDrvCaps.dwFlags);
  136. }
  137. } else {
  138. if (!(DSCAPS_PRIMARY8BIT & dsDrvCaps.dwFlags)) {
  139. // Try 16-bit
  140. pwfx->wBitsPerSample = 16;
  141. ASSERT(DSCAPS_PRIMARY16BIT & dsDrvCaps.dwFlags);
  142. }
  143. }
  144. // Adjust mono/stereo
  145. if (pwfx->nChannels == 2) {
  146. if (!(DSCAPS_PRIMARYSTEREO & dsDrvCaps.dwFlags)) {
  147. // Try mono
  148. pwfx->nChannels = 1;
  149. ASSERT(DSCAPS_PRIMARYMONO & dsDrvCaps.dwFlags);
  150. }
  151. } else {
  152. if (!(DSCAPS_PRIMARYMONO & dsDrvCaps.dwFlags)) {
  153. // Try stereo
  154. pwfx->nChannels = 2;
  155. ASSERT(DSCAPS_PRIMARYSTEREO & dsDrvCaps.dwFlags);
  156. }
  157. }
  158. // Fix up nBlockAlign and nAvgBytesPerSec
  159. pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8;
  160. pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
  161. return DS_OK;
  162. }
  163. #undef FNAME
  164. //--------------------------------------------------------------------------;
  165. //
  166. // HRESULT DsCreateHardwareBuffer
  167. //
  168. // Description:
  169. //
  170. // Arguments:
  171. // LPDSOUND pds
  172. //
  173. // LPDSBUFFER pdsb
  174. //
  175. // LPDSBUFFERDESC pdsbd
  176. //
  177. // LPBOOL pfTrySoftware: If an error is encountered such that we
  178. // should not retry creating the buffer as a software buffer,
  179. // then this routine will write FALSE to this flag. Otherwise
  180. // this routine WILL NOT WRITE to this flag.
  181. //
  182. // Return (DSVAL):
  183. //
  184. // History:
  185. // 07/17/95 FrankYe Created
  186. //
  187. //--------------------------------------------------------------------------;
  188. HRESULT DsCreateHardwareBuffer
  189. (
  190. LPDSOUND pds,
  191. LPDSBUFFER pdsb,
  192. LPDSBUFFERDESC pdsbd,
  193. LPBOOL pfTrySoftware
  194. )
  195. {
  196. LPWAVEFORMATEX pwfx = pdsb->pwfx;
  197. DWORD dwcbBufferSize = pdsb->cbBufferSize;
  198. DWORD dwFlags = pdsbd->dwFlags;
  199. LPBYTE pBuffer = NULL;
  200. HANDLE hBuffer = NULL;
  201. DSVAL dsv = DS_OK;
  202. pdsb->dwCardAddress = 0;
  203. //
  204. // We are asking for a HW buffer...
  205. //
  206. DPF(3,"HW Create HW buffer");
  207. DPF(3,"HW Create - sample rate %d", pdsb->helInfo.dwSampleRate );
  208. DPF(3,"HW Create - hfForamt %X", pdsb->helInfo.hfFormat );
  209. //
  210. // See whether we should use system memory for the sound buffer
  211. //
  212. if( (DSDDESC_USESYSTEMMEMORY & pds->fdwDriverDesc) &&
  213. !(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER ) ) {
  214. // Allocate the buffer sound buffer in system memory
  215. pBuffer = (LPBYTE)MemAlloc(dwcbBufferSize);
  216. if(NULL == pBuffer) {
  217. DPF(0,"DSDDESC_USESYSTEMMEMORY buffer alloc failed");
  218. dsv = DSERR_OUTOFMEMORY;
  219. *pfTrySoftware = FALSE;
  220. goto retDestruct;
  221. }
  222. DPF(1, " allocated system memory at %08Xh", pBuffer);
  223. }
  224. //
  225. // see whether to allocate on-card memory
  226. //
  227. if( (NULL != pds->pDriverHeap) && !(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) ) {
  228. // Use dmemmgr to allocate on-card buffer and pass
  229. // that allocation to the driver
  230. pdsb->dwCardAddress = VidMemAlloc( pds->pDriverHeap,
  231. dwcbBufferSize + pds->dwMemAllocExtra,
  232. 1);
  233. if (0 == pdsb->dwCardAddress) {
  234. dsv = DSERR_ALLOCATED;
  235. goto retDestruct;
  236. }
  237. DPF(1, " allocated card memory at %08Xh", pdsb->dwCardAddress);
  238. }
  239. //
  240. // now ask driver to create sound buffer
  241. //
  242. dsv = vxdDrvCreateSoundBuffer( pds->hHal, pwfx,
  243. dwFlags & DSBCAPS_DRIVERFLAGSMASK,
  244. pdsb->dwCardAddress, &dwcbBufferSize,
  245. &pBuffer, &hBuffer );
  246. if (DS_OK != dsv) {
  247. DPF(0,"vxdDrvCreateSoundBuffer failed");
  248. hBuffer = NULL;
  249. goto retDestruct;
  250. }
  251. //
  252. // see whether we should set format via mmsystem
  253. //
  254. if ( (DSDDESC_DOMMSYSTEMSETFORMAT & pds->fdwDriverDesc) &&
  255. (DSBCAPS_PRIMARYBUFFER & pdsbd->dwFlags) )
  256. {
  257. //
  258. // We need to set the wave format by doing a waveOutOpen on the
  259. // mmsystem wave device
  260. //
  261. UINT uDeviceID;
  262. MMRESULT mmr;
  263. DPF(3, "CreateSoundBuffer: DSDCAPS_DOMMSYSTEMSETFORMAT");
  264. ASSERT(pds->hwo);
  265. waveOutGetID(pds->hwo, &uDeviceID);
  266. HelperWaveClose( (DWORD)(pds->hwo) );
  267. pds->hwo = NULL;
  268. mmr = (MMRESULT)HelperWaveOpen(&(pds->hwo),
  269. uDeviceID,
  270. pwfx);
  271. if (MMSYSERR_NOERROR != mmr) {
  272. pds->hwo = NULL;
  273. if (MMSYSERR_ALLOCATED == mmr) dsv = DSERR_BUFFERLOST;
  274. if (MMSYSERR_NOMEM == mmr) dsv = DSERR_OUTOFMEMORY;
  275. if (DS_OK == dsv) dsv = DSERR_GENERIC;
  276. *pfTrySoftware = FALSE;
  277. goto retDestruct;
  278. }
  279. }
  280. //
  281. // all went okay
  282. //
  283. DPF(3,"IDSHWCreateSoundBuffer buffer alloc OK");
  284. DPF(3," lin addr %X", pBuffer );
  285. DPF(3," length %X", dwcbBufferSize );
  286. ASSERT(NULL != hBuffer);
  287. pdsb->hBuffer = hBuffer;
  288. pdsb->pDSBuffer = pBuffer;
  289. pdsb->cbBufferSize = dwcbBufferSize;
  290. pdsb->fdwDsbI &= (~DSB_INTERNALF_EMULATED);
  291. pdsb->fdwDsbI |= DSB_INTERNALF_HARDWARE;
  292. retDestruct:
  293. if (DS_OK == dsv) return dsv;
  294. // release buffer
  295. if (NULL != hBuffer) {
  296. vxdBufferRelease(hBuffer);
  297. hBuffer = NULL;
  298. }
  299. // free card memory
  300. if (0 != pdsb->dwCardAddress) {
  301. ASSERT(NULL != pds->pDriverHeap);
  302. ASSERT(!(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER));
  303. VidMemFree(pds->pDriverHeap, pdsb->dwCardAddress);
  304. pdsb->dwCardAddress = 0;
  305. }
  306. // free sysalloc mem
  307. if( (DSDDESC_USESYSTEMMEMORY & pds->fdwDriverDesc) &&
  308. (0 == (pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) &&
  309. (NULL != pBuffer) ) {
  310. MemFree(pBuffer);
  311. pBuffer = NULL;
  312. }
  313. return dsv;
  314. }
  315. //--------------------------------------------------------------------------;
  316. //
  317. // HRESULT DsCreateSoftwareBuffer
  318. //
  319. // Description:
  320. //
  321. // Arguments:
  322. // LPDSOUND pds
  323. //
  324. // LPDSBUFFER pdsb
  325. //
  326. // LPDSBUFFERDESC pdsbd
  327. //
  328. // Return (DSVAL):
  329. //
  330. // History:
  331. // 07/17/95 FrankYe Created
  332. //
  333. //--------------------------------------------------------------------------;
  334. HRESULT DsCreateSoftwareBuffer
  335. (
  336. LPDSOUND pds,
  337. LPDSBUFFER pdsb,
  338. LPDSBUFFERDESC pdsbd
  339. )
  340. {
  341. DPF(3,"HW Create Emulated secondary buffer");
  342. // Allocate the buffer
  343. pdsb->pDSBuffer = (LPBYTE)MemAlloc(pdsbd->dwBufferBytes);
  344. if(NULL == pdsb->pDSBuffer) {
  345. DPF(1,"IDSHWCreateSoundBuffer buffer alloc fail");
  346. return DSERR_OUTOFMEMORY;
  347. }
  348. pdsb->cbBufferSize = pdsbd->dwBufferBytes;
  349. pdsb->fdwDsbI &= (~DSB_INTERNALF_HARDWARE);
  350. pdsb->fdwDsbI |= DSB_INTERNALF_EMULATED;
  351. // Make sure both copies of the flags reflect that this
  352. // is a software buffer.
  353. pdsbd->dwFlags &= (~DSBCAPS_LOCHARDWARE);
  354. pdsbd->dwFlags |= DSBCAPS_LOCSOFTWARE;
  355. pdsb->fdwBufferDesc &= (~DSBCAPS_LOCHARDWARE);
  356. pdsb->fdwBufferDesc |= DSBCAPS_LOCSOFTWARE;
  357. DPF(3,"--------Alloc data for Emulated obj %X buff %X len %X",
  358. pdsb, pdsb->pDSBuffer, pdsb->cbBufferSize );
  359. return DS_OK;
  360. }