www.gusucode.com > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序 > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序\code\source\GAMELIB\Gp_sound.cpp
//Download by http://www.NewXing.com //******************************************** // DirectSound 相关处理函数 // 创建于2000年2月4日 //******************************************** #include <windows.h> #include <stdio.h> #include <dsound.h> #include <direct.h> #include "gp_init.h" #include "gp_other.h" #include "gp_sound.h" #define WAV_HDR_SIZE 44 #define SND_GATE 0 #define SND_PING 1 #define SND_STATIC 2 #define SND_WALK 3 extern HWND hWnd; BOOL CSound::bExist=false; BOOL CSound::bEnable=false; LPDIRECTSOUND CSound::lpDSound=NULL; LPDIRECTSOUNDBUFFER CSound::lpPrimarySoundBuffer=NULL; CSound::CSound() { DSSoundFX=NULL; } //----------------- //释放声音缓冲区 CSound::~CSound() { if( lpDSound && DSSoundFX ) { _RELEASE( DSSoundFX ); } } //----------------- //初始化声音设备 BOOL CSound::InitDirectSound(HWND hwnd) { if( bExist || bEnable ) return true; if( DirectSoundCreate(NULL,&lpDSound,NULL)!=DS_OK ) { MessageBox(hwnd,"Create DirectSound Failed!\n初始化DirectSound过程中出错!\ 请检查你是否正确的安装了DirectX 5.0以上版本,或有无其他设备正占用声卡!\ 否则你将无法听到声音。","error",MB_OK); bEnable=FALSE; return FALSE; } if( lpDSound->SetCooperativeLevel(hwnd,DSSCL_NORMAL)!=DS_OK) { MessageBox(hwnd,"error on set DirectSound CooperativeLevel\n初始化DirectSound\ 过程中出错!请检查你是否正确的安装了DirectX 5.0以上版本,或有无其他设备正占\ 用声卡!否则你将无法听到声音。","error",MB_OK); bEnable=FALSE; return FALSE; } bEnable = true; bExist=true; return TRUE; // 初始化成功 } //---------------- //创建主声音缓冲区 bool CSound::CreatePrimarySoundBuffer() { if( bExist || !bEnable ) return true; DSBUFFERDESC dsbdesc; WAVEFORMATEX pcmwf; // 设置wave格式结构 memset(&pcmwf, 0, sizeof(WAVEFORMATEX)); pcmwf.wFormatTag = WAVE_FORMAT_PCM; pcmwf.nChannels = 1; pcmwf.nSamplesPerSec = 8000; pcmwf.nBlockAlign = 4; pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; pcmwf.wBitsPerSample = 8; pcmwf.cbSize = 0; // 设置 DSBUFFERDESC 结构 memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out. dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; // 主缓冲区必须是0 dsbdesc.dwBufferBytes = 0; dsbdesc.lpwfxFormat = NULL; // 主缓冲区必须是NULL if( (lpDSound->CreateSoundBuffer(&dsbdesc, &lpPrimarySoundBuffer, NULL)) == DS_OK) { if( (lpPrimarySoundBuffer->SetFormat(&pcmwf)) == DS_OK ) return true; } return false; } //------------- //释放声音设备 void CSound::ReleaseDirectSound(void) { if( !bExist ) return; bExist=false; if( lpDSound != NULL ) { _RELEASE( lpPrimarySoundBuffer ); _RELEASE( lpDSound ); } } //--------------------- //音效开关 void CSound::EnableSound(bool sw) { CSound::bEnable=sw; } //--------------------- //创建一个WAV声音缓冲区 bool CSound::LoadSoundFX(HWND hwnd,char *filename) { if( !bEnable ) return true; DSBUFFERDESC dsbd; //结构 LPWAVEFORMATEX wav; //声音格式 DWORD len; //文件长度 BYTE *buf; //临时缓冲区 LPVOID ptr1; //指针1 LPVOID ptr2; //指针2 DWORD size1; DWORD size2; DWORD BufferSize; //DirectSoundBuffer 大小 FILE *f; long WavLong; if( (f=fopen(filename,"rb"))==NULL ) { MessageBox(hwnd,"error open file",filename,MB_OK); return FALSE; } fseek(f,0x04,SEEK_SET); fread(&WavLong,sizeof(long),1,f); //读取声音数据长度 len=WavLong+WAV_HDR_SIZE; //文件长度 BufferSize=len-WAV_HDR_SIZE-800; //设置缓冲区大小 buf=(BYTE *)malloc(len); if( buf==NULL ) { MessageBox(hwnd,"error buf",filename,MB_OK); return FALSE; } //读取声音数据到临时缓冲区 fseek(f,0l,SEEK_SET); fread(buf,len,1,f); fclose(f); ptr1=buf+20; wav=(LPWAVEFORMATEX)(ptr1); memset(&dsbd,0,sizeof(dsbd)); dsbd.dwSize=sizeof(dsbd); dsbd.dwFlags=DSBCAPS_STATIC; dsbd.dwBufferBytes=len-WAV_HDR_SIZE; dsbd.lpwfxFormat=wav; _RELEASE( DSSoundFX ); if(lpDSound->CreateSoundBuffer(&dsbd,&DSSoundFX,NULL)!=DS_OK) { MessageBox(hwnd,"error createsoundbuffer","error",MB_OK); return FALSE; } if( (DSSoundFX->Lock(0,BufferSize,&ptr1,&size1,&ptr2,&size2,0))!=DS_OK) { MessageBox(hwnd,"error Lock","error",MB_OK); return FALSE; } memcpy(ptr1,buf+WAV_HDR_SIZE,size1); //拷贝数据到声音缓冲区 if(size2) memcpy(ptr2,buf+size1+WAV_HDR_SIZE,size2);//拷贝数据到声音缓冲区 if( DSSoundFX->Unlock(ptr1,size1,ptr2,size2)!=DS_OK) { MessageBox(hwnd,"error UnLock","error",MB_OK); return FALSE; } _FREE(buf); return true; } //------------------------- //功能:播放声音 //参数:loop=-1 循环 void CSound::Play(DWORD loop) { if( bEnable==FALSE || !DSSoundFX ) return; DWORD *Status1=NULL; if( (DSSoundFX->GetStatus(Status1))!=DS_OK ) goto _next; if( *Status1 & DSBSTATUS_PLAYING == DSBSTATUS_PLAYING ) return; _next: DSSoundFX->SetCurrentPosition(0); if( loop==-1 ) loop=DSBPLAY_LOOPING; //循环播放 DSSoundFX->Play(0,0,loop); } //------------------------ //停止播放 void CSound::Stop() { if( bEnable==FALSE || DSSoundFX==NULL ) return; DSSoundFX->Stop(); } //------------------------- //缓冲区是否正在播放 bool CSound::IsPlaying() { if( bEnable==FALSE || DSSoundFX==NULL ) return true; DWORD pos, wpos; DSBCAPS dsbc; memset(&dsbc,0,sizeof(DSBCAPS)); dsbc.dwSize=sizeof(DSBCAPS); if( (DSSoundFX->GetCaps(&dsbc)) != DS_OK ) { MessageBox(hWnd, "DSSoundFX->GetCaps","error",MB_OK); return true; } pos=dsbc.dwBufferBytes; if( (DSSoundFX->GetCurrentPosition(&wpos,NULL)) != DS_OK ) { MessageBox(hWnd, "DSSoundFX->GetCurrentPosition","error",MB_OK); return true; } if( wpos >= pos/7.16 ) return false; return true; } //--------------------- //填充一个WAV声音缓冲区 bool CSound::LoadSoundBuffer(LPDIRECTSOUNDBUFFER lpSoundBuffer, char *filename) { if( bEnable==FALSE ) return FALSE; FILE *f; DSBUFFERDESC dsbd; //结构 LPWAVEFORMATEX wav; //声音格式 DWORD FileLen; //文件长度 BYTE *Buf; //临时缓冲区 long BufLong; //声音缓冲区长度 if( (f=fopen(filename,"rb"))==NULL ) { MessageBox(hWnd,"Not found the sound file!", filename, MB_OK); return FALSE; } fseek(f,0x28,SEEK_SET); fread(&BufLong,sizeof(long),1,f); //读取声音数据长度 FileLen=BufLong+WAV_HDR_SIZE; //文件长度 Buf=(BYTE *)malloc(FileLen); if( Buf==NULL ) { MessageBox(hWnd,"error alloc soundbuffer","error",MB_OK); return FALSE; } //读取声音数据到临时缓冲区 fseek(f,0x00,SEEK_SET); fread(Buf,FileLen,1,f); fclose(f); wav=(LPWAVEFORMATEX)(Buf+20); memset(&dsbd,0,sizeof(dsbd)); dsbd.dwSize=sizeof(dsbd); dsbd.dwFlags=DSBCAPS_STATIC; dsbd.dwBufferBytes=BufLong; dsbd.lpwfxFormat=wav; //创建缓冲区并读取数据 if( lpDSound->CreateSoundBuffer(&dsbd, &lpSoundBuffer, NULL) ) { LPVOID ptr1; //指针1 LPVOID ptr2; //指针2 DWORD size1; DWORD size2; if( ( lpSoundBuffer->Lock(0,BufLong,&ptr1,&size1,&ptr2,&size2,0))!=DS_OK) { MessageBox(hWnd,"error Lock DSoundBuffer","error",MB_OK); return FALSE; } //拷贝数据到声音缓冲区 memcpy(ptr1,Buf+WAV_HDR_SIZE,size1); if(size2) memcpy(ptr2,Buf+size1+WAV_HDR_SIZE,size2); if( lpSoundBuffer->Unlock(ptr1,size1,ptr2,size2)!=DS_OK) { MessageBox(hWnd,"error UnLock SoundBuffer","error",MB_OK); return FALSE; } } _FREE(Buf); return true;//返回 }