home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / DS3DVIEW / DSUTIL3D.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  15KB  |  520 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       dsutil3d.c
  6.  *  Content:    Routines for dealing with sounds from resources -- this
  7.  *                version has been modified and extended somewhat from the
  8.  *                version found in the SAMPLES\MISC directory.
  9.  *
  10.  *
  11.  ***************************************************************************/
  12.  
  13. #define WIN32_LEAN_AND_MEAN
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <mmsystem.h>
  17. #include "dsound.h"
  18.  
  19. typedef struct
  20. {
  21.     BYTE *pbWaveData;               // pointer into wave resource (for restore)
  22.     DWORD cbWaveSize;               // size of wave data (for restore)
  23.     int iAlloc;                     // number of buffers.
  24.     int iCurrent;                   // current buffer
  25.     IDirectSoundBuffer* Buffers[1]; // list of buffers
  26.  
  27. } SNDOBJ, *HSNDOBJ;
  28.  
  29. #define _HSNDOBJ_DEFINED
  30. #include "dsutil3d.h"
  31.  
  32. static const char c_szWAV[] = "WAV";
  33.  
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //
  36. // DSLoadSoundBuffer - Loads a .WAV into a sound buffer and returns the sound buffer
  37. //
  38. ///////////////////////////////////////////////////////////////////////////////
  39.  
  40. IDirectSoundBuffer *DSLoadSoundBuffer(IDirectSound *pDS, LPCTSTR lpName)
  41. {
  42.     IDirectSoundBuffer *pDSB = NULL;
  43.     DSBUFFERDESC dsBD = {0};
  44.     BYTE *pbWaveData;
  45.     void *pvBase;
  46.  
  47.     dsBD.dwSize = sizeof(dsBD);
  48.     dsBD.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY
  49.                         | DSBCAPS_LOCSOFTWARE;
  50.  
  51.     if (DSGetWaveResource(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData, &dsBD.dwBufferBytes))
  52.     {
  53.         if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
  54.         {
  55.             if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
  56.             {
  57.                 IDirectSoundBuffer_Release(pDSB);
  58.                 pDSB = NULL;
  59.             }
  60.         }
  61.         else
  62.         {
  63.             pDSB = NULL;
  64.         }
  65.     } else if (DSGetWaveFile(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData,
  66.                         &dsBD.dwBufferBytes, &pvBase))
  67.     {
  68.         if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
  69.         {
  70.             if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
  71.             {
  72.                 IDirectSoundBuffer_Release(pDSB);
  73.                 pDSB = NULL;
  74.             }
  75.         }
  76.         else
  77.         {
  78.             pDSB = NULL;
  79.         }
  80.         UnmapViewOfFile (pvBase);
  81.     }
  82.  
  83.     return pDSB;
  84. }
  85.  
  86.  
  87. ///////////////////////////////////////////////////////////////////////////////
  88. //
  89. // DSLoad3DSoundBuffer - Loads a .WAV into a 3D sound buffer and returns the sound buffer
  90. //
  91. ///////////////////////////////////////////////////////////////////////////////
  92.  
  93. IDirectSoundBuffer *DSLoad3DSoundBuffer(IDirectSound *pDS, LPCTSTR lpName)
  94. {
  95.     IDirectSoundBuffer *pDSB = NULL;
  96.     DSBUFFERDESC dsBD = {0};
  97.     BYTE *pbWaveData;
  98.     void *pvBase;
  99.  
  100.     dsBD.dwSize = sizeof(dsBD);
  101.     dsBD.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME
  102.                         | DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE
  103.                         | DSBCAPS_STICKYFOCUS;
  104.  
  105.     if (DSGetWaveResource(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData, &dsBD.dwBufferBytes))
  106.     {
  107.         if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
  108.         {
  109.             if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
  110.             {
  111.                 IDirectSoundBuffer_Release(pDSB);
  112.                 pDSB = NULL;
  113.             }
  114.         }
  115.         else
  116.         {
  117.             pDSB = NULL;
  118.         }
  119.     } else if (DSGetWaveFile(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData,
  120.                         &dsBD.dwBufferBytes, &pvBase))
  121.     {
  122.         if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
  123.         {
  124.             if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
  125.             {
  126.                 IDirectSoundBuffer_Release(pDSB);
  127.                 pDSB = NULL;
  128.             }
  129.         }
  130.         else
  131.         {
  132.             pDSB = NULL;
  133.         }
  134.         UnmapViewOfFile (pvBase);
  135.     }
  136.  
  137.     return pDSB;
  138. }
  139.  
  140.  
  141. ///////////////////////////////////////////////////////////////////////////////
  142. //
  143. // DSReloadSoundBuffer
  144. //
  145. ///////////////////////////////////////////////////////////////////////////////
  146.  
  147. BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, LPCTSTR lpName)
  148. {
  149.     BOOL result=FALSE;
  150.     BYTE *pbWaveData;
  151.     DWORD cbWaveSize;
  152.     void *pvBase;
  153.  
  154.     if (DSGetWaveResource(NULL, lpName, NULL, &pbWaveData, &cbWaveSize))
  155.     {
  156.         if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
  157.             DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
  158.         {
  159.             result = TRUE;
  160.         }
  161.     } else if( DSGetWaveFile(NULL, lpName, NULL, &pbWaveData, &cbWaveSize, &pvBase))
  162.     {
  163.         if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
  164.             DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
  165.         {
  166.             result = TRUE;
  167.         }
  168.         UnmapViewOfFile (pvBase);
  169.     }
  170.  
  171.     return result;
  172. }
  173.  
  174. ///////////////////////////////////////////////////////////////////////////////
  175. //
  176. // DSGetWaveResource
  177. //
  178. ///////////////////////////////////////////////////////////////////////////////
  179. BOOL DSGetWaveResource(HMODULE hModule, LPCTSTR lpName,
  180.     WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pcbWaveSize)
  181. {
  182.     HRSRC hResInfo;
  183.     HGLOBAL hResData;
  184.     void * pvRes;
  185.  
  186.     if (((hResInfo = FindResource(hModule, lpName, c_szWAV)) != NULL) &&
  187.         ((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
  188.         ((pvRes = LockResource(hResData)) != NULL) &&
  189.         DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize))
  190.     {
  191.         return TRUE;
  192.     }
  193.  
  194.     return FALSE;
  195.  
  196. }
  197.  
  198.  
  199. ///////////////////////////////////////////////////////////////////////////////
  200. //
  201. // DSGetWaveFile
  202. //
  203. ///////////////////////////////////////////////////////////////////////////////
  204. BOOL DSGetWaveFile(HMODULE hModule, LPCTSTR lpName,
  205.     WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pcbWaveSize,
  206.         void **ppvBase)
  207. {
  208.     void *pvRes;
  209.     HANDLE hFile, hMapping;
  210.  
  211.     *ppvBase = NULL;
  212.  
  213.     hFile = CreateFile (lpName, GENERIC_READ, FILE_SHARE_READ, 
  214.                             NULL, OPEN_EXISTING, 0, NULL);
  215.     if (hFile == INVALID_HANDLE_VALUE) return FALSE;
  216.  
  217.     hMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  218.     if (hMapping == INVALID_HANDLE_VALUE)
  219.     {
  220.         CloseHandle (hFile); 
  221.         return FALSE;
  222.     }
  223.  
  224.     CloseHandle (hFile);
  225.  
  226.     pvRes = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0);
  227.     if (pvRes == NULL)
  228.     {
  229.         CloseHandle (hMapping);
  230.         return FALSE;
  231.     }
  232.  
  233.         CloseHandle (hMapping);
  234.  
  235.     if (DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize) == FALSE)
  236.     {
  237.         UnmapViewOfFile (pvRes);
  238.         return FALSE;
  239.     }
  240.  
  241.     *ppvBase = pvRes;
  242.     return TRUE;
  243. }
  244.  
  245.  
  246. ///////////////////////////////////////////////////////////////////////////////
  247. // SndObj fns
  248. ///////////////////////////////////////////////////////////////////////////////
  249.  
  250. SNDOBJ *SndObjCreate(IDirectSound *pDS, LPCTSTR lpName, int iConcurrent)
  251. {
  252.     SNDOBJ *pSO = NULL;
  253.     LPWAVEFORMATEX pWaveHeader;
  254.     BOOL fFound = FALSE;
  255.     BYTE *pbData;
  256.     UINT cbData;
  257.     void * pvBase;
  258.  
  259.     if (DSGetWaveResource(NULL, lpName, &pWaveHeader, &pbData, &cbData))
  260.         fFound = TRUE;
  261.     if (DSGetWaveFile(NULL, lpName, &pWaveHeader, &pbData, &cbData, &pvBase))
  262.     {
  263.         fFound = TRUE;
  264.         UnmapViewOfFile( pvBase );
  265.     }
  266.     if( fFound )
  267.     {
  268.         if (iConcurrent < 1)
  269.             iConcurrent = 1;
  270.  
  271.         if ((pSO = (SNDOBJ *)LocalAlloc(LPTR, sizeof(SNDOBJ) +
  272.             (iConcurrent-1) * sizeof(IDirectSoundBuffer *))) != NULL)
  273.         {
  274.             int i;
  275.  
  276.             pSO->iAlloc = iConcurrent;
  277.             pSO->pbWaveData = pbData;
  278.             pSO->cbWaveSize = cbData;
  279.             pSO->Buffers[0] = DSLoadSoundBuffer(pDS, lpName);
  280.  
  281.             for (i=1; i<pSO->iAlloc; i++)
  282.             {
  283.                 if (FAILED(IDirectSound_DuplicateSoundBuffer(pDS,
  284.                     pSO->Buffers[0], &pSO->Buffers[i])))
  285.                 {
  286.                     pSO->Buffers[i] = DSLoadSoundBuffer(pDS, lpName);
  287.                     if (!pSO->Buffers[i]) {
  288.                         SndObjDestroy(pSO);
  289.                         pSO = NULL;
  290.                         break;
  291.                     }
  292.                 }
  293.             }
  294.         }
  295.     }
  296.  
  297.     return pSO;
  298. }
  299.  
  300. ///////////////////////////////////////////////////////////////////////////////
  301. ///////////////////////////////////////////////////////////////////////////////
  302.  
  303. void SndObjDestroy(SNDOBJ *pSO)
  304. {
  305.     if (pSO)
  306.     {
  307.         int i;
  308.  
  309.         for (i=0; i<pSO->iAlloc; i++)
  310.         {
  311.             if (pSO->Buffers[i])
  312.             {
  313.                 IDirectSoundBuffer_Release(pSO->Buffers[i]);
  314.                 pSO->Buffers[i] = NULL;
  315.             }
  316.         }
  317.         LocalFree((HANDLE)pSO);
  318.     }
  319. }
  320.  
  321. ///////////////////////////////////////////////////////////////////////////////
  322. ///////////////////////////////////////////////////////////////////////////////
  323.  
  324. IDirectSoundBuffer *SndObjGetFreeBuffer(SNDOBJ *pSO)
  325. {
  326.     IDirectSoundBuffer *pDSB;
  327.  
  328.     if (pSO == NULL)
  329.         return NULL;
  330.  
  331.     if (pDSB = pSO->Buffers[pSO->iCurrent])
  332.     {
  333.         HRESULT hres;
  334.         DWORD dwStatus;
  335.  
  336.         hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);
  337.  
  338.         if (FAILED(hres))
  339.             dwStatus = 0;
  340.  
  341.         if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  342.         {
  343.             if (pSO->iAlloc > 1)
  344.             {
  345.                 if (++pSO->iCurrent >= pSO->iAlloc)
  346.                     pSO->iCurrent = 0;
  347.  
  348.                 pDSB = pSO->Buffers[pSO->iCurrent];
  349.                 hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);
  350.  
  351.                 if (SUCCEEDED(hres) && (dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  352.                 {
  353.                     IDirectSoundBuffer_Stop(pDSB);
  354.                     IDirectSoundBuffer_SetCurrentPosition(pDSB, 0);
  355.                 }
  356.             }
  357.             else
  358.             {
  359.                 pDSB = NULL;
  360.             }
  361.         }
  362.  
  363.         if (pDSB && (dwStatus & DSBSTATUS_BUFFERLOST))
  364.         {
  365.             if (FAILED(IDirectSoundBuffer_Restore(pDSB)) ||
  366.                 !DSFillSoundBuffer(pDSB, pSO->pbWaveData, pSO->cbWaveSize))
  367.             {
  368.                 pDSB = NULL;
  369.             }
  370.         }
  371.     }
  372.  
  373.     return pDSB;
  374. }
  375.  
  376. ///////////////////////////////////////////////////////////////////////////////
  377. ///////////////////////////////////////////////////////////////////////////////
  378.  
  379. BOOL SndObjPlay(SNDOBJ *pSO, DWORD dwPlayFlags)
  380. {
  381.     BOOL result = FALSE;
  382.  
  383.     if (pSO == NULL)
  384.         return FALSE;
  385.  
  386.     if ((!(dwPlayFlags & DSBPLAY_LOOPING) || (pSO->iAlloc == 1)))
  387.     {
  388.         IDirectSoundBuffer *pDSB = SndObjGetFreeBuffer(pSO);
  389.         if (pDSB != NULL) {
  390.             result = SUCCEEDED(IDirectSoundBuffer_Play(pDSB, 0, 0, dwPlayFlags));
  391.         }
  392.     }
  393.  
  394.     return result;
  395. }
  396.  
  397. ///////////////////////////////////////////////////////////////////////////////
  398. ///////////////////////////////////////////////////////////////////////////////
  399.  
  400. BOOL SndObjStop(SNDOBJ *pSO)
  401. {
  402.     int i;
  403.  
  404.     if (pSO == NULL)
  405.         return FALSE;
  406.  
  407.     for (i=0; i<pSO->iAlloc; i++)
  408.     {
  409.         IDirectSoundBuffer_Stop(pSO->Buffers[i]);
  410.         IDirectSoundBuffer_SetCurrentPosition(pSO->Buffers[i], 0);
  411.     }
  412.  
  413.     return TRUE;
  414. }
  415.  
  416. ///////////////////////////////////////////////////////////////////////////////
  417. ///////////////////////////////////////////////////////////////////////////////
  418.  
  419. BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD cbWaveSize)
  420. {
  421.     if (pDSB && pbWaveData && cbWaveSize)
  422.     {
  423.         LPVOID pMem1, pMem2;
  424.         DWORD dwSize1, dwSize2;
  425.  
  426.         if (SUCCEEDED(IDirectSoundBuffer_Lock(pDSB, 0, cbWaveSize,
  427.             &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))
  428.         {
  429.             CopyMemory(pMem1, pbWaveData, dwSize1);
  430.  
  431.             if ( 0 != dwSize2 )
  432.                 CopyMemory(pMem2, pbWaveData+dwSize1, dwSize2);
  433.  
  434.             IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
  435.             return TRUE;
  436.         }
  437.     }
  438.  
  439.     return FALSE;
  440. }
  441.  
  442. ///////////////////////////////////////////////////////////////////////////////
  443. ///////////////////////////////////////////////////////////////////////////////
  444.  
  445. BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData,DWORD *pcbWaveSize)
  446. {
  447.     DWORD *pdw;
  448.     DWORD *pdwEnd;
  449.     DWORD dwRiff;
  450.     DWORD dwType;
  451.     DWORD dwLength;
  452.  
  453.     if (ppWaveHeader)
  454.         *ppWaveHeader = NULL;
  455.  
  456.     if (ppbWaveData)
  457.         *ppbWaveData = NULL;
  458.  
  459.     if (pcbWaveSize)
  460.         *pcbWaveSize = 0;
  461.  
  462.     pdw = (DWORD *)pvRes;
  463.     dwRiff = *pdw++;
  464.     dwLength = *pdw++;
  465.     dwType = *pdw++;
  466.  
  467.     if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  468.         goto exit;      // not even RIFF
  469.  
  470.     if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
  471.         goto exit;      // not a WAV
  472.  
  473.     pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  474.  
  475.     while (pdw < pdwEnd)
  476.     {
  477.         dwType = *pdw++;
  478.         dwLength = *pdw++;
  479.  
  480.         switch (dwType)
  481.         {
  482.         case mmioFOURCC('f', 'm', 't', ' '):
  483.             if (ppWaveHeader && !*ppWaveHeader)
  484.             {
  485.                 if (dwLength < sizeof(WAVEFORMAT))
  486.                     goto exit;      // not a WAV
  487.  
  488.                 *ppWaveHeader = (WAVEFORMATEX *)pdw;
  489.  
  490.                 if ((!ppbWaveData || *ppbWaveData) &&
  491.                     (!pcbWaveSize || *pcbWaveSize))
  492.                 {
  493.                     return TRUE;
  494.                 }
  495.             }
  496.             break;
  497.  
  498.         case mmioFOURCC('d', 'a', 't', 'a'):
  499.             if ((ppbWaveData && !*ppbWaveData) ||
  500.                 (pcbWaveSize && !*pcbWaveSize))
  501.             {
  502.                 if (ppbWaveData)
  503.                     *ppbWaveData = (LPBYTE)pdw;
  504.  
  505.                 if (pcbWaveSize)
  506.                     *pcbWaveSize = dwLength;
  507.  
  508.                 if (!ppWaveHeader || *ppWaveHeader)
  509.                     return TRUE;
  510.             }
  511.             break;
  512.         }
  513.  
  514.         pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
  515.     }
  516.  
  517. exit:
  518.     return FALSE;
  519. }
  520.