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

📄 dsapi.cpp

📁 网页游戏赤壁
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*==========================================================================
 *
 *  Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
 *	Source		:	DSstream.cpp
 *  File		:	DsApi.cpp
 *	Edited by	:	Liu Gang
 *	Version		:	V0023
 *	V0010		:	Oct.8.1996
 *	V0011		:	Nov.25.1996
 *	V0012		:	Apr.1.1997, add IfPlaying() function to classes
 *	V0020		:	Apr.2.1997, fixed a bug when playing static sound, 
 *								do not use Mutex with static wave objects
 *	V0021		:	May.2.1997, add function DS_IfSoundEnable()
 *	V0022		:	May.10.1997, fixed a bug in IfPlaying(), close the sound if the sound is end
 *	V0023		:	May.15.1997, fixed bugs when quit and init sound frequently
 *	V0024		:	Aug.13.1997, fixed a bug when playing
 *  Content:   streams data from a disk WAVE file to a
 *             DirectSound secondary buffer for playback.
 *
 ***************************************************************************/

#include "stdafx.h"
#include "dsApi.h"
#include "dsWave.h"	// wave file functions
#include "Assert.h"

//-----debug
//#define	_DS_LOG_
#ifdef	_DS_LOG_
	#include <stdio.h>
#endif
//-----debug
#define	_TEST_SOUND_

// globals for controling sounds
/////////////
// global sound device
LPDIRECTSOUND           lpDS = NULL;

// global dynamic waveinfo objects
int				nWaveCounter=0;		// counter for them
LPWAVEDYNAMIC	lpwdWaves[WAVE_OBJECT_MAX];

// global static waveinfo objects
int				nSWaveCounter=0;	// counter for them
LPWAVESTATIC	lpwsWaves[WAVE_OBJECT_MAXS];

// handle of window to receive error messages
HWND	DS_hwndGame;
/////////////

// globals for wave sound
/////////////
// true for enable sound
BOOL DS_bSoundEnable = FALSE;

// true for sound is usable
BOOL DS_bInitialized = FALSE;

// fade mode varible
int	DS_nFadeMode = DS_FADE_NONE;
// sound volume	varible
int	DS_nVolume = 0;
// sound pan varible
int DS_nPan = 0;
/////////////

// multi threads
/////////////
// used by TimeFunc() and Stop() in WAVEDYNAMIC
// not used in WAVESTATIC
// WaitforSingleObject() to get mutex
// ReleaseMutex() to release mutex
BOOL bCreateMutex = FALSE;
HANDLE	hMutex=0;
CRITICAL_SECTION	csPlayKey; // Guards one variable, gbPlay
/////////////


// initialize sound
/////////////
// error handle
// hwnd		:	error window
// err		:	error number
// return value	:	Always false
BOOL SoundFail( HWND hWnd, int err );

// for static wave only
// called if the static sound buffer got the end
// clear all the sounds played prviously, and now they are stoped.
void DS_CloseStopedSoundS();
/////////////

