www.pudn.com > DST.rar > DSBuffer.cpp


// DSBuffer.cpp : Implementation of CDSBuffer class 
// 
 
#include "stdafx.h" 
#include "DSBuffer.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
//设置如下两个全局变量控制音量: 
//用于控制背景音乐音量大小 
int   m_nBkGrdVolume = DSBVOLUME_MAX;  
//用于控制音效音量大小 
int   m_nYinXiaoVolume= DSBVOLUME_MAX-DSBVOLUME_MIN ;   
 
///////////////////////////////////////////////////////////////////////////// 
// CDSBuffer 
 
CDSBuffer::CDSBuffer() 
{ 
	// 复位声音缓冲区 
	m_lpDSBuffer = NULL; 
} 
 
CDSBuffer::CDSBuffer(const char *FileName,BOOL m_bBackGroundMusic,LPDIRECTSOUND lpDS, DWORD dwFlags) 
{ 
    //判断是否用于背景音乐 
	//若m_bBackGroundMusic为TRUE,则该音乐用于背景音乐 
	//若m_bBackGroundMusic为FALSE,则该音乐用于音效 
	m_bBkGrdMusic=m_bBackGroundMusic; 
 
	// 复位声音缓冲区 
	m_lpDSBuffer = NULL; 
 
    // 打开wave文件        
	FILE* pFile = fopen(FileName, "rb"); 
	if(!pFile) 
		return; 
 
	// 把相关信息读入Wave header           
	WaveHeader wavHdr; 
	if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1)  
	{ 
		fclose(pFile); 
		return; 
	} 
 
	// 所需的数据区的大小 
	DWORD dwSize = wavHdr.dwDSize; 
 
	// 是否是一个立体声声音文件? 
	BOOL bStereo = wavHdr.wChnls > 1 ? true : false; 
 
	// 为这个wave文件创建声音缓冲区 
	if(CreateSoundBuffer(lpDS, dwFlags, dwSize, wavHdr.dwSRate, wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo)) 
	{ 
		// 从wave文件中读入声音数据 
		if (!ReadData(pFile, dwSize, sizeof(wavHdr))) 
			MessageBox(NULL,"读入声音数据出错",NULL,MB_OK); 
	} 
 
	fclose(pFile); 
} 
 
 
CDSBuffer::~CDSBuffer() 
{ 
	StopSound(); 
	if(m_lpDSBuffer) 
	{        
		m_lpDSBuffer->Release(); 
	} 
} 
 
 
BOOL CDSBuffer::CreateSoundBuffer(LPDIRECTSOUND lpDS, DWORD dwFlags, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo) 
{ 
	PCMWAVEFORMAT pcmwf; 
	DSBUFFERDESC dsbdesc; 
 
	// 设置wave format结构. 
	memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) ); 
	pcmwf.wf.wFormatTag         = WAVE_FORMAT_PCM;       
	pcmwf.wf.nChannels          = bStereo ? 2 : 1; 
	pcmwf.wf.nSamplesPerSec     = dwFreq; 
	pcmwf.wf.nBlockAlign        = (WORD)dwBlkAlign; 
	pcmwf.wf.nAvgBytesPerSec    = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; 
	pcmwf.wBitsPerSample        = (WORD)dwBitsPerSample; 
 
	// 设置DSBUFFERDESC结构 
	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));  // Zero it out.  
	dsbdesc.dwSize              = sizeof(DSBUFFERDESC); 
	dsbdesc.dwFlags             = dwFlags; 
	dsbdesc.dwBufferBytes       = dwBufSize;  
	dsbdesc.lpwfxFormat         = (LPWAVEFORMATEX)&pcmwf; 
 
	if (DS_OK != lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDSBuffer, NULL)) 
	{ 
		MessageBox(NULL,"创建声音缓冲区失败",NULL,MB_OK); 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
 
BOOL CDSBuffer::ReadData(FILE* pFile, DWORD dwSize, DWORD dwPos)  
{ 
	// 定位到文件中的正确位置 
	if (dwPos != 0xffffffff)  
	{ 
		if (fseek(pFile, dwPos, SEEK_SET) != 0)  
		{ 
			return FALSE; 
		} 
	} 
 
	// 锁定缓冲区数据 
	LPVOID pData1; 
	DWORD  dwData1Size; 
	LPVOID pData2; 
	DWORD  dwData2Size; 
	HRESULT rval; 
 
	rval = m_lpDSBuffer->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR); 
	if (rval != DS_OK) 
	{ 
		return FALSE; 
	} 
 
	// 读取数据 
	if (dwData1Size > 0)  
	{ 
		if (fread(pData1, dwData1Size, 1, pFile) != 1)  
		{                
			return FALSE; 
		} 
	} 
 
	if (dwData2Size > 0)  
	{ 
		if (fread(pData2, dwData2Size, 1, pFile) != 1)  
		{ 
			return FALSE; 
		} 
	} 
 
	// 解除锁定 
	rval = m_lpDSBuffer->Unlock(pData1, dwData1Size, pData2, dwData2Size); 
	if (rval != DS_OK) 
	{ 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
//入口参数:bContinue,控制调用StopSound后是否接着原来的播放点播放 
//                    bContinue为TRUE时接着原来点播放,为FALSE时从头播放 
//                    默认bContinue为FALSE 
BOOL CDSBuffer::PlaySound(BOOL bContinue) 
{ 
	if(m_lpDSBuffer)	// 确认声音缓冲区有效 
	{ 
		DWORD dwStatus; 
		if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus)) 
		{ 
			MessageBox(NULL,"获取DirectSound缓冲区状态失败!",NULL,MB_OK); 
			return FALSE; 
		} 
 
		if((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING) 
		{ 
			if (m_bBkGrdMusic)  //是背景音乐则循环播放 
			{ 
				//设置播放位置 
				if (!bContinue) 
					m_lpDSBuffer->SetCurrentPosition(0); 
 
				if (DS_OK != m_lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING))		// Play the sound 
				{ 
					return FALSE; 
				} 
			} 
			else    //是音效则播放一次停止 
			{ 
				//设置播放位置 
				if (!bContinue) 
					m_lpDSBuffer->SetCurrentPosition(0); 
 
				if (DS_OK != m_lpDSBuffer->Play(0, 0, 0))		// Play the sound 
				{ 
					MessageBox(NULL,"不能播放声音缓冲区对象",NULL,MB_OK); 
					return FALSE; 
				} 
			} 
		} 
	} 
 
	return TRUE; 
} 
 
