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.

726 lines
22 KiB

  1. /****************************************************************************
  2. *
  3. * File: testsnd.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Kerim Erden (a-kerime@microsoft.com)
  6. * Purpose: Test DSound functionality on this machine
  7. *
  8. * (C) Copyright 1998 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #define DIRECTSOUND_VERSION 0x0600
  12. #include <Windows.h>
  13. #include <mmsystem.h>
  14. #include <d3dtypes.h>
  15. #include <dsound.h>
  16. #include "resource.h"
  17. #include "reginfo.h"
  18. #include "sysinfo.h"
  19. #include "dispinfo.h"
  20. #include "sndinfo.h"
  21. #include "testsnd.h"
  22. struct WAVE
  23. {
  24. WAVEFORMATEX* psHeader;
  25. LPBYTE pData;
  26. DWORD dwSize;
  27. };
  28. typedef HRESULT (WINAPI* LPDIRECTSOUNDCREATE)(GUID* pGUID, LPDIRECTSOUND* ppDS,
  29. IUnknown* pUnkOuter);
  30. enum TESTID
  31. {
  32. TESTID_LOAD_DSOUND_DLL = 1,
  33. TESTID_GET_DIRECTSOUNDCREATE,
  34. TESTID_DIRECTSOUNDCREATE,
  35. TESTID_SETCOOP,
  36. TESTID_GETCAPS,
  37. TESTID_LOADWAVDATA,
  38. TESTID_EMULDRIVER,
  39. TESTID_PRIMBUF,
  40. TESTID_NOFREEHWBUF,
  41. TESTID_SECBUF,
  42. TESTID_SETPOS,
  43. TESTID_NOSAMPLE,
  44. TESTID_CREATEEVENT,
  45. TESTID_SETNOTIF,
  46. TESTID_LOCKFAIL,
  47. TESTID_UNLOCKFAIL,
  48. TESTID_PLAY,
  49. TESTID_GETCURPOS,
  50. TESTID_USER_VERIFY_SOFTWARE,
  51. TESTID_USER_VERIFY_HARDWARE
  52. };
  53. BOOL BTranslateError(HRESULT hr, TCHAR* psz, BOOL bEnglish = FALSE); // from main.cpp (yuck)
  54. static BOOL TestDSInit(HWND hwndMain, LPDIRECTSOUND* ppDS, HINSTANCE* phInstDS,
  55. SoundInfo* pSoundInfo);
  56. static BOOL TestDSPlay(HWND hWndMain, DSCAPS* pDSCaps, LPDIRECTSOUND pDS,
  57. SoundInfo* pSoundInfo, WAVE* pWave, BOOL bHardware, BOOL b3D);
  58. static BOOL PlayDSound(HWND hWndMain, DSCAPS* pDSCaps, LPDIRECTSOUNDBUFFER pPrim,
  59. LPDIRECTSOUNDBUFFER pSec, WAVEFORMATEX* pPrimFmt, DWORD dwBufSize,
  60. SoundInfo* pSoundInfo, WAVE* pWave, BOOL bHardware, BOOL b3D);
  61. static BOOL LoadTestData(WAVE* pWave);
  62. static VOID FillFormat(WAVEFORMATEX* pWFM);
  63. static VOID TestDSTerm(LPDIRECTSOUND* ppDS, HINSTANCE* phInstDS, SoundInfo* pSoundInfo);
  64. static VOID TestDSReport(SoundInfo* pSoundInfo);
  65. static BOOL s_b16BitWarningGiven = FALSE;
  66. /****************************************************************************
  67. *
  68. * TestSnd
  69. *
  70. ****************************************************************************/
  71. VOID TestSnd(HWND hwndMain, SoundInfo* pSoundInfo)
  72. {
  73. HINSTANCE hInstDS = NULL;
  74. LPDIRECTSOUND pDS = NULL;
  75. DSCAPS sDSCaps;
  76. HRESULT hr = S_OK;
  77. WAVE sWaveTest;
  78. TCHAR sz[300];
  79. TCHAR szTitle[100];
  80. // Remove info from any previous test:
  81. ZeroMemory(&pSoundInfo->m_testResultSnd, sizeof(TestResult));
  82. s_b16BitWarningGiven = FALSE;
  83. LoadString(NULL, IDS_STARTDSOUNDTEST, sz, 300);
  84. LoadString(NULL, IDS_APPFULLNAME, szTitle, 100);
  85. if (IDNO == MessageBox(hwndMain, sz, szTitle, MB_YESNO))
  86. {
  87. pSoundInfo->m_testResultSnd.m_bCancelled = TRUE;
  88. TestDSReport(pSoundInfo);
  89. return;
  90. }
  91. // Remove info from any previous test:
  92. ZeroMemory(&pSoundInfo->m_testResultSnd, sizeof(TestResult));
  93. pSoundInfo->m_testResultSnd.m_bStarted = TRUE;
  94. if (!TestDSInit(hwndMain, &pDS, &hInstDS, pSoundInfo))
  95. goto LEnd;
  96. // Get Caps
  97. ZeroMemory(&sDSCaps, sizeof(sDSCaps));
  98. sDSCaps.dwSize = sizeof(sDSCaps);
  99. if (FAILED(hr = pDS->GetCaps(&sDSCaps)))
  100. {
  101. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_GETCAPS;
  102. pSoundInfo->m_testResultSnd.m_hr = hr;
  103. goto LEnd;
  104. }
  105. if (!LoadTestData(&sWaveTest))
  106. {
  107. // report cannot load wave data
  108. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_LOADWAVDATA;
  109. pSoundInfo->m_testResultSnd.m_hr = E_FAIL;
  110. goto LEnd;
  111. }
  112. // Check 2D, software buffers
  113. if (!TestDSPlay(hwndMain, &sDSCaps, pDS, pSoundInfo, &sWaveTest, FALSE, FALSE))
  114. goto LEnd;
  115. // Check 3D, software buffers
  116. if (!TestDSPlay(hwndMain, &sDSCaps, pDS, pSoundInfo, &sWaveTest, FALSE, TRUE))
  117. goto LEnd;
  118. if (sDSCaps.dwFlags & DSCAPS_EMULDRIVER ||
  119. (sDSCaps.dwFreeHw3DStaticBuffers == 0 && sDSCaps.dwFreeHwMixingStaticBuffers == 0) )
  120. {
  121. LoadString(NULL, IDS_NOHARDWAREBUFFERING, sz, 300);
  122. MessageBox(hwndMain, sz, szTitle, MB_OK);
  123. goto LEnd;
  124. }
  125. // Check 2D, hardware buffers
  126. if (!TestDSPlay(hwndMain, &sDSCaps, pDS, pSoundInfo, &sWaveTest, TRUE, FALSE))
  127. goto LEnd;
  128. // Check 3D, hardware buffers
  129. if (!TestDSPlay(hwndMain, &sDSCaps, pDS, pSoundInfo, &sWaveTest, TRUE, TRUE))
  130. goto LEnd;
  131. LEnd:
  132. TestDSTerm(&pDS, &hInstDS, pSoundInfo);
  133. TestDSReport(pSoundInfo);
  134. }
  135. /****************************************************************************
  136. *
  137. * TestDSInit
  138. *
  139. ****************************************************************************/
  140. BOOL TestDSInit(HWND hwndMain, LPDIRECTSOUND* ppDS, HINSTANCE* phInstDS,
  141. SoundInfo* pSoundInfo)
  142. {
  143. LPDIRECTSOUNDCREATE pDSCreate = NULL;
  144. HRESULT hr = S_OK;
  145. TCHAR szPath[MAX_PATH];
  146. // Load dsound.dll
  147. GetSystemDirectory(szPath, MAX_PATH);
  148. lstrcat(szPath, TEXT("\\dsound.dll"));
  149. *phInstDS = LoadLibrary(szPath);
  150. if (NULL == *phInstDS)
  151. {
  152. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_LOAD_DSOUND_DLL;
  153. pSoundInfo->m_testResultSnd.m_hr = DDERR_NOTFOUND;
  154. return FALSE;
  155. }
  156. // Get DirectSoundCreate entry point
  157. pDSCreate = (LPDIRECTSOUNDCREATE)GetProcAddress(*phInstDS, "DirectSoundCreate");
  158. if (NULL == pDSCreate)
  159. {
  160. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_GET_DIRECTSOUNDCREATE;
  161. pSoundInfo->m_testResultSnd.m_hr = DDERR_NOTFOUND;
  162. return FALSE;
  163. }
  164. // Call DirectSoundCreate
  165. if (FAILED(hr = pDSCreate(NULL, ppDS, NULL)))
  166. {
  167. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_DIRECTSOUNDCREATE;
  168. pSoundInfo->m_testResultSnd.m_hr = hr;
  169. return FALSE;
  170. }
  171. // Set cooperative level
  172. if (FAILED(hr = (*ppDS)->SetCooperativeLevel(hwndMain, DSSCL_EXCLUSIVE)))
  173. {
  174. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_SETCOOP;
  175. pSoundInfo->m_testResultSnd.m_hr = hr;
  176. return FALSE;
  177. }
  178. return TRUE;
  179. }
  180. /****************************************************************************
  181. *
  182. * TestDSPlay
  183. *
  184. ****************************************************************************/
  185. BOOL TestDSPlay(HWND hWndMain, DSCAPS* pDSCaps, LPDIRECTSOUND pDS,
  186. SoundInfo* pSoundInfo, WAVE* pWave, BOOL bHardware, BOOL b3D)
  187. {
  188. BOOL bRet = TRUE;
  189. DSBUFFERDESC sBufDesc;
  190. LPDIRECTSOUNDBUFFER pPrimBuf = NULL;
  191. LPDIRECTSOUNDBUFFER pDSBuf = NULL;
  192. HRESULT hr = S_OK;
  193. WAVEFORMATEX sWaveFmt;
  194. LPDIRECTSOUND3DBUFFER pBuf3D = NULL;
  195. // Create the Primary Buffer
  196. ZeroMemory(&sBufDesc, sizeof(sBufDesc));
  197. sBufDesc.dwSize = sizeof(sBufDesc);
  198. sBufDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
  199. if (b3D)
  200. sBufDesc.dwFlags |= DSBCAPS_CTRL3D;
  201. if (FAILED(hr = pDS->CreateSoundBuffer(&sBufDesc, &pPrimBuf, NULL)))
  202. {
  203. // Report: Cannot create primary buffer
  204. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_PRIMBUF;
  205. pSoundInfo->m_testResultSnd.m_hr = hr;
  206. bRet = FALSE;
  207. goto LEnd;
  208. }
  209. // Create a secondary static buffer
  210. ZeroMemory(&sBufDesc, sizeof(sBufDesc));
  211. sBufDesc.dwSize = sizeof(sBufDesc);
  212. sBufDesc.lpwfxFormat = pWave->psHeader;
  213. sBufDesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY;
  214. if (b3D)
  215. sBufDesc.dwFlags |= DSBCAPS_CTRL3D;
  216. if (bHardware)
  217. {
  218. // Check Hardware free mem
  219. if ((1 <= (b3D ? pDSCaps->dwFreeHw3DStaticBuffers : pDSCaps->dwFreeHwMixingStaticBuffers)) )
  220. {
  221. // Hardware static buffer
  222. sBufDesc.dwFlags |= DSBCAPS_STATIC | DSBCAPS_LOCHARDWARE;
  223. sBufDesc.dwBufferBytes = pWave->dwSize;
  224. }
  225. else
  226. {
  227. // Can't do hardware testing, so exit silently
  228. goto LEnd;
  229. }
  230. }
  231. else
  232. {
  233. sBufDesc.dwFlags |= DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
  234. sBufDesc.dwBufferBytes = pWave->dwSize;
  235. }
  236. if (FAILED(hr = pDS->CreateSoundBuffer(&sBufDesc, &pDSBuf, NULL)))
  237. {
  238. if (DSERR_CONTROLUNAVAIL == hr || DSERR_INVALIDPARAM == hr)
  239. {
  240. // Driver does not support position notify, try without it
  241. sBufDesc.dwFlags &= ~DSBCAPS_CTRLPOSITIONNOTIFY;
  242. hr = pDS->CreateSoundBuffer(&sBufDesc, &pDSBuf, NULL);
  243. }
  244. if (FAILED(hr))
  245. {
  246. if (hr == DSERR_BADFORMAT || hr == DSERR_INVALIDPARAM)
  247. {
  248. // Can't do this test because the test sound's format is not
  249. // supported. Skip this test quietly.
  250. goto LEnd;
  251. }
  252. else
  253. {
  254. // Report: Cannot create secondary buffer
  255. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_SECBUF;
  256. pSoundInfo->m_testResultSnd.m_hr = hr;
  257. bRet = FALSE;
  258. goto LEnd;
  259. }
  260. }
  261. }
  262. if (b3D)
  263. {
  264. if (FAILED(hr = pDSBuf->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID*)&pBuf3D)))
  265. {
  266. bRet = FALSE;
  267. goto LEnd;
  268. }
  269. if (FAILED(hr = pBuf3D->SetPosition(D3DVAL(0), D3DVAL(0), D3DVAL(0), DS3D_IMMEDIATE)))
  270. {
  271. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_SETPOS;
  272. pSoundInfo->m_testResultSnd.m_hr = hr;
  273. bRet = FALSE;
  274. goto LEnd;
  275. }
  276. }
  277. // Loop through the formats
  278. // Check caps, and do not play any formats that are not supported.
  279. sWaveFmt.wFormatTag = WAVE_FORMAT_PCM;
  280. // 8 bit mono, 22Khz:
  281. if ((pDSCaps->dwFlags & DSCAPS_PRIMARY8BIT) && (pDSCaps->dwFlags & DSCAPS_PRIMARYMONO))
  282. {
  283. sWaveFmt.wBitsPerSample = 8;
  284. sWaveFmt.nChannels = 1;
  285. sWaveFmt.nSamplesPerSec = 22050;
  286. if (!(pDSCaps->dwFlags & DSCAPS_CONTINUOUSRATE) ||
  287. ((sWaveFmt.nSamplesPerSec > pDSCaps->dwMinSecondarySampleRate) &&
  288. (sWaveFmt.nSamplesPerSec < pDSCaps->dwMaxSecondarySampleRate)))
  289. {
  290. FillFormat(&sWaveFmt);
  291. pPrimBuf->SetFormat(&sWaveFmt);
  292. if (!PlayDSound(hWndMain, pDSCaps, pPrimBuf, pDSBuf,
  293. &sWaveFmt, sBufDesc.dwBufferBytes, pSoundInfo, pWave, bHardware, b3D))
  294. {
  295. bRet = FALSE;
  296. goto LEnd;
  297. }
  298. }
  299. }
  300. // 8 bit stereo, 22Khz:
  301. if ((pDSCaps->dwFlags & DSCAPS_PRIMARY8BIT) && (pDSCaps->dwFlags & DSCAPS_PRIMARYSTEREO))
  302. {
  303. sWaveFmt.wBitsPerSample = 8;
  304. sWaveFmt.nChannels = 2;
  305. sWaveFmt.nSamplesPerSec = 22050;
  306. if (!(pDSCaps->dwFlags & DSCAPS_CONTINUOUSRATE) ||
  307. ((sWaveFmt.nSamplesPerSec > pDSCaps->dwMinSecondarySampleRate) &&
  308. (sWaveFmt.nSamplesPerSec < pDSCaps->dwMaxSecondarySampleRate)))
  309. {
  310. FillFormat(&sWaveFmt);
  311. pPrimBuf->SetFormat(&sWaveFmt);
  312. if (!PlayDSound(hWndMain, pDSCaps, pPrimBuf, pDSBuf,
  313. &sWaveFmt, sBufDesc.dwBufferBytes, pSoundInfo, pWave, bHardware, b3D))
  314. {
  315. bRet = FALSE;
  316. goto LEnd;
  317. }
  318. }
  319. }
  320. // 16 bit mono, 22Khz:
  321. if ((pDSCaps->dwFlags & DSCAPS_PRIMARY16BIT) && (pDSCaps->dwFlags & DSCAPS_PRIMARYMONO))
  322. {
  323. sWaveFmt.wBitsPerSample = 16;
  324. sWaveFmt.nChannels = 1;
  325. sWaveFmt.nSamplesPerSec = 22050;
  326. if (!(pDSCaps->dwFlags & DSCAPS_CONTINUOUSRATE) ||
  327. ((sWaveFmt.nSamplesPerSec > pDSCaps->dwMinSecondarySampleRate) &&
  328. (sWaveFmt.nSamplesPerSec < pDSCaps->dwMaxSecondarySampleRate)))
  329. {
  330. FillFormat(&sWaveFmt);
  331. pPrimBuf->SetFormat(&sWaveFmt);
  332. if (!s_b16BitWarningGiven)
  333. {
  334. WAVEFORMATEX wavefmt;
  335. wavefmt.cbSize = sizeof(wavefmt);
  336. if (SUCCEEDED(pPrimBuf->GetFormat(&wavefmt, sizeof(wavefmt), NULL)) &&
  337. wavefmt.wBitsPerSample != 16)
  338. {
  339. TCHAR szTitle[100];
  340. TCHAR szMessage[500];
  341. LoadString(NULL, IDS_APPFULLNAME, szTitle, 100);
  342. LoadString(NULL, IDS_NO16BITWARNING, szMessage, 500);
  343. MessageBox(hWndMain, szMessage, szTitle, MB_OK);
  344. s_b16BitWarningGiven = TRUE;
  345. }
  346. }
  347. if (!PlayDSound(hWndMain, pDSCaps, pPrimBuf, pDSBuf,
  348. &sWaveFmt, sBufDesc.dwBufferBytes, pSoundInfo, pWave, bHardware, b3D))
  349. {
  350. bRet = FALSE;
  351. goto LEnd;
  352. }
  353. }
  354. }
  355. // 16 bit stereo, 22Khz:
  356. if ((pDSCaps->dwFlags & DSCAPS_PRIMARY16BIT) && (pDSCaps->dwFlags & DSCAPS_PRIMARYSTEREO))
  357. {
  358. sWaveFmt.wBitsPerSample = 16;
  359. sWaveFmt.nChannels = 2;
  360. sWaveFmt.nSamplesPerSec = 22050;
  361. if (!(pDSCaps->dwFlags & DSCAPS_CONTINUOUSRATE) ||
  362. ((sWaveFmt.nSamplesPerSec > pDSCaps->dwMinSecondarySampleRate) &&
  363. (sWaveFmt.nSamplesPerSec < pDSCaps->dwMaxSecondarySampleRate)))
  364. {
  365. FillFormat(&sWaveFmt);
  366. pPrimBuf->SetFormat(&sWaveFmt);
  367. if (!PlayDSound(hWndMain, pDSCaps, pPrimBuf, pDSBuf,
  368. &sWaveFmt, sBufDesc.dwBufferBytes, pSoundInfo, pWave, bHardware, b3D))
  369. {
  370. bRet = FALSE;
  371. goto LEnd;
  372. }
  373. }
  374. }
  375. LEnd:
  376. if (NULL != pPrimBuf)
  377. pPrimBuf->Release();
  378. if (NULL != pBuf3D)
  379. pBuf3D->Release();
  380. if (NULL != pDSBuf)
  381. pDSBuf->Release();
  382. return bRet;
  383. }
  384. /****************************************************************************
  385. *
  386. * PlayDSound
  387. *
  388. ****************************************************************************/
  389. BOOL PlayDSound(HWND hWndMain, DSCAPS* pDSCaps, LPDIRECTSOUNDBUFFER pPrim,
  390. LPDIRECTSOUNDBUFFER pSec, WAVEFORMATEX* pPrimFmt, DWORD dwBufSize,
  391. SoundInfo* pSoundInfo, WAVE* pWave, BOOL bHardware, BOOL b3D)
  392. {
  393. HRESULT hr;
  394. VOID* pData = NULL;
  395. DWORD dwSize;
  396. LPDIRECTSOUNDNOTIFY pDSNot = NULL;
  397. HANDLE hNotEvent = NULL;
  398. DSBPOSITIONNOTIFY sPosNot;
  399. TCHAR szOut[MAX_PATH];
  400. DWORD dwCur = 0;
  401. TCHAR sz[300];
  402. TCHAR szTitle[100];
  403. LoadString(NULL, IDS_APPFULLNAME, szTitle, 100);
  404. if (FAILED(hr = pSec->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNot)))
  405. {
  406. pDSNot = NULL;
  407. }
  408. hNotEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  409. if (NULL == hNotEvent)
  410. {
  411. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_CREATEEVENT;
  412. pSoundInfo->m_testResultSnd.m_hr = S_FALSE;
  413. return FALSE;
  414. }
  415. if (NULL != pDSNot)
  416. {
  417. sPosNot.dwOffset = DSBPN_OFFSETSTOP;
  418. sPosNot.hEventNotify = hNotEvent;
  419. if (FAILED(hr = pDSNot->SetNotificationPositions(1, &sPosNot)))
  420. {
  421. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_SETNOTIF;
  422. pSoundInfo->m_testResultSnd.m_hr = hr;
  423. return FALSE;
  424. }
  425. }
  426. if (FAILED(hr = pSec->Lock(0, dwBufSize, &pData, &dwSize, NULL,
  427. 0, DSBLOCK_ENTIREBUFFER)))
  428. {
  429. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_LOCKFAIL;
  430. pSoundInfo->m_testResultSnd.m_hr = hr;
  431. return FALSE;
  432. }
  433. memcpy(pData, pWave->pData, dwSize);
  434. if (FAILED(hr = pSec->Unlock(pData, dwSize, NULL, 0)))
  435. {
  436. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_UNLOCKFAIL;
  437. pSoundInfo->m_testResultSnd.m_hr = hr;
  438. return FALSE;
  439. }
  440. // Play the buffer
  441. pSec->SetCurrentPosition(0);
  442. if (FAILED(hr = pSec->Play(0, 0, 0)))
  443. {
  444. pSoundInfo->m_testResultSnd.m_iStepThatFailed = TESTID_PLAY;
  445. pSoundInfo->m_testResultSnd.m_hr = hr;
  446. return FALSE;
  447. }
  448. WaitForSingleObject(hNotEvent, (pWave->dwSize * 1000 / pWave->psHeader->nAvgBytesPerSec));
  449. pSec->Stop();
  450. CloseHandle(hNotEvent);
  451. if (NULL != pDSNot)
  452. pDSNot->Release();
  453. TCHAR sz3D[50];
  454. TCHAR szChannelDesc[50];
  455. TCHAR szHWSW[50];
  456. LoadString(NULL, IDS_THATSOUNDWAS, sz, 300);
  457. if (b3D)
  458. {
  459. LoadString(NULL, IDS_3D, sz3D, 50);
  460. lstrcat(sz3D, TEXT(" "));
  461. }
  462. else
  463. {
  464. lstrcpy(sz3D, TEXT(""));
  465. }
  466. if (pPrimFmt->nChannels == 1)
  467. LoadString(NULL, IDS_MONO, szChannelDesc, 50);
  468. else if (pPrimFmt->nChannels == 2)
  469. LoadString(NULL, IDS_STEREO, szChannelDesc, 50);
  470. else
  471. LoadString(NULL, IDS_MULTICHANNEL, szChannelDesc, 50);
  472. if (bHardware)
  473. LoadString(NULL, IDS_HARDWARE, szHWSW, 50);
  474. else
  475. LoadString(NULL, IDS_SOFTWARE, szHWSW, 50);
  476. wsprintf(szOut, sz, sz3D, szChannelDesc, pPrimFmt->wBitsPerSample,
  477. pPrimFmt->nSamplesPerSec / 1000, szHWSW);
  478. INT iReply;
  479. iReply = MessageBox(hWndMain, szOut, szTitle, MB_YESNOCANCEL);
  480. if (IDYES == iReply)
  481. {
  482. return TRUE;
  483. }
  484. else if (IDNO == iReply)
  485. {
  486. pSoundInfo->m_testResultSnd.m_iStepThatFailed = (TRUE == bHardware) ?
  487. TESTID_USER_VERIFY_HARDWARE : TESTID_USER_VERIFY_SOFTWARE;
  488. pSoundInfo->m_testResultSnd.m_hr = hr;
  489. return FALSE;
  490. }
  491. else // IDCANCEL
  492. {
  493. pSoundInfo->m_testResultSnd.m_bCancelled = TRUE;
  494. return FALSE;
  495. }
  496. }
  497. /****************************************************************************
  498. *
  499. * LoadTestData
  500. *
  501. ****************************************************************************/
  502. BOOL LoadTestData(WAVE* pWave)
  503. {
  504. DWORD dwRiff;
  505. DWORD dwType;
  506. DWORD dwLength;
  507. HRSRC hResInfo = NULL;
  508. HGLOBAL hResData = NULL;
  509. DWORD* pdw = NULL;
  510. DWORD* pdwEnd = NULL;
  511. VOID* pData = NULL;
  512. WAVEFORMATEX** ppWaveHeader = &pWave->psHeader;
  513. LPBYTE* ppbWaveData = &pWave->pData;
  514. DWORD* pcbWaveSize = &pWave->dwSize;
  515. if (NULL == pWave)
  516. return FALSE;
  517. if (NULL == (hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_WAVTST), TEXT("WAVE"))))
  518. return FALSE;
  519. if (NULL == (hResData = LoadResource(NULL, hResInfo)))
  520. return FALSE;
  521. if (NULL == (pData = LockResource(hResData)))
  522. return FALSE;
  523. pWave->psHeader = NULL;
  524. pWave->pData = NULL;
  525. pWave->dwSize = 0;
  526. pdw = (DWORD *)pData;
  527. dwRiff = *pdw++;
  528. dwLength = *pdw++;
  529. dwType = *pdw++;
  530. if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  531. return FALSE;
  532. if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
  533. return FALSE;
  534. pdwEnd = (DWORD*)((BYTE*)pdw + dwLength - 4);
  535. while (pdw < pdwEnd)
  536. {
  537. dwType = *pdw++;
  538. dwLength = *pdw++;
  539. switch (dwType)
  540. {
  541. case mmioFOURCC('f', 'm', 't', ' '):
  542. if (ppWaveHeader && !*ppWaveHeader)
  543. {
  544. if (dwLength < sizeof(WAVEFORMAT))
  545. return FALSE;
  546. *ppWaveHeader = (WAVEFORMATEX*)pdw;
  547. if ((!ppbWaveData || *ppbWaveData) && (!pcbWaveSize || *pcbWaveSize))
  548. return TRUE;
  549. }
  550. break;
  551. case mmioFOURCC('d', 'a', 't', 'a'):
  552. if ((ppbWaveData && !*ppbWaveData) || (pcbWaveSize && !*pcbWaveSize))
  553. {
  554. if (ppbWaveData)
  555. *ppbWaveData = (LPBYTE)pdw;
  556. if (pcbWaveSize)
  557. *pcbWaveSize = dwLength;
  558. if (!ppWaveHeader || *ppWaveHeader)
  559. return TRUE;
  560. }
  561. break;
  562. }
  563. pdw = (DWORD*)((BYTE*)pdw + ((dwLength + 1) & ~1));
  564. }
  565. return FALSE;
  566. }
  567. /****************************************************************************
  568. *
  569. * FillFormat
  570. *
  571. ****************************************************************************/
  572. VOID FillFormat(WAVEFORMATEX* pWFM)
  573. {
  574. pWFM->nBlockAlign = (pWFM->nChannels * pWFM->wBitsPerSample) / 8;
  575. pWFM->nAvgBytesPerSec = pWFM->nSamplesPerSec * pWFM->nBlockAlign;
  576. }
  577. /****************************************************************************
  578. *
  579. * TestDSTerm
  580. *
  581. ****************************************************************************/
  582. VOID TestDSTerm(LPDIRECTSOUND* ppDS, HINSTANCE* phInstDS, SoundInfo* pSoundInfo)
  583. {
  584. if (NULL != *ppDS)
  585. {
  586. (*ppDS)->Release();
  587. *ppDS = NULL;
  588. }
  589. if (NULL != *phInstDS)
  590. FreeLibrary(*phInstDS);
  591. }
  592. /****************************************************************************
  593. *
  594. * TestDSReport
  595. *
  596. ****************************************************************************/
  597. VOID TestDSReport(SoundInfo* pSoundInfo)
  598. {
  599. if (pSoundInfo->m_testResultSnd.m_bCancelled)
  600. {
  601. LoadString(NULL, IDS_TESTSCANCELLED, pSoundInfo->m_testResultSnd.m_szDescription, 300);
  602. LoadString(NULL, IDS_TESTSCANCELLED_ENGLISH, pSoundInfo->m_testResultSnd.m_szDescriptionEnglish, 300);
  603. }
  604. else
  605. {
  606. if (pSoundInfo->m_testResultSnd.m_iStepThatFailed == 0)
  607. {
  608. LoadString(NULL, IDS_TESTSSUCCESSFUL, pSoundInfo->m_testResultSnd.m_szDescription, 300);
  609. LoadString(NULL, IDS_TESTSSUCCESSFUL_ENGLISH, pSoundInfo->m_testResultSnd.m_szDescriptionEnglish, 300);
  610. }
  611. else
  612. {
  613. TCHAR szDesc[200];
  614. TCHAR szError[200];
  615. TCHAR sz[300];
  616. if (0 == LoadString(NULL, IDS_FIRSTDSOUNDTESTERROR + pSoundInfo->m_testResultSnd.m_iStepThatFailed - 1,
  617. szDesc, 200))
  618. {
  619. LoadString(NULL, IDS_UNKNOWNERROR, szDesc, 200);
  620. }
  621. LoadString(NULL, IDS_FAILUREFMT, sz, 300);
  622. BTranslateError(pSoundInfo->m_testResultSnd.m_hr, szError);
  623. wsprintf(pSoundInfo->m_testResultSnd.m_szDescription, sz,
  624. pSoundInfo->m_testResultSnd.m_iStepThatFailed,
  625. szDesc, pSoundInfo->m_testResultSnd.m_hr, szError);
  626. // Nonlocalized version:
  627. if (0 == LoadString(NULL, IDS_FIRSTDSOUNDTESTERROR_ENGLISH + pSoundInfo->m_testResultSnd.m_iStepThatFailed - 1,
  628. szDesc, 200))
  629. {
  630. LoadString(NULL, IDS_UNKNOWNERROR_ENGLISH, szDesc, 200);
  631. }
  632. LoadString(NULL, IDS_FAILUREFMT_ENGLISH, sz, 300);
  633. BTranslateError(pSoundInfo->m_testResultSnd.m_hr, szError, TRUE);
  634. wsprintf(pSoundInfo->m_testResultSnd.m_szDescriptionEnglish, sz,
  635. pSoundInfo->m_testResultSnd.m_iStepThatFailed,
  636. szDesc, pSoundInfo->m_testResultSnd.m_hr, szError);
  637. }
  638. }
  639. }