/*****************************************************************************/
/* DS_InitSound()                                                            */
/*                                                                           */
/* Performs sound initialization.											 */
/*                                                                           */
/*****************************************************************************/
LPDIRECTSOUNDBUFFER	lpDSBPrimary = NULL;
WAVEFORMATEX wfx;
// initialize direct sound object
// hwnd		:	handle of window to receive error messages
// nType		:	wave format, 
//					default if do not want to change params of waves
// return value	:	TRUE if succeeded
BOOL DS_InitSound( HWND hwnd, int nType/* = DS_WAVE_FORMAT_AUTO*/ )
{
    HRESULT         hr;
	DSCAPS			dscaps;
    DSBUFFERDESC    dsbd;

	if( DS_bInitialized == TRUE )
	{
		OutputDebugString( "DS_InitSound Warning: sound has been initialized!\n" );
		return FALSE;	// sound has been initialized
	}

	DS_hwndGame = hwnd;

    hr = DirectSoundCreate( NULL, &lpDS, NULL );
    if( hr != DS_OK )
    {
		return SoundFail( DS_hwndGame, 0 );
    }

	if( nType == DS_WAVE_FORMAT_AUTO )
	{
	    // SetCooperativeLevel, we only need normal mode
		if(( hr = lpDS->SetCooperativeLevel( DS_hwndGame, DSSCL_NORMAL )) != DS_OK )
		{
			return SoundFail( DS_hwndGame, 1 );
		}
	}
	else
	{
	    // SetCooperativeLevel, normal mode is not enough
		if(( hr = lpDS->SetCooperativeLevel( DS_hwndGame, DSSCL_PRIORITY )) != DS_OK )
		{
			return SoundFail( DS_hwndGame, 4 );
		}
	}
	

	// get sound card compatible configration
	dscaps.dwSize = sizeof( dscaps );
	lpDS->GetCaps( &dscaps );
	char buf[255];
#ifdef	_DEBUG
	wsprintf( buf, "DS Caps: %d\n",dscaps.dwFlags );
	//OutputDebugString( buf );
#endif

    // Set up the primary direct sound buffer.
    memset(&dsbd, 0, sizeof(DSBUFFERDESC));
    dsbd.dwSize                 = sizeof(DSBUFFERDESC);
    dsbd.dwFlags                = DSBCAPS_PRIMARYBUFFER;
    
    if ((hr = lpDS->CreateSoundBuffer( &dsbd,
                          &lpDSBPrimary,
                          NULL )) != 0)
    {
		return SoundFail( DS_hwndGame, 2 );
    }

	// set primary buffer format if necessary
	if( nType != DS_WAVE_FORMAT_AUTO )
	{
		int nChannels;
		int nSamplesPerSec;
		int nwBitsPerSample;
		switch( nType )
		{
			case	DS_WAVE_FORMAT_2_22_8:
				nChannels =  2;
				nSamplesPerSec = 22050;
				nwBitsPerSample = 8;
				break;
			case	DS_WAVE_FORMAT_2_22_16:
				nChannels =  2;
				nSamplesPerSec = 11025;
				nwBitsPerSample = 8;
				break;
		}
		wfx.wFormatTag = WAVE_FORMAT_PCM;
		wfx.nChannels = 2;
		wfx.nSamplesPerSec = 11025;
		wfx.wBitsPerSample = 8;
		wfx.nBlockAlign = wfx.wBitsPerSample*wfx.nChannels/8;
		wfx.nAvgBytesPerSec = wfx.nSamplesPerSec*wfx.nBlockAlign;
		wfx.cbSize = 0;
		if ((hr = lpDSBPrimary->SetFormat(&wfx)) != DS_OK)
		{
			switch( hr )
			{
			case	DSERR_BADFORMAT:
				strcpy( buf," Bad format " );
				break;
			case	DSERR_INVALIDCALL:
				strcpy( buf," Invalid call " );
				break;
			case	DSERR_INVALIDPARAM:
				strcpy( buf," Invalid Parem " );
				break;
			case	DSERR_OUTOFMEMORY:
				strcpy( buf," Out of memory " );
				break;
			case	DSERR_PRIOLEVELNEEDED:
				strcpy( buf," Priority level needed " );
				break;
			}
			return SoundFail( DS_hwndGame, 3 );
		}
	}

	// always play in primary buffer
	lpDSBPrimary->Play( 0, 0, DSBPLAY_LOOPING );

	// for multi threads
	if( bCreateMutex == FALSE )
	{
		hMutex = CreateMutex( NULL, FALSE, NULL );
		InitializeCriticalSection (&csPlayKey);
		bCreateMutex = TRUE;
	}

	// initialize secondary sound buffers
	for( int i=0; i< WAVE_OBJECT_MAX; i++ )
	{
		lpwdWaves[i] = NULL;
	}
	for( i=0; i< WAVE_OBJECT_MAXS; i++ )
	{
		lpwsWaves[i] = NULL;
	}

	// enable sound
	DS_bInitialized = TRUE;
	DS_EnableSound( TRUE );

	return TRUE;

}

// release sound device
void DS_QuitSound( void )
{
	if( DS_bInitialized == FALSE )
	{
		OutputDebugString( "DS_QuitSound Warning: No sound at all!\n" );
		return;
	}
	else
	{
		// disable sound
		DS_EnableSound( FALSE );
		DS_bInitialized = FALSE;
		// for multi threads
		if( bCreateMutex == TRUE )
		{
			CloseHandle( hMutex );
			DeleteCriticalSection (&csPlayKey);
			bCreateMutex = FALSE;
		}
	}

	if( lpDS )
	{
		if( lpDSBPrimary != NULL )
		{
			lpDSBPrimary->Stop();
			lpDSBPrimary->Release();
			lpDSBPrimary = NULL;
		}

		lpDS->Release( );
		lpDS = NULL;
	}

}

// init fail message
BOOL SoundFail( HWND hWnd, int err )
{
	char buf[129];

    wsprintf(buf, "DirectSound init FAILED (%d):\n", err+DS_ERROR_ID);
	switch( err )
	{
	case	0:
		strcat( buf, "Direct Sound Creation Failed" );
		break;
	case	1:
		strcat( buf, "Direct Sound Set Cooperative Level Failed" );
		break;
	case	2:
		strcat( buf, "Cannot create primary buffer" ); 
		break;
	}

	DS_QuitSound();

	OutputDebugString( buf );
	return FALSE;
//	if( MessageBox(hWnd, buf, "Direct Sound Error", MB_OK|MB_ICONSTOP) == IDOK )
//			return TRUE;
//	else	return FALSE;
}

