www.pudn.com > 林海血原源代码.zip > Audio.cpp
// Audio.cpp: implementation of the CAudio class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Audio.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
void CSound::
Set3DPos(float x, float y, float z)
{ ds3DBuffer->SetPosition(x, y, -z, DS3D_IMMEDIATE); }
//------------------------------------------------------------------//
//- void CSound::Set3DDistances(float, float) -----------------------//
//------------------------------------------------------------------//
//- Sets the max, and minimum distance for a CSound to be heard. -//
//------------------------------------------------------------------//
void CSound::
Set3DDistances(float minDistance, float maxDistance)
{
DS3DBUFFER dsBufferParams;
dsBufferParams.flMinDistance= minDistance; //Sets the minimum distance
dsBufferParams.flMaxDistance= maxDistance; //Sets the maximum distance
//Now, set the parameters for our CSound's 3D buffer
if(ds3DBuffer)
ds3DBuffer->SetAllParameters(&dsBufferParams, DS3D_IMMEDIATE);
}
//------------------------------------------------------------------//
//- void CSound::Shutdown(void) -------------------------------------//
//------------------------------------------------------------------//
//- Shutdown the CSound, I originally had this in the destructor, -//
//- but it was acting screwy... so I now it has it's own function. -//
//------------------------------------------------------------------//
void CSound::
Shutdown(void)
{
if(dmSegment!=NULL)
{
dmSegment->Release();
dmSegment= NULL;
}
if(ds3DBuffer!=NULL)
{
ds3DBuffer->Release();
ds3DBuffer= NULL;
}
}
//------------------------------------------------------------------//
//- bool CAudio::Init(void) ----------------------------------//
//------------------------------------------------------------------//
//- Initiates DirectAudio. This function must be called by the -//
//- programmer, though the shutdown function is automatically -//
//- called by the destructor (as, not shutting down DAudio -//
//- correctly can have some bad consequences). -//
//------------------------------------------------------------------//
bool CAudio::
Init(HWND hwnd,unsigned int MaxNumber)
{
HRESULT hr;
WCHAR wcharStr[MAX_PATH];
char pathStr[MAX_PATH];
CoInitialize(NULL);
//Create the loader object, load it... and load it good.
hr= CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,
IID_IDirectMusicLoader8, (void**)&dmLoader);
if(FAILED(hr))
{
MessageBox(hwnd, "Unable to create main DirectAudio file loader", "ERROR", MB_OK);
return false;
}
//Create the performance object for that.... performance stuff.
hr= CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
IID_IDirectMusicPerformance8, (void**)&dmPerformance);
if(FAILED(hr))
{
MessageBox(hwnd, "Unable to create main DirectAudio performance object", "ERROR", MB_OK);
Shutdown();
return false;
}
//Initialize the performance with the standard audio path information
dmPerformance->InitAudio(NULL, NULL, hwnd, DMUS_APATH_DYNAMIC_3D , 64,
DMUS_AUDIOF_ALL, NULL);
//Create a simple 3D audiopath
hr= dmPerformance->CreateStandardAudioPath(DMUS_APATH_DYNAMIC_3D,
64, TRUE, &dm3DAudioPath);
if(FAILED(hr))
{
MessageBox(hwnd, "Unable to create the DirectAudio audio path", "ERROR", MB_OK);
Shutdown();
return false;
}
//Retrieve the listener information from our audiopath
hr= dm3DAudioPath->GetObjectInPath(0, DMUS_PATH_PRIMARY_BUFFER, 0, GUID_NULL, 0,
IID_IDirectSound3DListener8,
(void**)&ds3DListener);
if(FAILED(hr))
{
MessageBox(hwnd, "Unable to recieve listener from audio path", "ERROR", MB_OK);
Shutdown();
return false;
}
//Get the listener information
dsListenerParams.dwSize= sizeof(DS3DLISTENER);
ds3DListener->GetAllParameters(&dsListenerParams);
//Set our default position of listener (since the listener shouldn't be moving all too much
dsListenerParams.vPosition.x= 0.0f;
dsListenerParams.vPosition.y= 0.0f;
dsListenerParams.vPosition.z= 0.0f;
ds3DListener->SetAllParameters(&dsListenerParams, DS3D_IMMEDIATE);
//Retrieve the current directory
GetCurrentDirectory(MAX_PATH, pathStr);
//Convert the file name to a unicode string... as thats what COM needs
MultiByteToWideChar(CP_ACP, 0, pathStr, -1, wcharStr, MAX_PATH);
//Set the search directory
dmLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wcharStr, FALSE);
m_MaxNum=MaxNumber;
pSound=new CSound[m_MaxNum];
return true;
}
//------------------------------------------------------------------//
//- void CAudio::DAudioShutdown(void) ------------------------//
//------------------------------------------------------------------//
//- Shuts down DirectAudio. This function is called automatically -//
//- by the CAudio destructor, hence the reason why this -//
//- function is private. -//
//------------------------------------------------------------------//
void CAudio::Shutdown(void)
{
for(unsigned int i=0;i < m_MaxNum;i++)
{
pSound[i].Shutdown();
}
delete [] pSound;
//Shut down the direct CSound listener(player) information
if(ds3DListener!=NULL)
ds3DListener->Release();
//Shut down the direct music performance information
if(dmPerformance!=NULL)
{
dmPerformance->Stop(NULL, NULL, 0, 0);
dmPerformance->CloseDown();
dmPerformance->Release();
}
//Shut down the direct music audiopath
if(dm3DAudioPath!=NULL)
dm3DAudioPath->Release();
//Shut down the direct music loader
if(dmLoader!=NULL)
dmLoader->Release();
//Uninitialize COM (*MUST* be done, or you're asking for trouble)
CoUninitialize();
}
//------------------------------------------------------------------//
//- bool CAudio::Create(CSound*, char*, bool) -----------------//
//------------------------------------------------------------------//
//- Use the audio manager to create an individual CSound effect from-//
//- a file. -//
//------------------------------------------------------------------//
bool CAudio::
Create(unsigned int NumOfSound, char* filename, bool is3DSound)
{
if(NumOfSound>(m_MaxNum-1))return false;
DS3DBUFFER dsBufferParams;
HRESULT hr;
WCHAR wcharStr[MAX_PATH];
//Convert the file name to the string that DirectAudio needs
MultiByteToWideChar(CP_ACP, 0, filename, -1, wcharStr, MAX_PATH);
//Load the audio segment from a file
hr= dmLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,
IID_IDirectMusicSegment8,
wcharStr,
(void**)&pSound[NumOfSound].dmSegment);
if(FAILED(hr))
{
return false;
}
//Do code specific for 3D CSounds
if(is3DSound)
{
//Get the 3D buffer, and audio path
hr= dm3DAudioPath->GetObjectInPath(DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, 0,
GUID_NULL, 0, IID_IDirectSound3DBuffer,
(void**)&pSound[NumOfSound].ds3DBuffer);
if(FAILED(hr))
{
return false;
}
//Get the 3D buffer paramters
dsBufferParams.dwSize= sizeof(DS3DBUFFER);
pSound[NumOfSound].ds3DBuffer->GetAllParameters(&dsBufferParams);
//Set some new parameters
dsBufferParams.dwMode= DS3DMODE_HEADRELATIVE; // relative to the listener
pSound[NumOfSound].ds3DBuffer->SetAllParameters(&dsBufferParams, DS3D_IMMEDIATE);
//Set the 3D CSound flag to true
pSound[NumOfSound].is3DSound = true;
}
//Do code specific to non-3D CSounds (background music)
else
{
//Set the 3D buffer to null since we don't need it
pSound[NumOfSound].ds3DBuffer= NULL;
//Set the 3D CSound flag to false, since we don't need it either
pSound[NumOfSound].is3DSound= false;
}
return true;
}
//------------------------------------------------------------------//
//- void CAudio::Play(CSound*, DWORD) -------------------------//
//------------------------------------------------------------------//
//- Play the CSound, and repeat it numRepeats amount of times. -//
//------------------------------------------------------------------//
void CAudio::
Play(unsigned int NumOfSound, DWORD numRepeats)
{
if(NumOfSound>(m_MaxNum-1))return ;
//Set the number of repeats that we want for the specific CSound
pSound[NumOfSound].dmSegment->SetRepeats(numRepeats);
if(pSound[NumOfSound].is3DSound)
{
pSound[NumOfSound].dmSegment->Download(dmPerformance);
//Play the segment using the 3D audio path
dmPerformance->PlaySegmentEx(pSound[NumOfSound].dmSegment, NULL, NULL,
DMUS_SEGF_ALIGN , 0,
NULL, NULL, dm3DAudioPath);
}
else
{
//Download the segment's performance object
pSound[NumOfSound].dmSegment->Download(dmPerformance);
//Play the non-3D CSound segment
dmPerformance->PlaySegmentEx(pSound[NumOfSound].dmSegment, NULL, NULL,
DMUS_SEGF_DEFAULT, 0,
NULL, NULL, NULL);
}
}
//------------------------------------------------------------------//
//- void CAudio::Stop(CSound*) --------------------------------//
//------------------------------------------------------------------//
//- Stop playing the specified CSound. -//
//------------------------------------------------------------------//
void CAudio::
Stop(unsigned int NumOfSound)
{
if(NumOfSound>(m_MaxNum-1)) return ;
dmPerformance->StopEx(pSound[NumOfSound].dmSegment, 0, 0);
}
//------------------------------------------------------------------//
//- void CAudio::SetListenerPos(float, float, float) ---------//
//------------------------------------------------------------------//
//- Set the listener's (player's) position in 3D space. -//
//------------------------------------------------------------------//
void CAudio::
SetListenerPos(float x, float y, float z)
{
//Get the listener parameters
dsListenerParams.dwSize= sizeof(DS3DLISTENER);
ds3DListener->GetAllParameters(&dsListenerParams);
//Set the listener's position in 3D space
dsListenerParams.vPosition.x= x;
dsListenerParams.vPosition.y= y;
dsListenerParams.vPosition.z= -z;
//Set all of the new parameters
ds3DListener->SetAllParameters(&dsListenerParams, DS3D_IMMEDIATE);
}
//------------------------------------------------------------------//
//- void CAudio::SetListenerRolloff(float) -------------------//
//------------------------------------------------------------------//
//- Set the listener's CSound volume rolloff with distance. -//
//------------------------------------------------------------------//
void CAudio::
SetListenerRolloff(float rolloff)
{
if(ds3DListener)
ds3DListener->SetRolloffFactor(rolloff, DS3D_IMMEDIATE);
}
//------------------------------------------------------------------//
//- void CAudio::SetListenerOrientation(float, float, float, float, float, float) -//
//------------------------------------------------------------------//
//- Set the listener's orientation (you may need to implement a -//
//- camera class to use this function correctly). -//
//------------------------------------------------------------------//
void CAudio::
SetListenerOrientation(float forwardX, float forwardY, float forwardZ,
float topX, float topY, float topZ)
{
ds3DListener->SetOrientation(forwardX, forwardY, -forwardZ,
topX, topY, topZ, DS3D_IMMEDIATE);
}