BOOL CDSBuffer::StopSound() 
{ 
	if(m_lpDSBuffer)	// 确认声音缓冲区有效 
	{ 
		DWORD dwStatus; 
		if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus)) 
		{ 
			return FALSE; 
		} 
 
		if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING) 
		{   
			if (DS_OK != m_lpDSBuffer->Stop())		// Stop the sound 
			{ 
				return FALSE; 
			} 
 
		} 
	} 
	return TRUE; 
} 
 
 
BOOL CDSBuffer::IsValid() 
{ 
	if (m_lpDSBuffer) 
		return TRUE; 
	else 
		return FALSE; 
} 
 
//------------音量控制部分--------------- 
//SetVolume:设置音量 
//入口参数为百分数(0~100) 
void CDSBuffer::SetVolume(int percent) 
{ 
	int nVolume; 
	if (percent<=0) 
		nVolume=DSBVOLUME_MIN; 
	else if (percent>=100) 
		nVolume=DSBVOLUME_MAX; 
	else 
		nVolume=DSBVOLUME_MIN+(DSBVOLUME_MAX-DSBVOLUME_MIN)*percent/100; 
    GetBuffer()->SetVolume(nVolume); 
} 
 
//以下两个函数用于控制音量大小 
//入口参数为百分数(0~100) 
void CDSBuffer::VolumeDown(int percent) 
{ 
	if (percent<=0 ) 
		percent=1; 
	if (percent>=100) 
		percent=100; 
	if(m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量 
	{ 
		if (m_nBkGrdVolume<=DSBVOLUME_MIN) 
		{ 
			m_nBkGrdVolume=DSBVOLUME_MIN;	 
			GetBuffer()->SetVolume(m_nBkGrdVolume); 
			return; 
		} 
		m_nBkGrdVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent; 
		if (m_nBkGrdVolume<=DSBVOLUME_MIN) 
			m_nBkGrdVolume=DSBVOLUME_MIN; 
		GetBuffer()->SetVolume(m_nBkGrdVolume); 
	} 
	else                //是音效,则设置音效音量 
	{ 
		if (m_nYinXiaoVolume<=DSBVOLUME_MIN) 
		{ 
			m_nYinXiaoVolume=DSBVOLUME_MIN;	 
			GetBuffer()->SetVolume(m_nYinXiaoVolume); 
			return; 
		} 
		m_nYinXiaoVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent; 
		if (m_nYinXiaoVolume<=DSBVOLUME_MIN) 
			m_nYinXiaoVolume=DSBVOLUME_MIN; 
		GetBuffer()->SetVolume(m_nYinXiaoVolume); 
	} 
 
} 
 
void CDSBuffer::VolumeUp(int percent) 
{ 
	if (percent<=0 ) 
		percent=1; 
	if (percent>=100) 
		percent=100; 
    if (m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量 
	{ 
		if (m_nBkGrdVolume>=DSBVOLUME_MAX) 
		{ 
			m_nBkGrdVolume=DSBVOLUME_MAX; 
			GetBuffer()->SetVolume(m_nBkGrdVolume); 
			return; 
		} 
		m_nBkGrdVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10; 
		if (m_nBkGrdVolume>=DSBVOLUME_MAX) 
			m_nBkGrdVolume=DSBVOLUME_MAX; 
		GetBuffer()->SetVolume(m_nBkGrdVolume); 
	} 
	else                //是音效,则设置音效音量 
	{ 
		if (m_nYinXiaoVolume>=DSBVOLUME_MAX) 
		{ 
			m_nYinXiaoVolume=DSBVOLUME_MAX; 
			GetBuffer()->SetVolume(m_nYinXiaoVolume); 
			return; 
		} 
		m_nYinXiaoVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10; 
		if (m_nYinXiaoVolume>=DSBVOLUME_MAX) 
			m_nYinXiaoVolume=DSBVOLUME_MAX; 
		GetBuffer()->SetVolume(m_nYinXiaoVolume); 
	} 
}