// enable or disable sound effects
// bEnable		:	TRUE for enable sound
// return value	:	old state of sound, enable or disable
BOOL DS_EnableSound( BOOL bEnable )
{
	BOOL bEnableSave = DS_bSoundEnable;
	if( DS_bInitialized == FALSE )
		return FALSE;
	if( bEnable )
	{
		DS_bSoundEnable = TRUE;
	}
	else
	{
		DS_bSoundEnable = FALSE;
		// check and destroy sound buffers
		for( int i=0; i< WAVE_OBJECT_MAX; i++ )
		{
			//OutputDebugString( "Wait0," );
			EnterCriticalSection (&csPlayKey);
			WaitForSingleObject( hMutex, INFINITE );
			if( lpwdWaves[i] != NULL )
			{
				int nID = lpwdWaves[i]->nID;
			ReleaseMutex( hMutex );
			//OutputDebugString( "End Wait0\n" );
				lpwdWaves[i]->Stop();
			//OutputDebugString( "Wait1," );
			WaitForSingleObject( hMutex, INFINITE );
				PostMessage( DS_hwndGame, WM_DSSTREAM_DONE, (WPARAM)nID, (LPARAM)0 );
				//OutputDebugString( "Warning: Destroy dynamic sound object before stop playing sound!\n" );
			}
			ReleaseMutex( hMutex );
			LeaveCriticalSection (&csPlayKey);
			//OutputDebugString( "End Wait1\n" );
		}

		//-----debug
#ifdef	_DS_LOG_
		FILE*fp=fopen( "DSTest.log","at" );
		fprintf(fp,"G" );
		fclose(fp);
#endif
		//-----debug

		for( i=0; i< WAVE_OBJECT_MAXS; i++ )
		{
			EnterCriticalSection (&csPlayKey);
//			WaitForSingleObject( hMutex, INFINITE );
			if( lpwsWaves[i] != NULL )
			{
				int nID = lpwsWaves[i]->nID;
//				ReleaseMutex( hMutex );
				lpwsWaves[i]->Stop();
//				WaitForSingleObject( hMutex, INFINITE );
				PostMessage( DS_hwndGame, WM_DSSTREAM_DONE, (WPARAM)nID, (LPARAM)0 );
			}
//			ReleaseMutex( hMutex );
			LeaveCriticalSection (&csPlayKey);
		}
	}
	return bEnableSave;
}

// test if sound is enable
BOOL DS_IfSoundEnable()
{
	return DS_bSoundEnable;
}

// nFade		:	fade mode, see above
// return value	:	old fade mode
int	DS_FadeSound( int nFadeMode )
{
	int nFadeSave = DS_nFadeMode;
	DS_nFadeMode = nFadeMode;
	return nFadeSave;
}

// set volume
// real range is from 0 to -10000,
// this function is range from 0 to -5000
// under -3200 I cannot hear at all
// nVol			:	volume of the sound device
// return value	:	old volume of the sound device, -1 if error occurs
int	DS_VolumeSound( int nVol )
{
	int nVolume;
	nVolume = DS_nVolume;
	if( nVol >0 ) nVol = 0;
	if( nVol < -5000 ) nVol = -5000;
	DS_nVolume = nVol;
#ifdef	_DEBUG
	OutputDebugString( "DS Volume:" );
	OutputString( DS_nVolume, "\n" );
#endif
	return nVolume;
}

// set pan
// real range is from -10000 to 10000, 
// but this function is range from -2000 to 2000
// larger than 1000, right cannot hear
// smaller than -1000 left cannot hear
// nPan			:	pan value for the sound device
// return value	:	old pan value for the sound device
int	DS_PanSound( int nPan )
{
	int nPanSave = DS_nPan;
	if( nPan < - 2000)	nPan = -2000;
	if( nPan > 2000 )	nPan = 2000;
	DS_nPan = nPan;
#ifdef	_DEBUG
	OutputDebugString( "DS Pan:" );
	OutputString( DS_nPan, "\n" );
#endif
	return nPan;
}

// get sound volume
inline int DS_GetVolume()
{
	return DS_nVolume;	
}
///////////////////


//==========================================================================
//
// class WAVEDYNAMIC
//
//==========================================================================
///////////////////
// global wave play
// used by class WAVEDYNAMIC

// get WAVEDYNAMIC pointer
// nIndex		:	ID in global wave array
// return value	:	WAVEDYNAMIC pointer
LPWAVEDYNAMIC SetToGlobal( int nIndex );

// nIndex		:	ID in global wave array
// return value	:	0 if succeeded, otherwise error number,
int StreamBufferSetup( int nIndex );

// nIndex	:	ID in global wave array
void StreamBufferRelease( int nIndex );

// nIndex	:	ID in global wave array
void ResetWavePlayer( int nIndex );

// nIndex	:	ID in global wave array
void CALLBACK TimeFunc( UINT, UINT, DWORD nIndex, DWORD, DWORD );

// constructor
CDynamicWave::CDynamicWave()
{
    pwfx = NULL;             /* Wave Format data structure */
    hmmio = 0;             /* MM I/O handle for the WAVE */
    mmck;              /* Multimedia RIFF chunk */
    memset( &mmckInRIFF,0, sizeof( mmckInRIFF ) );        /* Use in opening a WAVE file */
    lpDSBStreamBuffer = NULL; /* Points to DirectSoundBuffer */
    dwBufferSize = 0;      /* Size of the entire buffer */
    dwBufferSegSize = 0;   /* Size of one buffer segment */
    dwNextWriteOffset = 0; /* Offset to next buffer segment */
    dwPlayLast = 0;        /* Stores last play cursor */

⌨️ 快捷键说明

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