⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsutil.c

📁 Windows CE .Net 下面 Direct DRAW编程的经典实例。对于初学Windows 平台下Direct DRAW技术的程序员颇具借鉴意义!
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*==========================================================================
 *
 *
 *  File:       dsutil.cpp
 *  Content:    Routines for dealing with sounds from resources
 *
 *
 ***************************************************************************/

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <dsound.h>

typedef struct
{
    BYTE *pbWaveData;               // pointer into wave resource (for restore)
    DWORD cbWaveSize;               // size of wave data (for restore)
    int iAlloc;                     // number of buffers.
    int iCurrent;                   // current buffer
    IDirectSoundBuffer* Buffers[1]; // list of buffers

} SNDOBJ, *HSNDOBJ;

#define _HSNDOBJ_DEFINED
#include "dsutil.h"

static const TCHAR c_szWAV[] = TEXT("WAV");

///////////////////////////////////////////////////////////////////////////////
//
// DSLoadSoundBuffer
//
///////////////////////////////////////////////////////////////////////////////

IDirectSoundBuffer *
DSLoadSoundBuffer(IDirectSound *pDS, 
		  LPCTSTR lpName, 
		  HINSTANCE hInstance)
{
    IDirectSoundBuffer *pDSB = NULL;
    DSBUFFERDESC dsBD = {0};
    BYTE *pbWaveData;

    if (DSGetWaveResource(hInstance, lpName, &dsBD.lpwfxFormat, &pbWaveData, &dsBD.dwBufferBytes))
    {
	dsBD.dwSize = sizeof(dsBD);
	dsBD.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;

	if (SUCCEEDED(IDirectSound_CreateSoundBuffer(pDS, &dsBD, &pDSB, NULL)))
	{
	    if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
	    {
		IDirectSoundBuffer_Release(pDSB);
		pDSB = NULL;
	    }
	}
	else
	{
	    pDSB = NULL;
	}
    }

    return pDSB;
}

///////////////////////////////////////////////////////////////////////////////
//
// DSReloadSoundBuffer
//
///////////////////////////////////////////////////////////////////////////////

BOOL 
DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, 
		    LPCTSTR lpName, 
		    HINSTANCE hInstance)
{
    BOOL result=FALSE;
    BYTE *pbWaveData;
    DWORD cbWaveSize;

    if (DSGetWaveResource(hInstance, lpName, NULL, &pbWaveData, &cbWaveSize))
    {
	if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
	    DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
	{
	    result = TRUE;
	}
    }

    return result;
}

///////////////////////////////////////////////////////////////////////////////
//
// DSGetWaveResource
//
///////////////////////////////////////////////////////////////////////////////

