DSUTIL.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

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