www.pudn.com > GameEngine.rar > GameEngine_Sound.cpp, change:2005-10-19,size:5954b
#include "..\GameEngine_Common.h"
#include "GameEngine_Sound.h"
/******************************************************/
/*******CGameEngine_SoundManager类的函数实现代码*******/
/******************************************************/
//先初始化m_pSoundManager,否则会产生链接错误
CGameEngine_SoundManager* CGameEngine_SoundManager::m_pSoundManager=NULL;
CGameEngine_SoundManager::CGameEngine_SoundManager(){
m_pSoundManager=this; //构造函数初始化
m_pDirectSound=NULL;
}
CGameEngine_SoundManager::~CGameEngine_SoundManager(){
SafeRelease(m_pDirectSound);
}
//初始化管理器
bool CGameEngine_SoundManager::Init(HWND hWnd,DWORD dwCoopLevel){
//创建IDirectSound对象
if(FAILED(DirectSoundCreate8(NULL,&m_pDirectSound,NULL)))
return false;
//设置协调级别(DSSCL_NORMAL会自动设置一个主缓冲区)
if(FAILED(m_pDirectSound->SetCooperativeLevel(hWnd,dwCoopLevel)))
return false;
return true;
}
//设置主缓冲区格式
bool CGameEngine_SoundManager::SetPrimaryBufferFormat(
WORD wChannels,
DWORD dwSamplesPerSec,
WORD wBitsPerSample){
if(m_pDirectSound==NULL)
return false;
//填写主缓冲区的描述结构体
DSBUFFERDESC bufferDesc;
ZeroMemory(&bufferDesc,sizeof(DSBUFFERDESC));
bufferDesc.dwSize=sizeof(DSBUFFERDESC);
bufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER; //表示主缓冲区
bufferDesc.dwBufferBytes=0; //主缓冲区必须设置为0
bufferDesc.lpwfxFormat=NULL; //主缓冲区必须设置为NULL
//取得主缓冲区
IDirectSoundBuffer* pDirectSoundBuf=NULL;
if(FAILED(m_pDirectSound->CreateSoundBuffer(&bufferDesc,&pDirectSoundBuf,NULL)))
return false;
//设置主缓冲区的自定义格式
WAVEFORMATEX waveFormat;
ZeroMemory(&waveFormat,sizeof(WAVEFORMATEX));
waveFormat.wFormatTag=WAVE_FORMAT_PCM;
waveFormat.nChannels=wChannels;
waveFormat.nSamplesPerSec=dwSamplesPerSec;
waveFormat.wBitsPerSample=wBitsPerSample;
waveFormat.nBlockAlign=(waveFormat.wBitsPerSample / 8) * waveFormat.nChannels;
waveFormat.nAvgBytesPerSec=waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
if(FAILED(pDirectSoundBuf->SetFormat(&waveFormat)))
return false;
//释放主缓冲区接口对象(已在声卡内存分配好主缓冲区)
SafeRelease(pDirectSoundBuf);
return true;
}
/**************************************************/
/********CGameEngine_Sound类的函数实现代码*********/
/**************************************************/
CGameEngine_Sound::CGameEngine_Sound(){
}
CGameEngine_Sound::~CGameEngine_Sound(){
SafeRelease(m_pDirectSoundBuf8);
}
bool CGameEngine_Sound::LoadWaveFile(TCHAR* szWaveFile){
//打开Wave文件
FILE *fp;
if((fp=fopen(szWaveFile,"rb"))==NULL)
return false;
//取得次缓冲区
if(!GetSecondaryBuffer(fp)){
fclose(fp); //关闭Wave文件
return false;
}
//读入Wave声音数据
if(!LoadDataInBuffer(fp)){
fclose(fp);
return false;
}
//关闭文件
fclose(fp);
return true;
}
bool CGameEngine_Sound::GetSecondaryBuffer(FILE *fp){
//读文件头的Wav格式
sWaveHeader* pWaveHeader=new sWaveHeader();
fseek(fp,0,SEEK_SET);
fread(pWaveHeader,1,sizeof(sWaveHeader),fp);
//检查是否为Wav文件
if(memcmp(pWaveHeader->RiffID, "RIFF", 4) ||
memcmp(pWaveHeader->WaveID, "WAVE", 4) ||
memcmp(pWaveHeader->FormatID, "fmt ", 4) ||
memcmp(pWaveHeader->DataID, "data",4))
return false;
//设置声音格式
WAVEFORMATEX waveFormat;
ZeroMemory(&waveFormat,sizeof(WAVEFORMATEX));
waveFormat.wFormatTag=WAVE_FORMAT_PCM;
waveFormat.nChannels=pWaveHeader->Channels; //声道数
waveFormat.nSamplesPerSec=pWaveHeader->SampleRate; //播放频率
waveFormat.wBitsPerSample=pWaveHeader->BitsPerSample; //位数
waveFormat.nBlockAlign=(waveFormat.wBitsPerSample / 8) * waveFormat.nChannels;
waveFormat.nAvgBytesPerSec=waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
//填写缓冲区描述结构体(音量可控制、声音文件大小和声音格式)
DSBUFFERDESC bufferDesc;
ZeroMemory(&bufferDesc,sizeof(DSBUFFERDESC));
bufferDesc.dwSize=sizeof(DSBUFFERDESC);
bufferDesc.dwFlags=DSBCAPS_CTRLVOLUME|DSBCAPS_GLOBALFOCUS|DSBCAPS_STATIC;
bufferDesc.dwBufferBytes=pWaveHeader->DataSize;
bufferDesc.lpwfxFormat=&waveFormat;
//先取得IDirectSoundBuffer缓冲区接口对象
IDirectSoundBuffer* pDirectSoundBuf=NULL;
if(FAILED(CGameEngine_SoundManager::GetSoundManager()->GetDirectSound()->CreateSoundBuffer(&bufferDesc,&pDirectSoundBuf,NULL)))
return false;
//再取得IDirectSoundBuffer8缓冲区接口对象
if(FAILED(pDirectSoundBuf->QueryInterface(IID_IDirectSoundBuffer8,
(void**)&m_pDirectSoundBuf8))){
pDirectSoundBuf->Release();
return false;
}
delete pWaveHeader;
return true;
}
bool CGameEngine_Sound::LoadDataInBuffer(FILE* fp){
//读Wave文件大小
sWaveHeader* pWaveHeader=new sWaveHeader();
fseek(fp,0,SEEK_SET);
fread(pWaveHeader,1,sizeof(sWaveHeader),fp);
//锁定缓冲区
BYTE *pSoundPtr1=NULL;
BYTE *pSoundPtr2=NULL;
DWORD dwSoundSize1,dwSoundSize2;
if(FAILED(m_pDirectSoundBuf8->Lock(0,pWaveHeader->DataSize,
(void**)&pSoundPtr1, &dwSoundSize1,
(void**)&pSoundPtr2, &dwSoundSize2,0)))
return false;
//读数据到缓冲区
fread(pSoundPtr1,1,dwSoundSize1,fp);
if(pSoundPtr2 != NULL)
fread(pSoundPtr2,1,dwSoundSize2,fp);
//解锁
m_pDirectSoundBuf8->Unlock(pSoundPtr1,dwSoundSize1,pSoundPtr2,dwSoundSize2);
delete pWaveHeader;
return true;
}
bool CGameEngine_Sound::Play(bool bLoop){
if(m_pDirectSoundBuf8==NULL)
return false;
m_pDirectSoundBuf8->SetCurrentPosition(0);
if(FAILED(m_pDirectSoundBuf8->Play(0,0,bLoop?true:false)))
return false;
return true;
}
bool CGameEngine_Sound::SetVolume(long lVolume){
if(FAILED(m_pDirectSoundBuf8->SetVolume(lVolume)))
return false;
return true;
}
bool CGameEngine_Sound::Stop(){
if(FAILED(m_pDirectSoundBuf8->Stop()))
return false;
return true;
}