BOOL 
DSGetWaveResource(HMODULE hModule, 
		  LPCTSTR lpName,
		  WAVEFORMATEX **ppWaveHeader, 
		  BYTE **ppbWaveData, 
		  DWORD *pcbWaveSize)
{
    HRSRC hResInfo;
    HGLOBAL hResData;
    void *pvRes;

    if (((hResInfo = FindResource(hModule, lpName, c_szWAV)) != NULL) &&
	((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
	((pvRes = LockResource(hResData)) != NULL) &&
	DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize))
    {
	return TRUE;
    }

    return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
// SndObj fns
///////////////////////////////////////////////////////////////////////////////

SNDOBJ *
SndObjCreate(IDirectSound *pDS, 
	     LPCTSTR lpName, 
	     int iConcurrent, 
	     HINSTANCE hInstance)
{
    SNDOBJ *pSO = NULL;
    LPWAVEFORMATEX pWaveHeader;
    BYTE *pbData;
    UINT cbData;

    if (DSGetWaveResource(hInstance, lpName, &pWaveHeader, &pbData, &cbData))
    {
	if (iConcurrent < 1)
	    iConcurrent = 1;

	if ((pSO = (SNDOBJ *)LocalAlloc(LPTR, sizeof(SNDOBJ) +
	    (iConcurrent-1) * sizeof(IDirectSoundBuffer *))) != NULL)
	{
	    int i;

	    pSO->iAlloc = iConcurrent;
	    pSO->pbWaveData = pbData;
	    pSO->cbWaveSize = cbData;
	    pSO->Buffers[0] = DSLoadSoundBuffer(pDS, lpName, hInstance);

	    for (i=1; i<pSO->iAlloc; i++)
	    {
		if (FAILED(IDirectSound_DuplicateSoundBuffer(pDS,
		    pSO->Buffers[0], &pSO->Buffers[i])))
		{
		    pSO->Buffers[i] = DSLoadSoundBuffer(pDS, lpName, hInstance);
		    if (!pSO->Buffers[i]) {
			SndObjDestroy(pSO);
			pSO = NULL;
			break;
		    }
		}
	    }
	}
    }

    return pSO;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void 
SndObjDestroy(SNDOBJ *pSO)
{
    if (pSO)
    {
	int i;

	for (i=0; i<pSO->iAlloc; i++)
	{
	    if (pSO->Buffers[i])
	    {
		IDirectSoundBuffer_Release(pSO->Buffers[i]);
		pSO->Buffers[i] = NULL;
	    }
	}
	LocalFree((HANDLE)pSO);
    }
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

IDirectSoundBuffer *
SndObjGetFreeBuffer(SNDOBJ *pSO)
{
    IDirectSoundBuffer *pDSB;

    if (pSO == NULL)
	return NULL;

    if (pDSB = pSO->Buffers[pSO->iCurrent])
    {
	HRESULT hres;
	DWORD dwStatus;

	hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);

	if (FAILED(hres))
	    dwStatus = 0;

	if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
	{
	    if (pSO->iAlloc > 1)
	    {
		if (++pSO->iCurrent >= pSO->iAlloc)
		    pSO->iCurrent = 0;

		pDSB = pSO->Buffers[pSO->iCurrent];
		hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);

		if (SUCCEEDED(hres) && (dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
		{
		    IDirectSoundBuffer_Stop(pDSB);
		    IDirectSoundBuffer_SetCurrentPosition(pDSB, 0);
		}
	    }
	    else
	    {
		pDSB = NULL;
	    }
	}

	if (pDSB && (dwStatus & DSBSTATUS_BUFFERLOST))
	{
	    if (FAILED(IDirectSoundBuffer_Restore(pDSB)) ||
		!DSFillSoundBuffer(pDSB, pSO->pbWaveData, pSO->cbWaveSize))
	    {
		pDSB = NULL;
	    }
	}
    }

    return pDSB;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

BOOL 
SndObjPlay(SNDOBJ *pSO, 
	   DWORD dwPlayFlags)
{
    BOOL result = FALSE;

    if (pSO == NULL)
	return FALSE;

    if ((!(dwPlayFlags & DSBPLAY_LOOPING) || (pSO->iAlloc == 1)))
    {
	IDirectSoundBuffer *pDSB = SndObjGetFreeBuffer(pSO);
	if (pDSB != NULL) {
	    result = SUCCEEDED(IDirectSoundBuffer_Play(pDSB, 0, 0, dwPlayFlags));
	}
    }

    return result;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

BOOL 
SndObjStop(SNDOBJ *pSO)
{
    int i;

    if (pSO == NULL)
	return FALSE;

    for (i=0; i<pSO->iAlloc; i++)
    {
	IDirectSoundBuffer_Stop(pSO->Buffers[i]);
	IDirectSoundBuffer_SetCurrentPosition(pSO->Buffers[i], 0);
    }

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

BOOL 
DSFillSoundBuffer(IDirectSoundBuffer *pDSB, 
		  BYTE *pbWaveData, 
		  DWORD cbWaveSize)
{
    if (pDSB && pbWaveData && cbWaveSize)
    {
	LPVOID pMem1, pMem2;
	DWORD dwSize1, dwSize2;

	if (SUCCEEDED(IDirectSoundBuffer_Lock(pDSB, 0, cbWaveSize,
	    &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))
	{
	    memcpy(pMem1, pbWaveData, dwSize1);

	    if ( 0 != dwSize2 )
		memcpy(pMem2, pbWaveData+dwSize1, dwSize2);

	    IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
	    return TRUE;
	}
    }

    return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

BOOL DSParseWaveResource(void *pvRes, 
			 WAVEFORMATEX **ppWaveHeader, 
			 BYTE **ppbWaveData,
			 DWORD *pcbWaveSize)
{
    DWORD *pdw;
    DWORD *pdwEnd;
    DWORD dwRiff;
    DWORD dwType;
    DWORD dwLength;

    if (ppWaveHeader)
	*ppWaveHeader = NULL;

    if (ppbWaveData)
	*ppbWaveData = NULL;

    if (pcbWaveSize)
	*pcbWaveSize = 0;

    pdw = (DWORD *)pvRes;
    dwRiff = *pdw++;
    dwLength = *pdw++;
    dwType = *pdw++;

    if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
	goto exit;      // not even RIFF

    if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
	goto exit;      // not a WAV

    pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);

    while (pdw < pdwEnd)
    {
	dwType = *pdw++;
	dwLength = *pdw++;

	switch (dwType)
	{
	case mmioFOURCC('f', 'm', 't', ' '):
	    if (ppWaveHeader && !*ppWaveHeader)
	    {
		if (dwLength < sizeof(WAVEFORMAT))
		    goto exit;      // not a WAV

		*ppWaveHeader = (WAVEFORMATEX *)pdw;

		if ((!ppbWaveData || *ppbWaveData) &&
		    (!pcbWaveSize || *pcbWaveSize))
		{
		    return TRUE;
		}
	    }
	    break;

	case mmioFOURCC('d', 'a', 't', 'a'):
	    if ((ppbWaveData && !*ppbWaveData) ||
		(pcbWaveSize && !*pcbWaveSize))
	    {
		if (ppbWaveData)
		    *ppbWaveData = (LPBYTE)pdw;

		if (pcbWaveSize)
		    *pcbWaveSize = dwLength;

		if (!ppWaveHeader || *ppWaveHeader)
		    return TRUE;
	    }
	    break;
	}

	pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
    }

exit:
    return FALSE;
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -