KLMusic.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:13k
源码类别:

模拟服务器

开发平台:

C/C++

  1. //---------------------------------------------------------------------------
  2. // Sword3 Engine (c) 1999-2000 by Kingsoft
  3. //
  4. // File: KLMusic.cpp
  5. // Date: 2000.08.08
  6. // Code: Daniel Wang
  7. // Desc: Wave Stream Music Class
  8. //---------------------------------------------------------------------------
  9. #include <stdafx.h>
  10. #include "KLMusic.h"
  11. //---------------------------------------------------------------------------
  12. // 函数: KLMusic
  13. // 功能: 购造函数
  14. // 参数: void
  15. // 返回: void
  16. //---------------------------------------------------------------------------
  17. KLMusic::KLMusic()
  18. {
  19. m_pDS    = NULL;
  20. m_pSoundBuffer = NULL;
  21. m_pSoundNotify = NULL;
  22. m_hEvent[0]    = NULL;
  23. m_hEvent[1]    = NULL;
  24. m_hEvent[2]    = NULL;
  25. m_dwBufferSize = 0;
  26. m_bLoop        = FALSE;
  27. m_hWnd    = NULL;
  28. }
  29. //---------------------------------------------------------------------------
  30. // 函数: ~KLMusic
  31. // 功能: 析造函数
  32. // 参数: void
  33. // 返回: void
  34. //---------------------------------------------------------------------------
  35. KLMusic::~KLMusic()
  36. {
  37. Close();
  38. }
  39. //---------------------------------------------------------------------------
  40. // 函数: ThreadFunction
  41. // 功能: 播放线程
  42. // 参数: void
  43. // 返回: void
  44. //---------------------------------------------------------------------------
  45. void KLMusic::ThreadFunction(void* lpParam)
  46. {
  47. KLMusic* pMusic = (KLMusic*)lpParam;
  48. while (TRUE)
  49. {
  50. if (!pMusic->HandleNotify())
  51. break;
  52. }
  53. }
  54. //---------------------------------------------------------------------------
  55. // 函数: Open
  56. // 功能: 打开音乐文件
  57. // 参数: FileName WAV文件名
  58. // 返回: TRUE-成功 FALSE-失败
  59. //---------------------------------------------------------------------------
  60. BOOL KLMusic::Open(LPSTR FileName)
  61. {
  62. return FALSE;
  63. }
  64. //---------------------------------------------------------------------------
  65. // 函数: Init
  66. // 功能: 初始化
  67. // 参数: void
  68. // 返回: TRUE-成功 FALSE-失败
  69. //---------------------------------------------------------------------------
  70. BOOL KLMusic::Init()
  71. {
  72. if(!InitDSound())
  73. return FALSE;
  74. // init sound format
  75. InitSoundFormat();
  76. // init sound buffer
  77. if (!InitSoundBuffer())
  78. return FALSE;
  79. // create event handle
  80. if (!InitEventHandle())
  81. return FALSE;
  82. // create sound notify
  83. if (!InitSoundNotify())
  84. return FALSE;
  85. // fill buffer with silence
  86. FillBufferWithSilence();
  87. // set buffer play position
  88. m_pSoundBuffer->SetCurrentPosition(0);
  89. // 修改,先填一段声音数据,如果不这么做声音会延迟0.5秒
  90. FillBufferWithSound(1);
  91. // create play thread
  92. m_Thread.Create(ThreadFunction, this);
  93. return TRUE;
  94. }
  95. bool KLMusic::InitDSound()
  96. {
  97.     HRESULT             hr;
  98.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  99.     SAFE_RELEASE( m_pDS );
  100.     // Create IDirectSound using the primary sound device
  101.     if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) )
  102.     {
  103. return FALSE;
  104. }
  105.     // Set DirectSound coop level 
  106.     if( FAILED( hr = m_pDS->SetCooperativeLevel( m_hWnd, DSSCL_PRIORITY )))
  107.     {
  108. return FALSE;
  109. }
  110.     // Get the primary buffer 
  111.     DSBUFFERDESC dsbd;
  112.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  113.     dsbd.dwSize        = sizeof(DSBUFFERDESC);
  114.     dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
  115.     dsbd.dwBufferBytes = 0;
  116.     dsbd.lpwfxFormat   = NULL;
  117.     if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
  118. {
  119. return FALSE;
  120. }
  121.     if( FAILED( hr = pDSBPrimary->SetFormat(&m_WaveFormat) ) )
  122. {
  123. return FALSE;
  124. }
  125.     SAFE_RELEASE( pDSBPrimary );
  126.     return TRUE;
  127. }
  128. //---------------------------------------------------------------------------
  129. // 函数: Close
  130. // 功能: 释放音乐
  131. // 参数: void
  132. // 返回: void
  133. //---------------------------------------------------------------------------
  134. void KLMusic::Close()
  135. {
  136. // 必须先等线程结束,再释放内存,防止非法操作
  137. Stop();
  138. SetEvent(m_hEvent[2]);
  139. m_Thread.WaitForExit();
  140. FreeSoundNotify();
  141. FreeSoundBuffer();
  142. FreeEventHandle();
  143. SAFE_RELEASE( m_pDS ); 
  144. }
  145. //---------------------------------------------------------------------------
  146. // 函数: InitSoundFormat
  147. // 功能:
  148. // 参数: void
  149. // 返回: void
  150. //---------------------------------------------------------------------------
  151. void KLMusic::InitSoundFormat()
  152. {
  153. }
  154. //---------------------------------------------------------------------------
  155. // 函数: InitSoundBuffer
  156. // 功能: 创建声音Buffer
  157. // 参数: void
  158. // 返回: TRUE-成功 FALSE-失败
  159. //---------------------------------------------------------------------------
  160. BOOL KLMusic::InitSoundBuffer()
  161. {
  162. DSBUFFERDESC dsbdesc;
  163. HRESULT hres;
  164. // get direct sound
  165. if (m_pDS == NULL)
  166. return FALSE;
  167. // close any open file and release interfaces
  168. if (m_pSoundBuffer)
  169. FreeSoundBuffer();
  170. // set streaming sound buffer desc
  171. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
  172. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  173. dsbdesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY // 播放位置通知
  174. | DSBCAPS_GETCURRENTPOSITION2 // 可以取得当前位置
  175. | DSBCAPS_CTRLVOLUME // 使音量可以控制
  176. | DSBCAPS_LOCSOFTWARE // 使用软件混音
  177. | DSBCAPS_STICKYFOCUS; // 可以在后台播放
  178. // The size of the buffer is arbitrary, but should be at least
  179. // two seconds, to keep data writes well ahead of the play position.
  180. dsbdesc.dwBufferBytes = m_dwBufferSize;
  181. dsbdesc.lpwfxFormat = &m_WaveFormat;
  182. // create streaming sound buffer
  183. hres = m_pDS->CreateSoundBuffer(&dsbdesc, &m_pSoundBuffer, NULL);
  184. if (hres != DS_OK)
  185. {
  186. return FALSE;
  187. }
  188. return TRUE;
  189. }
  190. //---------------------------------------------------------------------------
  191. // 函数: FreeSoundBuffer
  192. // 功能: 释放音乐Buffer
  193. // 参数: void
  194. // 返回: void
  195. //---------------------------------------------------------------------------
  196. void KLMusic::FreeSoundBuffer()
  197. {
  198. if (m_pDS == NULL)
  199. return;
  200. SAFE_RELEASE(m_pSoundBuffer);
  201. }
  202. //---------------------------------------------------------------------------
  203. // 函数: InitEventHandle
  204. // 功能: 创建事件句柄
  205. // 参数: void
  206. // 返回: TRUE-成功 FALSE-失败
  207. //---------------------------------------------------------------------------
  208. BOOL KLMusic::InitEventHandle()
  209. {
  210. for (int i = 0; i < NUMEVENTS; i++)
  211. {
  212. if (m_hEvent[i] == NULL)
  213. m_hEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
  214. if (m_hEvent[i] == NULL)
  215. {
  216. return FALSE;
  217. }
  218. }
  219. return TRUE;
  220. }
  221. //---------------------------------------------------------------------------
  222. // 函数: FreeEventHandle
  223. // 功能: 创建事件句柄
  224. // 参数: void
  225. // 返回: TRUE-成功 FALSE-失败
  226. //---------------------------------------------------------------------------
  227. void KLMusic::FreeEventHandle()
  228. {
  229. for (int i = 0; i < NUMEVENTS; i++)
  230. {
  231. if (m_hEvent[i])
  232. {
  233. CloseHandle(m_hEvent[i]);
  234. m_hEvent[i] = NULL;
  235. }
  236. }
  237. }
  238. //---------------------------------------------------------------------------
  239. // 函数: InitSoundNotify
  240. // 功能: 创建SoundNotify
  241. // 参数: void
  242. // 返回: TRUE-成功 FALSE-失败
  243. //---------------------------------------------------------------------------
  244. BOOL KLMusic::InitSoundNotify()
  245. {
  246. HRESULT hres;
  247. // check sound buffer
  248. if (m_pSoundBuffer == NULL)
  249. return FALSE;
  250. // setup pos notify
  251. m_PosNotify[0].dwOffset = 0;
  252. m_PosNotify[0].hEventNotify = m_hEvent[0];
  253. m_PosNotify[1].dwOffset = m_dwBufferSize / 2;
  254. m_PosNotify[1].hEventNotify = m_hEvent[1];
  255. // query interface
  256. hres = m_pSoundBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&m_pSoundNotify);
  257. if (hres != S_OK)
  258. {
  259. return FALSE;
  260. }
  261. // set notify position
  262. hres = m_pSoundNotify->SetNotificationPositions(2, m_PosNotify);
  263. if (hres != DS_OK)
  264. {
  265. return FALSE;
  266. }
  267. return TRUE;
  268. }
  269. //---------------------------------------------------------------------------
  270. // 函数: FreeSoundNotify
  271. // 功能: 释放播放通告
  272. // 参数: void
  273. // 返回: void
  274. //---------------------------------------------------------------------------
  275. void KLMusic::FreeSoundNotify()
  276. {
  277. if (m_pDS == NULL)
  278. return;
  279. SAFE_RELEASE(m_pSoundNotify);
  280. }
  281. //---------------------------------------------------------------------------
  282. // 函数: HandleNotify
  283. // 功能: 处理音乐播放中的通告消息
  284. // 参数: void
  285. // 返回: void
  286. //---------------------------------------------------------------------------
  287. BOOL KLMusic::HandleNotify()
  288. {
  289. DWORD dwEvent;
  290. // wait for event[0..3] to be signaled
  291. dwEvent = WaitForMultipleObjects(
  292. NUMEVENTS, // How many possible events
  293. m_hEvent, // Location of handles
  294. FALSE, // Wait for all?
  295. INFINITE); // How long to wait
  296.     // WAIT_OBJECT_0 == 0 but is properly treated as an arbitrary
  297.     // index value assigned to the first event, therefore we subtract
  298.     // it from dwEvent to get the zero-based index of the event.
  299. dwEvent -= WAIT_OBJECT_0;
  300. // If the event was set by the buffer,
  301. // there's input to process.
  302. if ((dwEvent == 0) || (dwEvent == 1))
  303. {
  304. FillBufferWithSound(dwEvent);
  305. }
  306. // If the event[2] was set, exit thread
  307. return (dwEvent != 2);
  308. }
  309. //---------------------------------------------------------------------------
  310. // 函数: FillBufferWithSound
  311. // 功能: 填充音乐Buffer
  312. // 参数: dwPos 位置
  313. // 返回: TRUE-成功 FALSE-失败
  314. //---------------------------------------------------------------------------
  315. BOOL KLMusic::FillBufferWithSound(DWORD dwPos)
  316. {
  317. DWORD dwStartOfs;
  318. LONG lNumToWrite;
  319. PVOID lpvPtr1;
  320. PVOID lpvPtr2;
  321. DWORD dwBytes1;
  322. DWORD dwBytes2;
  323. DWORD dwBytesRead;
  324. HRESULT hres;
  325. // check sound buffer
  326. if (m_pSoundBuffer == NULL)
  327. return FALSE;
  328. // decide start offset in sound buffer
  329. if (dwPos == 0)
  330. dwStartOfs = m_PosNotify[1].dwOffset;
  331. else
  332. dwStartOfs = m_PosNotify[0].dwOffset;
  333. // decide number bytes to write to buffer
  334. lNumToWrite = m_dwBufferSize / 2;
  335. // lock buffer to obtain buffer pointer
  336. hres = m_pSoundBuffer->Lock(
  337. dwStartOfs,       // Offset of lock start
  338. lNumToWrite,      // Number of bytes to lock
  339. &lpvPtr1,         // Address of lock start
  340. &dwBytes1,        // Count of bytes locked
  341. &lpvPtr2,         // Address of wrap around
  342. &dwBytes2,        // Count of wrap around bytes
  343. 0);               // Flags
  344. // check return value
  345. if (hres != DS_OK)
  346. return FALSE;
  347. // Read wave data from the file into the buffer
  348. dwBytesRead = ReadWaveData((PBYTE)lpvPtr1, dwBytes1);
  349. // if reached end of file
  350. if (dwBytesRead < dwBytes1)
  351. {
  352. memset((PBYTE)lpvPtr1 + dwBytesRead, 0,
  353. dwBytes1 - dwBytesRead);
  354. }
  355. // unlock sound buffer
  356. m_pSoundBuffer->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
  357. // if reached end of file
  358. if (dwBytesRead < dwBytes1)
  359. {
  360. Rewind();
  361. if (!m_bLoop)
  362. Stop();
  363. }
  364. return TRUE;
  365. }
  366. //---------------------------------------------------------------------------
  367. // 函数: FillMusicBufferWithSilence
  368. // 功能: 用空白填充音乐Buffer
  369. // 参数: void
  370. // 返回: TRUE-成功 FALSE-失败
  371. //---------------------------------------------------------------------------
  372. BOOL KLMusic::FillBufferWithSilence()
  373. {
  374. PVOID   pb1, pb2;
  375. DWORD   cb1, cb2;
  376. HRESULT hres;
  377. // check sound buffer
  378. if (m_pSoundBuffer == NULL)
  379. return FALSE;
  380. hres = m_pSoundBuffer->Lock(0, m_dwBufferSize, &pb1, &cb1, &pb2, &cb2, 0);
  381. if (hres != DS_OK)
  382. return FALSE;
  383. memset(pb1, 0, cb1);
  384. m_pSoundBuffer->Unlock(pb1, cb1, pb2, cb2);
  385. return TRUE;
  386. }
  387. //---------------------------------------------------------------------------
  388. // 函数: ReadWaveData
  389. // 功能: 读取波形数据
  390. // 参数: lpBuf 缓存
  391. // dwLen 长度
  392. // 返回: DWORD 实际读取的长度
  393. //---------------------------------------------------------------------------
  394. DWORD KLMusic::ReadWaveData(LPBYTE lpBuf, DWORD dwLen)
  395. {
  396. return 0;
  397. }
  398. //---------------------------------------------------------------------------
  399. // 函数: Play
  400. // 功能: 播放音乐
  401. // 参数: bLoop 是否循环播放
  402. // 返回: void
  403. //---------------------------------------------------------------------------
  404. void KLMusic::Play(BOOL bLoop)
  405. {
  406. if (m_pSoundBuffer)
  407. {
  408. m_pSoundBuffer->Play(0, 0, DSBPLAY_LOOPING);
  409. m_bLoop = bLoop;
  410. }
  411. }
  412. //---------------------------------------------------------------------------
  413. // 函数: Stop
  414. // 功能: 停止音乐播放
  415. // 参数: void
  416. // 返回: void
  417. //---------------------------------------------------------------------------
  418. void KLMusic::Stop()
  419. {
  420. if (m_pSoundBuffer)
  421. {
  422. m_pSoundBuffer->Stop();
  423. }
  424. }
  425. //---------------------------------------------------------------------------
  426. // 函数: SetVolume
  427. // 功能: 设置音乐的音量
  428. // 参数: lVolume 音量 [0, -10000]
  429. //    DSBVOLUME_MAX = 0
  430. // DSBVOLUME_MIN = -10000
  431. // 返回: void
  432. //---------------------------------------------------------------------------
  433. void KLMusic::SetVolume(LONG lVolume)
  434. {
  435. if (m_pSoundBuffer)
  436. {
  437. m_pSoundBuffer->SetVolume(lVolume);
  438. }
  439. }
  440. //---------------------------------------------------------------------------
  441. // 函数: Rewind
  442. // 功能: 从头播放音乐
  443. // 参数: void
  444. // 返回: void
  445. //---------------------------------------------------------------------------
  446. void KLMusic::Rewind()
  447. {
  448. }
  449. //---------------------------------------------------------------------------