Figure 5
DXSound.cpp
/******************************************************************************
FILE: DXSound.cpp
This module contains all of the DirectSound specific code. This includes
initialization and uninitialization functions as well as functions to create
and play sound buffers.
GLOBALS:
g_lpDSound -- A pointer to the IDirectSound interface
g_lpDSBufferPrimary -- A pointer to the IDirectSoundBuffer interface
used for the primary sound buffer
g_lpDS3dListener -- A pointer to the IDirectSound3DListener interface
g_lpDSBufferOuch[NUMOUCHES] -- Array of pointers to IDirectSoundBuffer
interface for the "ouch" sound
g_lpDS3DBufferOuch[NUMOUCHES] -- Array of pointers to the IDirectSound3DBuffer
interface for the "ouch" sound
g_lpDSBufferDoppler -- A pointer to the IDirectSoundBuffer for the doppler
sound
g_lpDS3DBufferDoppler -- A pointer to the IDirectSound3DBuffer for the doppler
sound
g_lpDSBufferDance -- A pointer to the IDirectSoundBuffer for the "Dance" sound
g_lpDS3DBufferDance -- A pointer to the IDirectSound3DBuffer for the "Dance"
sound
g_lpDSBufferCone -- A pointer to the IDirectSoundBuffer for the "Cone" sound
g_lpDS3DBufferCone -- A pointer to the IDirectSound3DBuffer for the "Cone"
sound
g_bDSActive -- Is this application currently active
******************************************************************************/
#include <Windowsx.h>
#include <Dsound.h>
#include <mmsystem.h>
#include <mmreg.h>
#include "DXSound.h"
#include "main.h"
#include "resource.h"
#define NUMOUCHES 4
LPDIRECTSOUND g_lpDSound = NULL ;
LPDIRECTSOUNDBUFFER g_lpDSBufferPrimary = NULL ;
LPDIRECTSOUND3DLISTENER g_lpDS3dListener = NULL ;
LPDIRECTSOUNDBUFFER g_lpDSBufferOuch[NUMOUCHES] = {NULL} ;
LPDIRECTSOUND3DBUFFER g_lpDS3DBufferOuch[NUMOUCHES] = {NULL} ;
LPDIRECTSOUNDBUFFER g_lpDSBufferDoppler = NULL ;
LPDIRECTSOUND3DBUFFER g_lpDS3DBufferDoppler = NULL ;
LPDIRECTSOUNDBUFFER g_lpDSBufferDance = NULL ;
LPDIRECTSOUND3DBUFFER g_lpDS3DBufferDance = NULL ;
LPDIRECTSOUNDBUFFER g_lpDSBufferCone = NULL ;
LPDIRECTSOUND3DBUFFER g_lpDS3DBufferCone = NULL ;
BOOL g_bDSActive = TRUE ;
BOOL InitListener( void ) ;
BOOL InitOuchBuffer( void ) ;
LPDIRECTSOUNDBUFFER WavToStaticBuffer( LPBYTE lpBuffer, DWORD dwSize,
LPDIRECTSOUNDBUFFER lpdsBuffer ) ;
BOOL RestoreBufferData( LPDIRECTSOUNDBUFFER lpdsBuffer, UINT nResource ) ;
BOOL InitDopplerBuffer( void ) ;
BOOL InitDanceBuffer( void ) ;
BOOL InitConeBuffer( void ) ;
/******************************************************************************
FUNCTION: InitDirectSound
This is where the actual COM initialization occurs. The DirectSound object
is created and initialized with the proper cooperative level. Also the primary
sound buffer is created, and functions are called to create the secondary
buffers.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitDirectSound( void )
{
DSBUFFERDESC dsBufferDesc ;
// Create the DirectSoundObject and retrieve a pointer to its IDirectSound
// interface
if ( FAILED( DirectSoundCreate( NULL, &g_lpDSound, NULL ) ) )
return FALSE ;
// Set the cooperative level to normal. This limits us to a primary
// buffer format of 22kHz, stereo, 8-bit
if ( FAILED( g_lpDSound->SetCooperativeLevel( g_hMainWnd, DSSCL_NORMAL ) ) )
{
UnInitDirectSound() ;
return FALSE ;
}
// Set up the DSBUFFERDESC structure for creation of the primary buffer.
// Make sure that the unused items in the structure are set to zero.
// Notice the DSBCAPS_CTRL3D, we need this for 3d sound support.
dsBufferDesc.dwSize = sizeof( dsBufferDesc ) ;
dsBufferDesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER |
DSBCAPS_LOCHARDWARE ;
dsBufferDesc.dwBufferBytes = 0 ;
dsBufferDesc.dwReserved = 0 ;
dsBufferDesc.lpwfxFormat = NULL ;
// Create the primary buffer. If it fails, uninit DirectSound and exit
if ( FAILED( g_lpDSound->CreateSoundBuffer( &dsBufferDesc,
&g_lpDSBufferPrimary, NULL ) ) )
{
UnInitDirectSound() ;
return FALSE ;
}
// Set the buffer playing and looping. This keeps the mixer running.
g_lpDSBufferPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ;
// Call function to set up the listener interface
if ( !InitListener() )
{
UnInitDirectSound() ;
return FALSE ;
}
// Call a function to set up secondary sound buffers for the "ouch" sound
if ( !InitOuchBuffer() )
{
UnInitDirectSound() ;
return FALSE ;
}
// Call a function to set up secondary sound buffers for the "Doppler" sound
if ( !InitDopplerBuffer() )
{
UnInitDirectSound() ;
return FALSE ;
}
// Call a function to set up secondary sound buffers for the "Dance" sound
if ( !InitDanceBuffer() )
{
UnInitDirectSound() ;
return FALSE ;
}
// Call a function to set up secondary sound buffers for the "Cone" sound
if ( !InitConeBuffer() )
{
UnInitDirectSound() ;
return FALSE ;
}
return TRUE ;
}
/******************************************************************************
FUNCTION: DSActive
This function is called when the application becomes active. It replays the
sounds that are constantly playing.
PARAMETERS:
None
RETURNS:
None
******************************************************************************/
void DSActive( void )
{
g_bDSActive = TRUE ;
if ( g_lpDSBufferDoppler )
PlayDoppler() ;
if ( g_lpDSBufferCone )
PlayCone() ;
}
/******************************************************************************
FUNCTION: DSInactive
This function is called when the application becomes inactive.
PARAMETERS:
None
RETURNS:
None
******************************************************************************/
void DSInactive( void )
{
// This variable is set false so that we know not to bother restoring
// buffers for the moment.
g_bDSActive = FALSE ;
}
/******************************************************************************
FUNCTION: InitListener
This function queries the primary sound buffer object for the
IDirectSound3Dlistener interface. It then sets up some settings for the
listner.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitListener( void )
{
// Query for the IDirectSound3DListener interface.
if ( FAILED( g_lpDSBufferPrimary->QueryInterface(
IID_IDirectSound3DListener, (void**) &g_lpDS3dListener ) ) )
return FALSE ;
// This sets the distance factor to 1 which is actually the default, however
// you could adjust this value to magnify or lessen the muting effect
// of distance. In general DirectSound is set up to behave like the real
// world where one unit is one meter. This demo then has a one to one
// ratio of meters to pixels.
g_lpDS3dListener->SetDistanceFactor( (D3DVALUE) 1, DS3D_DEFERRED ) ;
// The roll-off factor by default is 1. However with a distance factor
// of one, and a pixel==one meter situation, the roll-off of one would
// make things too quiet. By setting roll-off to 1/100 of the default
// sounds are again loud enough. This shows how these settings are
// relative, and can be adjusted at will.
g_lpDS3dListener->SetRolloffFactor( (D3DVALUE) .01, DS3D_DEFERRED ) ;
// Set up the initial listener orientation. Throughout we will be
// adjusting the listener orientation as per user mouse input. However,
// we will always keep the top of the head pointed in the same direction.
g_lpDS3dListener->SetOrientation( 0, 1, 0, 0, 0, 1, DS3D_DEFERRED ) ;
// Notice that our previous calls were using the DS3D_DEFERRED setting.
// This call commits those settings in one action, which is more efficient
// then changing them one at a time.
g_lpDS3dListener->CommitDeferredSettings() ;
return TRUE ;
}
/******************************************************************************
FUNCTION: InitOuchBuffer
This function creates four secondary sound buffers for the "ouch" sound.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitOuchBuffer( void )
{
HRSRC hrsrc ;
HGLOBAL hgRes ;
DWORD dwSize ;
int nLoop ;
// Find and load the user defined resource for the "ouch" wave file
hrsrc = FindResource( NULL, MAKEINTRESOURCE( IDR_OUCH ), "WAVE" ) ;
hgRes = LoadResource( NULL, hrsrc ) ;
dwSize = SizeofResource( NULL, hrsrc ) ;
// Call our function WavToStaticBuffer, so that it can create a buffer for
// us.
g_lpDSBufferOuch[0] = WavToStaticBuffer( (LPBYTE) hgRes, dwSize, NULL ) ;
if ( !g_lpDSBufferOuch[0] )
return NULL ;
// Make several duplicate buffers using the same actual sound data. This
// is an efficient way of having multiple sound buffers that can be played
// autonomously without taking up more memory for the sounds.
for ( nLoop = 0 ; nLoop < ( NUMOUCHES-1 ) ; nLoop++ )
{
if ( FAILED( g_lpDSound->DuplicateSoundBuffer( g_lpDSBufferOuch[0],
&g_lpDSBufferOuch[1+nLoop] ) ) )
{
g_lpDSBufferOuch[0]->Release() ;
}
}
// Query interface for the IDirectSound3DBuffer interfaces for our four
// sound buffers. These interfaces will be used for the 3D capabilities
// of the sounds.
for ( nLoop = 0 ; nLoop < NUMOUCHES ; nLoop++ )
{
if ( FAILED( g_lpDSBufferOuch[nLoop]->QueryInterface(
IID_IDirectSound3DBuffer, (void **) &g_lpDS3DBufferOuch[nLoop] ) ) )
{
return NULL ;
}
}
return TRUE ;
}
/******************************************************************************
FUNCTION: InitDopplerBuffer
This function creates a secondary sound buffer for the "Doppler" sound.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitDopplerBuffer( void )
{
HRSRC hrsrc ;
HGLOBAL hgRes ;
DWORD dwSize ;
// Find and load the user defined resource for the Doppler sound
hrsrc = FindResource( NULL, MAKEINTRESOURCE( IDR_DOPPLER ), "WAVE" ) ;
hgRes = LoadResource( NULL, hrsrc ) ;
dwSize = SizeofResource( NULL, hrsrc ) ;
// Pass a pointer to the wav data to our function to create a secondary
// sound buffer for the sound.
g_lpDSBufferDoppler = WavToStaticBuffer( (LPBYTE) hgRes, dwSize, NULL ) ;
if ( !g_lpDSBufferOuch )
return NULL ;
// Query interface for the IDirectSound3DBuffer. This interface is used
// to implement the 3D features for this sound.
if ( FAILED( g_lpDSBufferDoppler->QueryInterface( IID_IDirectSound3DBuffer,
(void **) &g_lpDS3DBufferDoppler ) ) )
{
return NULL ;
}
// Set this sounds velocity. This is a constant. The position of the
// sound source is changed periodically by the demo, causing the Doppler
// effect. Try changing the velocity values to see how it affects the sound
g_lpDS3DBufferDoppler->SetVelocity( 20, 20, 0, DS3D_IMMEDIATE ) ;
return TRUE ;
}
/******************************************************************************
FUNCTION: InitDanceBuffer
This function creates a secondary sound buffer for the "Dance" sound.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitDanceBuffer( void )
{
HRSRC hrsrc ;
HGLOBAL hgRes ;
DWORD dwSize ;
// Find and load the user defined resource for the Dance sound
hrsrc = FindResource( NULL, MAKEINTRESOURCE( IDR_DANCE ), "WAVE" ) ;
hgRes = LoadResource( NULL, hrsrc ) ;
dwSize = SizeofResource( NULL, hrsrc ) ;
// Pass a pointer to the wav data to our function to create a secondary
// sound buffer for the sound.
g_lpDSBufferDance = WavToStaticBuffer( (LPBYTE) hgRes, dwSize, NULL ) ;
if ( !g_lpDSBufferDance )
return NULL ;
// Query interface for the IDirectSound3DBuffer. This interface is used
// to implement the 3D features for this sound.
if ( FAILED( g_lpDSBufferDance->QueryInterface( IID_IDirectSound3DBuffer,
(void **) &g_lpDS3DBufferDance ) ) )
{
return NULL ;
}
return TRUE ;
}
/******************************************************************************
FUNCTION: InitConeBuffer
This function creates a secondary sound buffer for the "Cone" sound.
PARAMETERS:
None
RETURNS:
Success or Failure
******************************************************************************/
BOOL InitConeBuffer( void )
{
HRSRC hrsrc ;
HGLOBAL hgRes ;
DWORD dwSize ;
// Find and load the user defined resource for the "Cone" sound
hrsrc = FindResource( NULL, MAKEINTRESOURCE( IDR_CONE ), "WAVE" ) ;
hgRes = LoadResource( NULL, hrsrc ) ;
dwSize = SizeofResource( NULL, hrsrc ) ;
// Pass the data to our function which will create a static buffer for it
g_lpDSBufferCone = WavToStaticBuffer( (LPBYTE) hgRes, dwSize, NULL ) ;
if ( !g_lpDSBufferCone )
return NULL ;
// QueryInterface for the IDirectSound3DBuffer. This buffer is used for the
// 3d features we will apply to the cone effect.
if ( FAILED( g_lpDSBufferCone->QueryInterface( IID_IDirectSound3DBuffer,
(void **) &g_lpDS3DBufferCone ) ) )
{
return NULL ;
}
// Set up the angles for the sound. The demo will constantly rotate the
// orientation
g_lpDS3DBufferCone->SetConeAngles( 90, 360, DS3D_DEFERRED ) ;
g_lpDS3DBufferCone->SetConeOutsideVolume( DSBVOLUME_MIN/4, DS3D_DEFERRED ) ;
// Once again, the settings are deferred, so now we commit them
g_lpDS3dListener->CommitDeferredSettings() ;
return TRUE ;
}
/******************************************************************************
FUNCTION: WavToStaticBuffer
This function takes a buffer which holds a wav file, and creates a secondary
static sound buffer for the wav. It then loads the data from the buffer into
the static buffer. This function uses the multimedia functions (mm) to parse
the wave data. It would be a very simple task to extend this function to read
a WAV file.
PARAMETERS:
lpBuffer -- Pointer to a buffer containing wave data
dwSize -- size of buffer
lpdsBuffer -- pointer to an existing IDirectSoundBuffer interface. Pass NULL
if a new interface should be created. Otherwise, the data will
be stored with this interface.
RETURNS:
A pointer to the IDirectSoundBuffer interface, or NULL if it failed
******************************************************************************/
LPDIRECTSOUNDBUFFER WavToStaticBuffer( LPBYTE lpBuffer, DWORD dwSize,
LPDIRECTSOUNDBUFFER lpdsBuffer )
{
MMIOINFO mmIOInfo ;
HMMIO mmioWave ;
MMCKINFO mmckinfoParent, mmckinfoSubchunk ;
WAVEFORMATEX wfPCM ;
char *lpFile = (char *) lpBuffer ;
HRESULT hr ;
BOOL bNewBuffer = FALSE ;
DSBUFFERDESC dsBufferDesc ;
LPBYTE lpvAudio1 ;
LPBYTE lpvAudio2 ;
DWORD dwWriteBytes1 ;
DWORD dwWriteBytes2 ;
// Set the MMIOINFO structure up for reading a multimedia WAV file from
// memory.
memset( &mmIOInfo, sizeof( MMIOINFO ), 0 ) ;
mmIOInfo.pIOProc = NULL ;
mmIOInfo.fccIOProc = FOURCC_MEM ;
mmIOInfo.pchBuffer = lpFile ;
mmIOInfo.cchBuffer = dwSize ;
// Open the wave data using the mm functions
mmioWave = mmioOpen( NULL, &mmIOInfo, MMIO_READWRITE ) ;
if ( !mmioWave )
return NULL ;
// Descend to find a "WAVE" block, if this fails then the data is not
// WAV data.
mmckinfoParent.fccType = mmioFOURCC( 'W', 'A', 'V', 'E' ) ;
if ( mmioDescend( mmioWave, &mmckinfoParent, NULL, MMIO_FINDRIFF ) )
{
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Descend again to the "fmt " block and retrieve the format information
mmckinfoSubchunk.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ) ;
if ( mmioDescend( mmioWave, &mmckinfoSubchunk, &mmckinfoParent,
MMIO_FINDCHUNK ) )
{
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// This line actually reads the data from the "fmt " chunk, this data
// should be in the form of a WAVEFORMATEX structure
if ( mmioRead( mmioWave, (char *) &wfPCM, mmckinfoSubchunk.cksize ) == -1 )
{
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Step out a layer... think of the mm functions as step in and out of
// hierarchies of "chunks" of information
mmioAscend( mmioWave, &mmckinfoSubchunk, 0 ) ;
// Find the "data" subchunk
mmckinfoSubchunk.ckid = mmioFOURCC( 'd', 'a', 't', 'a' ) ;
if ( mmioDescend( mmioWave, &mmckinfoSubchunk, &mmckinfoParent,
MMIO_FINDCHUNK ) )
{
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// At this point we have succeeded in finding the data for the WAV file so
// we need to create a DirectSoundBuffer if one wasn't passed.
if ( !lpdsBuffer )
{
// Set up DSBUFFERDESC structure for a static secondary buffer.
dsBufferDesc.dwSize = sizeof( DSBUFFERDESC ) ;
dsBufferDesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_STATIC ;
// Buffer size retrieved from the mmckinfo structure for the data
// portion of the wav
dsBufferDesc.dwBufferBytes = mmckinfoSubchunk.cksize ;
dsBufferDesc.dwReserved = 0 ;
dsBufferDesc.lpwfxFormat = &wfPCM ;
// Create buffer.
if ( FAILED( g_lpDSound->CreateSoundBuffer( &dsBufferDesc, &lpdsBuffer,
NULL ) ) )
{
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Did we create a new buffer
bNewBuffer = TRUE ;
}
// Lock the buffer for the DirectSoundBuffer object
hr = lpdsBuffer->Lock( 0, 0, (void **) &lpvAudio1, &dwWriteBytes1,
(void **) &lpvAudio2, &dwWriteBytes2, DSBLOCK_ENTIREBUFFER ) ;
if ( hr == DSERR_BUFFERLOST )
{
// If the buffer was lost try restoring it and lock again
lpdsBuffer->Restore() ;
hr = lpdsBuffer->Lock( 0, 0, (void **) &lpvAudio1, &dwWriteBytes1,
(void **) &lpvAudio2, &dwWriteBytes2, DSBLOCK_ENTIREBUFFER ) ;
}
if ( FAILED( hr ) )
{
if ( bNewBuffer )
lpdsBuffer->Release() ;
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
if ( dwWriteBytes1 != mmckinfoSubchunk.cksize )
{
if ( bNewBuffer )
lpdsBuffer->Release() ;
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Read the data directly into the locked buffer
if ( mmioRead( mmioWave, ( char* ) lpvAudio1, mmckinfoSubchunk.cksize )
== -1 )
{
if ( bNewBuffer )
lpdsBuffer->Release() ;
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Unlock the buffer
if ( FAILED( lpdsBuffer->Unlock( (void *) lpvAudio1, dwWriteBytes1,
(void *) lpvAudio2, dwWriteBytes2 ) ) )
{
if ( bNewBuffer )
lpdsBuffer->Release() ;
mmioClose( mmioWave, 0 ) ;
return NULL ;
}
// Close the multimedia object
mmioClose( mmioWave, 0 ) ;
return lpdsBuffer ;
}
/******************************************************************************
FUNCTION: RestoreBufferData
This function will reload a resource and attempt to restore the buffer for a
direct sound buffer.
PARAMETERS:
lpdsBuffer -- Existing direct sound interface
nResource -- Resource ID of the user defined resource holding the WAV data
RETURNS:
Returns success or failure
******************************************************************************/
BOOL RestoreBufferData( LPDIRECTSOUNDBUFFER lpdsBuffer, UINT nResource )
{
HRSRC hrsrc ;
HGLOBAL hgRes ;
DWORD dwSize ;
// Don't bother trying if the application window is not in the foreground
if ( !g_bDSActive )
return FALSE ;
// Find and load the resources
hrsrc = FindResource( NULL, MAKEINTRESOURCE( nResource ), "WAVE" ) ;
hgRes = LoadResource( NULL, hrsrc ) ;
dwSize = SizeofResource( NULL, hrsrc ) ;
// Copy the data from the resource into our buffer using our nifty function
lpdsBuffer = WavToStaticBuffer( (LPBYTE) hgRes, dwSize, lpdsBuffer ) ;
if ( !lpdsBuffer )
return FALSE ;
return TRUE ;
}
/******************************************************************************
FUNCTION: SetListenerPos
This function sets the position of the listener object in 3D space. It also
sets the orientation. The data is taken from an application defined structure
called DemoListener.
PARAMETERS:
pDL -- Pointer to the DemoListener structure containing the position info
bDeferred -- Defer changes?
RETURNS:
Returns success or failure
******************************************************************************/
BOOL SetListenerPos( DemoListener *pDL, BOOL bDeferred )
{
// Set the position of the listener
if ( FAILED( g_lpDS3dListener->SetPosition( (D3DVALUE) pDL->m_nXPos,
(D3DVALUE) pDL->m_nYPos, 0, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ) )
return FALSE ;
// Set orientation of the listener
return !FAILED( g_lpDS3dListener->SetOrientation( pDL->m_fnFaceX,
pDL->m_fnFaceY, 0, 0, 0, -1, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ) ;
}
/******************************************************************************
FUNCTION: SetDopplerPos
This function sets the position of the Doppler object. The data is taken from
an application defined structure called DemoDoppler.
PARAMETERS:
pDD -- Pointer to the DemoDoppler structure containing the position info
bDeferred -- Defer changes?
RETURNS:
Returns success or failure
******************************************************************************/
BOOL SetDopplerPos( DemoDoppler *pDD, BOOL bDeferred )
{
// Set the position of the Doppler object
if ( FAILED( g_lpDS3DBufferDoppler->SetPosition( (D3DVALUE) pDD->m_nXPos,
(D3DVALUE) pDD->m_nYPos, 0, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ) )
return FALSE ;
return TRUE ;
}
/******************************************************************************
FUNCTION: PlayDoppler
Play the doppler object, and restore it if the buffer has been lost.
PARAMETERS:
void
RETURNS:
void
******************************************************************************/
void PlayDoppler( void )
{
HRESULT hr ;
// Play
hr = g_lpDSBufferDoppler->Play( 0, 0, DSBPLAY_LOOPING ) ;
if ( hr == DSERR_BUFFERLOST )
{
// Failed? Restore.
if ( RestoreBufferData( g_lpDSBufferDoppler, IDR_DOPPLER ) )
{
// Play again...
g_lpDSBufferDoppler->Play( 0, 0, DSBPLAY_LOOPING ) ;
}
}
}
/******************************************************************************
FUNCTION: SetConePos
Set the position of the Cone object in DirectSound 3D space.
PARAMETERS:
void
RETURNS:
void
******************************************************************************/
BOOL SetConePos( DemoCone *pDLS, BOOL bDeferred )
{
// Set the position. The demo currently locks the position.
if ( FAILED( g_lpDS3DBufferCone->SetPosition( (D3DVALUE) pDLS->m_nXPos,
(D3DVALUE) pDLS->m_nYPos, 0, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ) )
return FALSE ;
// Set the orientation.
return !FAILED( g_lpDS3DBufferCone->SetConeOrientation( pDLS->m_fnFaceX,
pDLS->m_fnFaceY, 0, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ) ;
}
/******************************************************************************
FUNCTION: PlayCone
Play the cone object
PARAMETERS:
void
RETURNS:
void
******************************************************************************/
void PlayCone( void )
{
HRESULT hr ;
// Play
hr = g_lpDSBufferCone->Play( 0, 0, DSBPLAY_LOOPING ) ;
if ( hr == DSERR_BUFFERLOST )
{
// buffer lost? Restore.
if ( RestoreBufferData( g_lpDSBufferCone, IDR_CONE ) )
{
// Play again
g_lpDSBufferCone->Play( 0, 0, DSBPLAY_LOOPING ) ;
}
}
}
/******************************************************************************
FUNCTION: PlayOuch
Play the ouch object. A little more complicated then the other "Play"
functions because it plays the first available buffer of 4.
PARAMETERS:
nX -- X position of the source
nY -- Y position of the source
bDeferred -- Defer the changes?
RETURNS:
none
******************************************************************************/
void PlayOuch( int nX, int nY, BOOL bDeferred )
{
DWORD dwStatus ;
int nLoop ;
HRESULT hr ;
// Loop through each buffer and check status playing.
for ( nLoop = 0 ; nLoop < NUMOUCHES ; nLoop++ )
{
if ( FAILED( g_lpDSBufferOuch[nLoop]->GetStatus( &dwStatus ) ) )
continue ;
// If not playing... then this is the one that we will play.
if ( !( dwStatus & DSBSTATUS_PLAYING ) )
{
// Set the position
g_lpDS3DBufferOuch[nLoop]->SetPosition( (D3DVALUE) nX, (D3DVALUE) nY,
0, bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ;
// Play it
hr = g_lpDSBufferOuch[nLoop]->Play( 0, 0, 0 ) ;
if ( hr == DSERR_BUFFERLOST )
{
// Buffer lost? Restore.
if ( RestoreBufferData( g_lpDSBufferOuch[nLoop], IDR_OUCH ) )
{
// Play
g_lpDSBufferOuch[nLoop]->Play( 0, 0, 0 ) ;
}
}
break ;
}
}
}
/******************************************************************************
FUNCTION: PlayDance
Play the "Dance" object.
PARAMETERS:
nX -- X position of the source
nY -- Y position of the source
bDeferred -- Defer the changes?
RETURNS:
none
******************************************************************************/
void PlayDance( int nX, int nY, BOOL bDeferred )
{
HRESULT hr ;
// Set the object's position
g_lpDS3DBufferDance->SetPosition( (D3DVALUE) nX, (D3DVALUE) nY, 0,
bDeferred?DS3D_DEFERRED:DS3D_IMMEDIATE ) ;
// Play the sound
hr = g_lpDSBufferDance->Play( 0, 0, 0 ) ;
if ( hr == DSERR_BUFFERLOST )
{
if ( RestoreBufferData( g_lpDSBufferDance, IDR_DANCE ) )
{
g_lpDSBufferDance->Play( 0, 0, 0 ) ;
}
}
}
/******************************************************************************
FUNCTION: StopDance
Stop the "Dance" object. It is important that we can stop the "Dance" sound
when the user lets go of the button.
PARAMETERS:
none
RETURNS:
none
******************************************************************************/
void StopDance( void )
{
// Stop
g_lpDSBufferDance->Stop() ;
}
/******************************************************************************
FUNCTION: CommitChanges
This function will commit deferred changes for DirectSound. This is an
important feature because it allows you to make multiple changes at once which
is more effecient.
PARAMETERS:
none
RETURNS:
none
******************************************************************************/
void CommitChanges( void )
{
g_lpDS3dListener->CommitDeferredSettings() ;
}
/******************************************************************************
FUNCTION: UnInitDirectSound
Un init all of the DirectSound stuff.
PARAMETERS:
none
RETURNS:
none
******************************************************************************/
void UnInitDirectSound( void )
{
int nLoop ;
// Release
if ( g_lpDS3DBufferCone )
g_lpDS3DBufferCone->Release() ;
// Release
if ( g_lpDS3DBufferDance )
g_lpDS3DBufferDance->Release() ;
// Release
if ( g_lpDS3DBufferDoppler )
g_lpDS3DBufferDoppler->Release() ;
// Release
if ( g_lpDSBufferCone )
g_lpDSBufferCone->Release() ;
// Release
if ( g_lpDSBufferDance )
g_lpDSBufferDance->Release() ;
// Release
if ( g_lpDSBufferDoppler )
g_lpDSBufferDoppler->Release() ;
// Loop and release
for ( nLoop = 0 ; nLoop < NUMOUCHES ; nLoop++ )
{
if ( g_lpDS3DBufferOuch[nLoop] )
g_lpDS3DBufferOuch[nLoop]->Release() ;
if ( g_lpDSBufferOuch[nLoop] )
g_lpDSBufferOuch[nLoop]->Release() ;
}
// Release
if ( g_lpDS3dListener )
g_lpDS3dListener->Release() ;
// Release -- talk about your cut and paste comments
if ( g_lpDSBufferPrimary )
g_lpDSBufferPrimary->Release() ;
// Release
if ( g_lpDSound )
g_lpDSound->Release() ;
}