home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Demos / DuelVoice / dsutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  14.1 KB  |  513 lines

  1. //-----------------------------------------------------------------------------
  2. // File: dsutil.cpp
  3. //
  4. // Desc: Routines for dealing with sounds from resources
  5. //
  6. // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #include <windows.h>
  9. #include <mmsystem.h>
  10. #include <dsound.h>
  11. #include "dsutil.h"
  12.  
  13.  
  14. //-----------------------------------------------------------------------------
  15. // Defines, constants, and global variables
  16. //-----------------------------------------------------------------------------
  17. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  18. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  19.  
  20. LPDIRECTSOUND           g_pDS = NULL;
  21. LPDIRECTSOUND3DLISTENER g_pDSListener = NULL;
  22.  
  23.  
  24.  
  25.  
  26. //-----------------------------------------------------------------------------
  27. // Name: DSUtil_LoadSoundBuffer()
  28. // Desc:
  29. //-----------------------------------------------------------------------------
  30. LPDIRECTSOUNDBUFFER DSUtil_LoadSoundBuffer( LPDIRECTSOUND pDS, LPCTSTR strName )
  31. {
  32.     LPDIRECTSOUNDBUFFER pDSB = NULL;
  33.     DSBUFFERDESC        dsbd;
  34.     BYTE*               pbWaveData;
  35.  
  36.     ZeroMemory( &dsbd, sizeof(dsbd) );
  37.     dsbd.dwSize  = sizeof(dsbd);
  38.     dsbd.dwFlags = DSBCAPS_STATIC|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|
  39.                    DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPOSITIONNOTIFY;
  40.  
  41.     if( SUCCEEDED( DSUtil_GetWaveResource( NULL, strName, &dsbd.lpwfxFormat,
  42.                                            &pbWaveData, &dsbd.dwBufferBytes ) ) )
  43.     {
  44.  
  45.         if( SUCCEEDED( pDS->CreateSoundBuffer( &dsbd, &pDSB, NULL ) ) )
  46.         {
  47.             if( FAILED( DSUtil_FillSoundBuffer( pDSB, pbWaveData,
  48.                                                 dsbd.dwBufferBytes ) ) )
  49.             {
  50.                 pDSB->Release();
  51.                 pDSB = NULL;
  52.             }
  53.         }
  54.         else
  55.         {
  56.             pDSB = NULL;
  57.         }
  58.     }
  59.  
  60.     return pDSB;
  61. }
  62.  
  63.  
  64.  
  65.  
  66. //-----------------------------------------------------------------------------
  67. // Name: DSUtil_ReloadSoundBuffer()
  68. // Desc: 
  69. //-----------------------------------------------------------------------------
  70. HRESULT DSUtil_ReloadSoundBuffer( LPDIRECTSOUNDBUFFER pDSB, LPCTSTR strName )
  71. {
  72.     BYTE* pbWaveData;
  73.     DWORD cbWaveSize;
  74.  
  75.     if( FAILED( DSUtil_GetWaveResource( NULL, strName, NULL, &pbWaveData,
  76.                                         &cbWaveSize ) ) )
  77.         return E_FAIL;
  78.  
  79.     if( FAILED( pDSB->Restore() ) )
  80.         return E_FAIL;
  81.  
  82.     if( FAILED( DSUtil_FillSoundBuffer( pDSB, pbWaveData, cbWaveSize ) ) )
  83.         return E_FAIL;
  84.  
  85.     return S_OK;
  86. }
  87.  
  88.  
  89.  
  90.  
  91. //-----------------------------------------------------------------------------
  92. // Name: 
  93. // Desc: 
  94. //-----------------------------------------------------------------------------
  95. HRESULT DSUtil_GetWaveResource( HMODULE hModule, LPCTSTR strName,
  96.                                 WAVEFORMATEX** ppWaveHeader, BYTE** ppbWaveData,
  97.                                 DWORD* pcbWaveSize )
  98. {
  99.     HRSRC   hResInfo;
  100.     HGLOBAL hResData;
  101.     VOID*   pvRes;
  102.  
  103.     if( NULL == ( hResInfo = FindResource( hModule, strName, TEXT("WAVE") ) ) )
  104.     {
  105.         if( NULL == ( hResInfo = FindResource( hModule, strName, TEXT("WAV") ) ) )
  106.             return E_FAIL;
  107.     }
  108.  
  109.     if( NULL == ( hResData = LoadResource( hModule, hResInfo ) ) )
  110.         return E_FAIL;
  111.  
  112.     if( NULL == ( pvRes = LockResource( hResData ) ) )
  113.         return E_FAIL;
  114.  
  115.     if( FAILED( DSUtil_ParseWaveResource( pvRes, ppWaveHeader, ppbWaveData,
  116.                                           pcbWaveSize ) ) )
  117.         return E_FAIL;
  118.  
  119.     return S_OK;
  120. }
  121.  
  122.  
  123.  
  124.  
  125. //-----------------------------------------------------------------------------
  126. // Name: 
  127. // Desc: 
  128. //-----------------------------------------------------------------------------
  129. SoundObject* DSUtil_CreateSound( LPCTSTR strName, DWORD dwNumConcurrentBuffers )
  130. {
  131.     SoundObject*   pSound = NULL;
  132.     LPWAVEFORMATEX pWaveHeader;
  133.     BYTE*          pbData;
  134.     DWORD          cbData;
  135.  
  136.     if( NULL == g_pDS )
  137.         return NULL;
  138.  
  139.     if( dwNumConcurrentBuffers < 1 )
  140.         dwNumConcurrentBuffers = 1;
  141.  
  142.     if( SUCCEEDED( DSUtil_GetWaveResource( NULL, strName, &pWaveHeader,
  143.                                            &pbData, &cbData ) ) )
  144.     {
  145.         pSound = new SoundObject;
  146.         pSound->dwNumBuffers = dwNumConcurrentBuffers;
  147.         pSound->pbWaveData   = pbData;
  148.         pSound->cbWaveSize   = cbData;
  149.         pSound->dwCurrent    = 0;
  150.         pSound->pdsbBuffers  = new LPDIRECTSOUNDBUFFER[dwNumConcurrentBuffers+1];
  151.  
  152.         pSound->pdsbBuffers[0] = DSUtil_LoadSoundBuffer( g_pDS, strName );
  153.  
  154.         for( DWORD i=1; i<pSound->dwNumBuffers; i++ )
  155.         {
  156.             if( FAILED( g_pDS->DuplicateSoundBuffer( pSound->pdsbBuffers[0],
  157.                                                    &pSound->pdsbBuffers[i] ) ) )
  158.             {
  159.                 pSound->pdsbBuffers[i] = DSUtil_LoadSoundBuffer( g_pDS, strName );
  160.                 if( NULL == pSound->pdsbBuffers[i] )
  161.                 {
  162.                     DSUtil_DestroySound( pSound );
  163.                     pSound = NULL;
  164.                     break;
  165.                 }
  166.             }
  167.         }
  168.     }
  169.  
  170.     return pSound;
  171. }
  172.  
  173.  
  174.  
  175.  
  176. //-----------------------------------------------------------------------------
  177. // Name: DSUtil_DestroySound()
  178. // Desc: 
  179. //-----------------------------------------------------------------------------
  180. VOID DSUtil_DestroySound( SoundObject* pSound )
  181. {
  182.     if( pSound )
  183.     {
  184.         for( DWORD i=0; i<pSound->dwNumBuffers; i++ )
  185.         {
  186.             if( pSound->pdsbBuffers[i] )
  187.                 pSound->pdsbBuffers[i]->Release();
  188.         }
  189.         
  190.         delete pSound->pdsbBuffers;
  191.         delete pSound;
  192.     }
  193. }
  194.  
  195.  
  196.  
  197.  
  198. //-----------------------------------------------------------------------------
  199. // Name: 
  200. // Desc: 
  201. //-----------------------------------------------------------------------------
  202. LPDIRECTSOUNDBUFFER DSUtil_GetFreeSoundBuffer( SoundObject* pSound )
  203. {
  204.     HRESULT hr;
  205.     DWORD   dwStatus;
  206.  
  207.     if( NULL == pSound )
  208.         return NULL;
  209.  
  210.     LPDIRECTSOUNDBUFFER pDSB = pSound->pdsbBuffers[pSound->dwCurrent];
  211.     if( NULL == pDSB )
  212.         return NULL;
  213.  
  214.     hr = pDSB->GetStatus( &dwStatus );
  215.     if( FAILED(hr) )
  216.         dwStatus = 0;
  217.  
  218.     if( dwStatus & DSBSTATUS_PLAYING )
  219.     {
  220.         if( pSound->dwNumBuffers <= 1 )
  221.             return NULL;
  222.  
  223.         if( ++pSound->dwCurrent >= pSound->dwNumBuffers )
  224.             pSound->dwCurrent = 0;
  225.  
  226.         pDSB = pSound->pdsbBuffers[pSound->dwCurrent];
  227.         
  228.         hr = pDSB->GetStatus( &dwStatus);
  229.         if( FAILED(hr) )
  230.             dwStatus = 0;
  231.  
  232.         if( dwStatus & DSBSTATUS_PLAYING )
  233.         {
  234.             pDSB->Stop();
  235.             pDSB->SetCurrentPosition( 0 );
  236.         }
  237.     }
  238.  
  239.     if( dwStatus & DSBSTATUS_BUFFERLOST )
  240.     {
  241.         if( FAILED( pDSB->Restore() ) )
  242.             return NULL;
  243.             
  244.         if( FAILED( DSUtil_FillSoundBuffer( pDSB, pSound->pbWaveData,
  245.                                             pSound->cbWaveSize ) ) )
  246.             return NULL;
  247.     }
  248.  
  249.     return pDSB;
  250. }
  251.  
  252.  
  253.  
  254.  
  255. //-----------------------------------------------------------------------------
  256. // Name: DSUtil_PlaySound()
  257. // Desc: 
  258. //-----------------------------------------------------------------------------
  259. HRESULT DSUtil_PlaySound( SoundObject* pSound, DWORD dwPlayFlags )
  260. {
  261.     if( NULL == pSound )
  262.         return E_FAIL;
  263.  
  264.     if( !(dwPlayFlags & DSBPLAY_LOOPING) || (pSound->dwNumBuffers == 1) )
  265.     {
  266.         LPDIRECTSOUNDBUFFER pDSB = DSUtil_GetFreeSoundBuffer( pSound );
  267.         if( pDSB )
  268.         {
  269.             if( SUCCEEDED( pDSB->Play( 0, 0, dwPlayFlags ) ) )
  270.                 return S_OK;
  271.         }
  272.     }
  273.  
  274.     return E_FAIL;
  275. }
  276.  
  277.  
  278.  
  279.  
  280. //-----------------------------------------------------------------------------
  281. // Name: DSUtil_StopSound()
  282. // Desc: 
  283. //-----------------------------------------------------------------------------
  284. HRESULT DSUtil_StopSound( SoundObject* pSound )
  285. {
  286.     if( NULL == pSound )
  287.         return E_FAIL;
  288.  
  289.     for( DWORD i=0; i<pSound->dwNumBuffers; i++ )
  290.     {
  291.         pSound->pdsbBuffers[i]->Stop();
  292.         pSound->pdsbBuffers[i]->SetCurrentPosition( 0 );
  293.     }
  294.  
  295.     return S_OK;
  296. }
  297.  
  298.  
  299.  
  300.  
  301. //-----------------------------------------------------------------------------
  302. // Name: 
  303. // Desc: 
  304. //-----------------------------------------------------------------------------
  305. HRESULT DSUtil_FillSoundBuffer( LPDIRECTSOUNDBUFFER pDSB, BYTE* pbWaveData,
  306.                                 DWORD dwWaveSize )
  307. {
  308.     VOID* pMem1;
  309.     VOID* pMem2;
  310.     DWORD dwSize1;
  311.     DWORD dwSize2;
  312.  
  313.     if( NULL == pDSB || NULL == pbWaveData || 0 == dwWaveSize )
  314.         return E_FAIL;
  315.  
  316.     if( FAILED( pDSB->Lock( 0, dwWaveSize, &pMem1, &dwSize1, &pMem2,
  317.                             &dwSize2, 0 ) ) )
  318.         return E_FAIL;
  319.  
  320.     if( 0 != dwSize1 ) CopyMemory( pMem1, pbWaveData, dwSize1 );
  321.     if( 0 != dwSize2 ) CopyMemory( pMem2, pbWaveData+dwSize1, dwSize2 );
  322.  
  323.     pDSB->Unlock( pMem1, dwSize1, pMem2, dwSize2);
  324.  
  325.     return S_OK;
  326. }
  327.  
  328.  
  329.  
  330.  
  331. //-----------------------------------------------------------------------------
  332. // Name: 
  333. // Desc: 
  334. //-----------------------------------------------------------------------------
  335. HRESULT DSUtil_ParseWaveResource( VOID* pvRes, WAVEFORMATEX** ppWaveHeader,
  336.                                   BYTE** ppbWaveData, DWORD* pcbWaveSize )
  337. {
  338.     DWORD* pdw;
  339.     DWORD* pdwEnd;
  340.     DWORD  dwRiff;
  341.     DWORD  dwType;
  342.     DWORD  dwLength;
  343.  
  344.     if( ppWaveHeader )
  345.         *ppWaveHeader = NULL;
  346.  
  347.     if( ppbWaveData )
  348.         *ppbWaveData = NULL;
  349.  
  350.     if( pcbWaveSize )
  351.         *pcbWaveSize = 0;
  352.  
  353.     pdw      = (DWORD*)pvRes;
  354.     dwRiff   = *pdw++;
  355.     dwLength = *pdw++;
  356.     dwType   = *pdw++;
  357.  
  358.     if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )
  359.         return E_FAIL;
  360.  
  361.     if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )
  362.         return E_FAIL;
  363.  
  364.     pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  365.  
  366.     while( pdw < pdwEnd )
  367.     {
  368.         dwType   = *pdw++;
  369.         dwLength = *pdw++;
  370.  
  371.         if( dwType == mmioFOURCC('f', 'm', 't', ' ') )
  372.         {
  373.             if (ppWaveHeader && !*ppWaveHeader)
  374.             {
  375.                 if( dwLength < sizeof(WAVEFORMAT) )
  376.                     return E_FAIL;
  377.  
  378.                 *ppWaveHeader = (WAVEFORMATEX*)pdw;
  379.  
  380.                 if( (!ppbWaveData || *ppbWaveData) &&
  381.                     (!pcbWaveSize || *pcbWaveSize) )
  382.                 {
  383.                     return S_OK;
  384.                 }
  385.             }
  386.         }
  387.  
  388.         if( dwType == mmioFOURCC('d', 'a', 't', 'a') )
  389.         {
  390.             if( (ppbWaveData && !*ppbWaveData) ||
  391.                 (pcbWaveSize && !*pcbWaveSize) )
  392.             {
  393.                 if( ppbWaveData )
  394.                     *ppbWaveData = (BYTE*)pdw;
  395.  
  396.                 if( pcbWaveSize )
  397.                     *pcbWaveSize = dwLength;
  398.  
  399.                 if( !ppWaveHeader || *ppWaveHeader )
  400.                     return S_OK;
  401.             }
  402.         }
  403.  
  404.         pdw = (DWORD*)( (BYTE*)pdw + ((dwLength+1)&~1) );
  405.     }
  406.  
  407.     return E_FAIL;
  408. }
  409.  
  410.  
  411.  
  412.  
  413.  
  414. //-----------------------------------------------------------------------------
  415. // Name: DSUtil_PlayPannedSound()
  416. // Desc: Play a sound, but first set the panning according to where the
  417. //       object is on the screen. fScreenXPos is between -1.0f (left) and
  418. //       1.0f (right).
  419. //-----------------------------------------------------------------------------
  420. VOID DSUtil_PlayPannedSound( SoundObject* pSound, FLOAT fScreenXPos )
  421. {
  422.     LPDIRECTSOUNDBUFFER pDSB = DSUtil_GetFreeSoundBuffer( pSound );
  423.  
  424.     if( pDSB )
  425.     {
  426.         pDSB->SetPan( (LONG)( 10000L * fScreenXPos ) );
  427.         pDSB->Play( 0, 0, 0 );
  428.     }
  429. }
  430.  
  431.  
  432.  
  433.  
  434. //-----------------------------------------------------------------------------
  435. // Name: DSUtil_InitDirectSound()
  436. // Desc: 
  437. //-----------------------------------------------------------------------------
  438. HRESULT DSUtil_InitDirectSound( HWND hWnd )
  439. {
  440.     if( FAILED( DirectSoundCreate( NULL, &g_pDS, NULL ) ) )
  441.         return E_FAIL;
  442.  
  443.     if( FAILED( g_pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) )
  444.     {
  445.         g_pDS->Release();
  446.         g_pDS = NULL;
  447.         return E_FAIL;
  448.     }
  449.  
  450.     HRESULT             hr;
  451.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  452.  
  453.     // Get the primary buffer 
  454.     DSBUFFERDESC dsbd;
  455.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  456.     dsbd.dwSize        = sizeof(DSBUFFERDESC);
  457.     dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
  458.     dsbd.dwBufferBytes = 0;
  459.     dsbd.lpwfxFormat   = NULL;
  460.        
  461.     if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
  462.         return hr;
  463.  
  464.     WAVEFORMATEX wfx;
  465.     ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
  466.     wfx.wFormatTag      = WAVE_FORMAT_PCM; 
  467.     wfx.nChannels       = 2; 
  468.     wfx.nSamplesPerSec  = 22050; 
  469.     wfx.wBitsPerSample  = 16; 
  470.     wfx.nBlockAlign     = wfx.wBitsPerSample / 8 * wfx.nChannels;
  471.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  472.  
  473.     if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) )
  474.         return hr;
  475.  
  476.     if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, 
  477.                                                   (VOID**)&g_pDSListener ) ) )
  478.         return hr;
  479.  
  480.     SAFE_RELEASE( pDSBPrimary );
  481.  
  482.     if( FAILED( hr = g_pDSListener->SetPosition( 0.f, 0.f, -1.f, DS3D_DEFERRED ) ) )
  483.         return hr;
  484.  
  485.     if( FAILED( hr = g_pDSListener->SetDopplerFactor( 9.9f ,DS3D_DEFERRED ) ) )
  486.         return hr;
  487.  
  488.     if( FAILED( hr = g_pDSListener->SetRolloffFactor( 0.25f ,DS3D_DEFERRED ) ) )
  489.         return hr;
  490.  
  491.     if( FAILED( hr = g_pDSListener->CommitDeferredSettings() ) ) 
  492.         return hr;
  493.  
  494.     return S_OK;
  495. }
  496.  
  497.  
  498.  
  499.  
  500. //-----------------------------------------------------------------------------
  501. // Name: DSUtil_FreeDirectSound()
  502. // Desc: 
  503. //-----------------------------------------------------------------------------
  504. VOID DSUtil_FreeDirectSound()
  505. {
  506.     SAFE_RELEASE( g_pDSListener );
  507.     SAFE_RELEASE( g_pDS );
  508. }
  509.  
  510.  
  511.  
  512.  
  513.