home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / misc / dsutil.c < prev    next >
C/C++ Source or Header  |  1997-07-14  |  10KB  |  379 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       dsutil.cpp
  6.  *  Content:    Routines for dealing with sounds from resources
  7.  *
  8.  *
  9.  ***************************************************************************/
  10.  
  11. #define WIN32_LEAN_AND_MEAN
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include <mmsystem.h>
  15. #include <dsound.h>
  16.  
  17. typedef struct
  18. {
  19.     BYTE *pbWaveData;               // pointer into wave resource (for restore)
  20.     DWORD cbWaveSize;               // size of wave data (for restore)
  21.     int iAlloc;                     // number of buffers.
  22.     int iCurrent;                   // current buffer
  23.     IDirectSoundBuffer* Buffers[1]; // list of buffers
  24.  
  25. } SNDOBJ, *HSNDOBJ;
  26.  
  27. #define _HSNDOBJ_DEFINED
  28. #include "dsutil.h"
  29.  
  30. static const char c_szWAV[] = "WAV";
  31.  
  32. ///////////////////////////////////////////////////////////////////////////////
  33. //
  34. // DSLoadSoundBuffer
  35. //
  36. ///////////////////////////////////////////////////////////////////////////////
  37.  
  38. IDirectSoundBuffer *DSLoadSoundBuffer(IDirectSound *pDS, LPCTSTR lpName)
  39. {
  40.     IDirectSoundBuffer *pDSB = NULL;
  41.     DSBUFFERDESC dsBD = {0};
  42.     BYTE *pbWaveData;
  43.  
  44.     if (DSGetWaveResource(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData, &dsBD.dwBufferBytes))
  45.     {
  46.         dsBD.dwSize = sizeof(dsBD);
  47.         dsBD.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
  48.  
  49.         if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
  50.         {
  51.             if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
  52.             {
  53.                 IDirectSoundBuffer_Release(pDSB);
  54.                 pDSB = NULL;
  55.             }
  56.         }
  57.         else
  58.         {
  59.             pDSB = NULL;
  60.         }
  61.     }
  62.  
  63.     return pDSB;
  64. }
  65.  
  66. ///////////////////////////////////////////////////////////////////////////////
  67. //
  68. // DSReloadSoundBuffer
  69. //
  70. ///////////////////////////////////////////////////////////////////////////////
  71.  
  72. BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, LPCTSTR lpName)
  73. {
  74.     BOOL result=FALSE;
  75.     BYTE *pbWaveData;
  76.     DWORD cbWaveSize;
  77.  
  78.     if (DSGetWaveResource(NULL, lpName, NULL, &pbWaveData, &cbWaveSize))
  79.     {
  80.         if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
  81.             DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
  82.     {
  83.         result = TRUE;
  84.         }
  85.     }
  86.  
  87.     return result;
  88. }
  89.  
  90. ///////////////////////////////////////////////////////////////////////////////
  91. //
  92. // DSGetWaveResource
  93. //
  94. ///////////////////////////////////////////////////////////////////////////////
  95.  
  96. BOOL DSGetWaveResource(HMODULE hModule, LPCTSTR lpName,
  97.     WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pcbWaveSize)
  98. {
  99.     HRSRC hResInfo;
  100.     HGLOBAL hResData;
  101.     void *pvRes;
  102.  
  103.     if (((hResInfo = FindResource(hModule, lpName, c_szWAV)) != NULL) &&
  104.         ((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
  105.         ((pvRes = LockResource(hResData)) != NULL) &&
  106.         DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize))
  107.     {
  108.         return TRUE;
  109.     }
  110.  
  111.     return FALSE;
  112. }
  113.  
  114. ///////////////////////////////////////////////////////////////////////////////
  115. // SndObj fns
  116. ///////////////////////////////////////////////////////////////////////////////
  117.  
  118. SNDOBJ *SndObjCreate(IDirectSound *pDS, LPCTSTR lpName, int iConcurrent)
  119. {
  120.     SNDOBJ *pSO = NULL;
  121.     LPWAVEFORMATEX pWaveHeader;
  122.     BYTE *pbData;
  123.     UINT cbData;
  124.  
  125.     if (DSGetWaveResource(NULL, lpName, &pWaveHeader, &pbData, &cbData))
  126.     {
  127.         if (iConcurrent < 1)
  128.             iConcurrent = 1;
  129.  
  130.         if ((pSO = (SNDOBJ *)LocalAlloc(LPTR, sizeof(SNDOBJ) +
  131.         (iConcurrent-1) * sizeof(IDirectSoundBuffer *))) != NULL)
  132.         {
  133.             int i;
  134.  
  135.             pSO->iAlloc = iConcurrent;
  136.             pSO->pbWaveData = pbData;
  137.             pSO->cbWaveSize = cbData;
  138.             pSO->Buffers[0] = DSLoadSoundBuffer(pDS, lpName);
  139.  
  140.         for (i=1; i<pSO->iAlloc; i++)
  141.         {
  142.         if (FAILED(IDirectSound_DuplicateSoundBuffer(pDS,
  143.                     pSO->Buffers[0], &pSO->Buffers[i])))
  144.                 {
  145.             pSO->Buffers[i] = DSLoadSoundBuffer(pDS, lpName);
  146.             if (!pSO->Buffers[i]) {
  147.             SndObjDestroy(pSO);
  148.             pSO = NULL;
  149.             break;
  150.             }
  151.         }
  152.             }
  153.         }
  154.     }
  155.  
  156.     return pSO;
  157. }
  158.  
  159. ///////////////////////////////////////////////////////////////////////////////
  160. ///////////////////////////////////////////////////////////////////////////////
  161.  
  162. void SndObjDestroy(SNDOBJ *pSO)
  163. {
  164.     if (pSO)
  165.     {
  166.         int i;
  167.  
  168.         for (i=0; i<pSO->iAlloc; i++)
  169.         {
  170.             if (pSO->Buffers[i])
  171.             {
  172.                 IDirectSoundBuffer_Release(pSO->Buffers[i]);
  173.                 pSO->Buffers[i] = NULL;
  174.             }
  175.         }
  176.         LocalFree((HANDLE)pSO);
  177.     }
  178. }
  179.  
  180. ///////////////////////////////////////////////////////////////////////////////
  181. ///////////////////////////////////////////////////////////////////////////////
  182.  
  183. IDirectSoundBuffer *SndObjGetFreeBuffer(SNDOBJ *pSO)
  184. {
  185.     IDirectSoundBuffer *pDSB;
  186.  
  187.     if (pSO == NULL)
  188.         return NULL;
  189.  
  190.     if (pDSB = pSO->Buffers[pSO->iCurrent])
  191.     {
  192.         HRESULT hres;
  193.         DWORD dwStatus;
  194.  
  195.         hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);
  196.  
  197.         if (FAILED(hres))
  198.             dwStatus = 0;
  199.  
  200.         if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  201.         {
  202.             if (pSO->iAlloc > 1)
  203.             {
  204.                 if (++pSO->iCurrent >= pSO->iAlloc)
  205.                     pSO->iCurrent = 0;
  206.  
  207.                 pDSB = pSO->Buffers[pSO->iCurrent];
  208.                 hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);
  209.  
  210.                 if (SUCCEEDED(hres) && (dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  211.                 {
  212.                     IDirectSoundBuffer_Stop(pDSB);
  213.                     IDirectSoundBuffer_SetCurrentPosition(pDSB, 0);
  214.                 }
  215.             }
  216.             else
  217.             {
  218.                 pDSB = NULL;
  219.             }
  220.         }
  221.  
  222.         if (pDSB && (dwStatus & DSBSTATUS_BUFFERLOST))
  223.         {
  224.             if (FAILED(IDirectSoundBuffer_Restore(pDSB)) ||
  225.                 !DSFillSoundBuffer(pDSB, pSO->pbWaveData, pSO->cbWaveSize))
  226.             {
  227.                 pDSB = NULL;
  228.             }
  229.         }
  230.     }
  231.  
  232.     return pDSB;
  233. }
  234.  
  235. ///////////////////////////////////////////////////////////////////////////////
  236. ///////////////////////////////////////////////////////////////////////////////
  237.  
  238. BOOL SndObjPlay(SNDOBJ *pSO, DWORD dwPlayFlags)
  239. {
  240.     BOOL result = FALSE;
  241.  
  242.     if (pSO == NULL)
  243.         return FALSE;
  244.  
  245.     if ((!(dwPlayFlags & DSBPLAY_LOOPING) || (pSO->iAlloc == 1)))
  246.     {
  247.     IDirectSoundBuffer *pDSB = SndObjGetFreeBuffer(pSO);
  248.     if (pDSB != NULL) {
  249.         result = SUCCEEDED(IDirectSoundBuffer_Play(pDSB, 0, 0, dwPlayFlags));
  250.     }
  251.     }
  252.  
  253.     return result;
  254. }
  255.  
  256. ///////////////////////////////////////////////////////////////////////////////
  257. ///////////////////////////////////////////////////////////////////////////////
  258.  
  259. BOOL SndObjStop(SNDOBJ *pSO)
  260. {
  261.     int i;
  262.  
  263.     if (pSO == NULL)
  264.         return FALSE;
  265.  
  266.     for (i=0; i<pSO->iAlloc; i++)
  267.     {
  268.         IDirectSoundBuffer_Stop(pSO->Buffers[i]);
  269.         IDirectSoundBuffer_SetCurrentPosition(pSO->Buffers[i], 0);
  270.     }
  271.  
  272.     return TRUE;
  273. }
  274.  
  275. ///////////////////////////////////////////////////////////////////////////////
  276. ///////////////////////////////////////////////////////////////////////////////
  277.  
  278. BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD cbWaveSize)
  279. {
  280.     if (pDSB && pbWaveData && cbWaveSize)
  281.     {
  282.         LPVOID pMem1, pMem2;
  283.         DWORD dwSize1, dwSize2;
  284.  
  285.         if (SUCCEEDED(IDirectSoundBuffer_Lock(pDSB, 0, cbWaveSize,
  286.             &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))
  287.         {
  288.             CopyMemory(pMem1, pbWaveData, dwSize1);
  289.  
  290.             if ( 0 != dwSize2 )
  291.                 CopyMemory(pMem2, pbWaveData+dwSize1, dwSize2);
  292.  
  293.             IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
  294.             return TRUE;
  295.         }
  296.     }
  297.  
  298.     return FALSE;
  299. }
  300.  
  301. ///////////////////////////////////////////////////////////////////////////////
  302. ///////////////////////////////////////////////////////////////////////////////
  303.  
  304. BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData,DWORD *pcbWaveSize)
  305. {
  306.     DWORD *pdw;
  307.     DWORD *pdwEnd;
  308.     DWORD dwRiff;
  309.     DWORD dwType;
  310.     DWORD dwLength;
  311.  
  312.     if (ppWaveHeader)
  313.         *ppWaveHeader = NULL;
  314.  
  315.     if (ppbWaveData)
  316.         *ppbWaveData = NULL;
  317.  
  318.     if (pcbWaveSize)
  319.         *pcbWaveSize = 0;
  320.  
  321.     pdw = (DWORD *)pvRes;
  322.     dwRiff = *pdw++;
  323.     dwLength = *pdw++;
  324.     dwType = *pdw++;
  325.  
  326.     if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  327.         goto exit;      // not even RIFF
  328.  
  329.     if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
  330.         goto exit;      // not a WAV
  331.  
  332.     pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  333.  
  334.     while (pdw < pdwEnd)
  335.     {
  336.         dwType = *pdw++;
  337.         dwLength = *pdw++;
  338.  
  339.         switch (dwType)
  340.         {
  341.         case mmioFOURCC('f', 'm', 't', ' '):
  342.             if (ppWaveHeader && !*ppWaveHeader)
  343.             {
  344.                 if (dwLength < sizeof(WAVEFORMAT))
  345.                     goto exit;      // not a WAV
  346.  
  347.                 *ppWaveHeader = (WAVEFORMATEX *)pdw;
  348.  
  349.                 if ((!ppbWaveData || *ppbWaveData) &&
  350.                     (!pcbWaveSize || *pcbWaveSize))
  351.                 {
  352.                     return TRUE;
  353.                 }
  354.             }
  355.             break;
  356.  
  357.         case mmioFOURCC('d', 'a', 't', 'a'):
  358.             if ((ppbWaveData && !*ppbWaveData) ||
  359.                 (pcbWaveSize && !*pcbWaveSize))
  360.             {
  361.                 if (ppbWaveData)
  362.                     *ppbWaveData = (LPBYTE)pdw;
  363.  
  364.                 if (pcbWaveSize)
  365.                     *pcbWaveSize = dwLength;
  366.  
  367.                 if (!ppWaveHeader || *ppWaveHeader)
  368.                     return TRUE;
  369.             }
  370.             break;
  371.         }
  372.  
  373.         pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
  374.     }
  375.  
  376. exit:
  377.     return FALSE;
  378. }
  379.