DSBuffer.cpp
上传用户:sdpcwz
上传日期:2009-12-14
资源大小:1237k
文件大小:7k
源码类别:

书籍源码

开发平台:

Visual C++

  1. // DSBuffer.cpp : Implementation of CDSBuffer class
  2. //
  3. #include "stdafx.h"
  4. #include "DSBuffer.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. //设置如下两个全局变量控制音量:
  11. //用于控制背景音乐音量大小
  12. int   m_nBkGrdVolume = DSBVOLUME_MAX; 
  13. //用于控制音效音量大小
  14. int   m_nYinXiaoVolume= DSBVOLUME_MAX-DSBVOLUME_MIN ;  
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CDSBuffer
  17. CDSBuffer::CDSBuffer()
  18. {
  19. // 复位声音缓冲区
  20. m_lpDSBuffer = NULL;
  21. }
  22. CDSBuffer::CDSBuffer(const char *FileName,BOOL m_bBackGroundMusic,LPDIRECTSOUND lpDS, DWORD dwFlags)
  23. {
  24.     //判断是否用于背景音乐
  25. //若m_bBackGroundMusic为TRUE,则该音乐用于背景音乐
  26. //若m_bBackGroundMusic为FALSE,则该音乐用于音效
  27. m_bBkGrdMusic=m_bBackGroundMusic;
  28. // 复位声音缓冲区
  29. m_lpDSBuffer = NULL;
  30.     // 打开wave文件       
  31. FILE* pFile = fopen(FileName, "rb");
  32. if(!pFile)
  33. return;
  34. // 把相关信息读入Wave header          
  35. WaveHeader wavHdr;
  36. if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1) 
  37. {
  38. fclose(pFile);
  39. return;
  40. }
  41. // 所需的数据区的大小
  42. DWORD dwSize = wavHdr.dwDSize;
  43. // 是否是一个立体声声音文件?
  44. BOOL bStereo = wavHdr.wChnls > 1 ? true : false;
  45. // 为这个wave文件创建声音缓冲区
  46. if(CreateSoundBuffer(lpDS, dwFlags, dwSize, wavHdr.dwSRate, wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo))
  47. {
  48. // 从wave文件中读入声音数据
  49. if (!ReadData(pFile, dwSize, sizeof(wavHdr)))
  50. MessageBox(NULL,"读入声音数据出错",NULL,MB_OK);
  51. }
  52. fclose(pFile);
  53. }
  54. CDSBuffer::~CDSBuffer()
  55. {
  56. StopSound();
  57. if(m_lpDSBuffer)
  58. {       
  59. m_lpDSBuffer->Release();
  60. }
  61. }
  62. BOOL CDSBuffer::CreateSoundBuffer(LPDIRECTSOUND lpDS, DWORD dwFlags, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
  63. {
  64. PCMWAVEFORMAT pcmwf;
  65. DSBUFFERDESC dsbdesc;
  66. // 设置wave format结构.
  67. memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
  68. pcmwf.wf.wFormatTag         = WAVE_FORMAT_PCM;      
  69. pcmwf.wf.nChannels          = bStereo ? 2 : 1;
  70. pcmwf.wf.nSamplesPerSec     = dwFreq;
  71. pcmwf.wf.nBlockAlign        = (WORD)dwBlkAlign;
  72. pcmwf.wf.nAvgBytesPerSec    = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
  73. pcmwf.wBitsPerSample        = (WORD)dwBitsPerSample;
  74. // 设置DSBUFFERDESC结构
  75. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));  // Zero it out. 
  76. dsbdesc.dwSize              = sizeof(DSBUFFERDESC);
  77. dsbdesc.dwFlags             = dwFlags;
  78. dsbdesc.dwBufferBytes       = dwBufSize; 
  79. dsbdesc.lpwfxFormat         = (LPWAVEFORMATEX)&pcmwf;
  80. if (DS_OK != lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDSBuffer, NULL))
  81. {
  82. MessageBox(NULL,"创建声音缓冲区失败",NULL,MB_OK);
  83. return FALSE;
  84. }
  85. return TRUE;
  86. }
  87. BOOL CDSBuffer::ReadData(FILE* pFile, DWORD dwSize, DWORD dwPos) 
  88. {
  89. // 定位到文件中的正确位置
  90. if (dwPos != 0xffffffff) 
  91. {
  92. if (fseek(pFile, dwPos, SEEK_SET) != 0) 
  93. {
  94. return FALSE;
  95. }
  96. }
  97. // 锁定缓冲区数据
  98. LPVOID pData1;
  99. DWORD  dwData1Size;
  100. LPVOID pData2;
  101. DWORD  dwData2Size;
  102. HRESULT rval;
  103. rval = m_lpDSBuffer->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
  104. if (rval != DS_OK)
  105. {
  106. return FALSE;
  107. }
  108. // 读取数据
  109. if (dwData1Size > 0) 
  110. {
  111. if (fread(pData1, dwData1Size, 1, pFile) != 1) 
  112. {               
  113. return FALSE;
  114. }
  115. }
  116. if (dwData2Size > 0) 
  117. {
  118. if (fread(pData2, dwData2Size, 1, pFile) != 1) 
  119. {
  120. return FALSE;
  121. }
  122. }
  123. // 解除锁定
  124. rval = m_lpDSBuffer->Unlock(pData1, dwData1Size, pData2, dwData2Size);
  125. if (rval != DS_OK)
  126. {
  127. return FALSE;
  128. }
  129. return TRUE;
  130. }
  131. //入口参数:bContinue,控制调用StopSound后是否接着原来的播放点播放
  132. //                    bContinue为TRUE时接着原来点播放,为FALSE时从头播放
  133. //                    默认bContinue为FALSE
  134. BOOL CDSBuffer::PlaySound(BOOL bContinue)
  135. {
  136. if(m_lpDSBuffer) // 确认声音缓冲区有效
  137. {
  138. DWORD dwStatus;
  139. if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
  140. {
  141. MessageBox(NULL,"获取DirectSound缓冲区状态失败!",NULL,MB_OK);
  142. return FALSE;
  143. }
  144. if((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
  145. {
  146. if (m_bBkGrdMusic)  //是背景音乐则循环播放
  147. {
  148. //设置播放位置
  149. if (!bContinue)
  150. m_lpDSBuffer->SetCurrentPosition(0);
  151. if (DS_OK != m_lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING)) // Play the sound
  152. {
  153. return FALSE;
  154. }
  155. }
  156. else    //是音效则播放一次停止
  157. {
  158. //设置播放位置
  159. if (!bContinue)
  160. m_lpDSBuffer->SetCurrentPosition(0);
  161. if (DS_OK != m_lpDSBuffer->Play(0, 0, 0)) // Play the sound
  162. {
  163. MessageBox(NULL,"不能播放声音缓冲区对象",NULL,MB_OK);
  164. return FALSE;
  165. }
  166. }
  167. }
  168. }
  169. return TRUE;
  170. }
  171. BOOL CDSBuffer::StopSound()
  172. {
  173. if(m_lpDSBuffer) // 确认声音缓冲区有效
  174. {
  175. DWORD dwStatus;
  176. if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
  177. {
  178. return FALSE;
  179. }
  180. if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  181. {  
  182. if (DS_OK != m_lpDSBuffer->Stop()) // Stop the sound
  183. {
  184. return FALSE;
  185. }
  186. }
  187. }
  188. return TRUE;
  189. }
  190. BOOL CDSBuffer::IsValid()
  191. {
  192. if (m_lpDSBuffer)
  193. return TRUE;
  194. else
  195. return FALSE;
  196. }
  197. //------------音量控制部分---------------
  198. //SetVolume:设置音量
  199. //入口参数为百分数(0~100)
  200. void CDSBuffer::SetVolume(int percent)
  201. {
  202. int nVolume;
  203. if (percent<=0)
  204. nVolume=DSBVOLUME_MIN;
  205. else if (percent>=100)
  206. nVolume=DSBVOLUME_MAX;
  207. else
  208. nVolume=DSBVOLUME_MIN+(DSBVOLUME_MAX-DSBVOLUME_MIN)*percent/100;
  209.     GetBuffer()->SetVolume(nVolume);
  210. }
  211. //以下两个函数用于控制音量大小
  212. //入口参数为百分数(0~100)
  213. void CDSBuffer::VolumeDown(int percent)
  214. {
  215. if (percent<=0 )
  216. percent=1;
  217. if (percent>=100)
  218. percent=100;
  219. if(m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量
  220. {
  221. if (m_nBkGrdVolume<=DSBVOLUME_MIN)
  222. {
  223. m_nBkGrdVolume=DSBVOLUME_MIN;
  224. GetBuffer()->SetVolume(m_nBkGrdVolume);
  225. return;
  226. }
  227. m_nBkGrdVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent;
  228. if (m_nBkGrdVolume<=DSBVOLUME_MIN)
  229. m_nBkGrdVolume=DSBVOLUME_MIN;
  230. GetBuffer()->SetVolume(m_nBkGrdVolume);
  231. }
  232. else                //是音效,则设置音效音量
  233. {
  234. if (m_nYinXiaoVolume<=DSBVOLUME_MIN)
  235. {
  236. m_nYinXiaoVolume=DSBVOLUME_MIN;
  237. GetBuffer()->SetVolume(m_nYinXiaoVolume);
  238. return;
  239. }
  240. m_nYinXiaoVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent;
  241. if (m_nYinXiaoVolume<=DSBVOLUME_MIN)
  242. m_nYinXiaoVolume=DSBVOLUME_MIN;
  243. GetBuffer()->SetVolume(m_nYinXiaoVolume);
  244. }
  245. }
  246. void CDSBuffer::VolumeUp(int percent)
  247. {
  248. if (percent<=0 )
  249. percent=1;
  250. if (percent>=100)
  251. percent=100;
  252.     if (m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量
  253. {
  254. if (m_nBkGrdVolume>=DSBVOLUME_MAX)
  255. {
  256. m_nBkGrdVolume=DSBVOLUME_MAX;
  257. GetBuffer()->SetVolume(m_nBkGrdVolume);
  258. return;
  259. }
  260. m_nBkGrdVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10;
  261. if (m_nBkGrdVolume>=DSBVOLUME_MAX)
  262. m_nBkGrdVolume=DSBVOLUME_MAX;
  263. GetBuffer()->SetVolume(m_nBkGrdVolume);
  264. }
  265. else                //是音效,则设置音效音量
  266. {
  267. if (m_nYinXiaoVolume>=DSBVOLUME_MAX)
  268. {
  269. m_nYinXiaoVolume=DSBVOLUME_MAX;
  270. GetBuffer()->SetVolume(m_nYinXiaoVolume);
  271. return;
  272. }
  273. m_nYinXiaoVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10;
  274. if (m_nYinXiaoVolume>=DSBVOLUME_MAX)
  275. m_nYinXiaoVolume=DSBVOLUME_MAX;
  276. GetBuffer()->SetVolume(m_nYinXiaoVolume);
  277. }
  278. }