Audio.cpp
上传用户:hkb425
上传日期:2007-06-16
资源大小:34191k
文件大小:16k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. // Audio.cpp: implementation of the CAudio class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Audio.h"
  6. /////////////////////////////////////////////
  7. void CAudioSegment::Set3DPos(VERTEX *pos)
  8. {
  9. if(ds3DBuffer)
  10. {
  11.      ds3DBuffer->SetPosition(pos->xpos, pos->ypos, -pos->zpos, 
  12.                     DS3D_IMMEDIATE);
  13. }
  14. }
  15. //------------------------------------------------------------------//
  16. //- void CAudioSegment::Set3DDistances(float, float) -----------------------//
  17. //------------------------------------------------------------------//
  18. //- Sets the max, and minimum distance for a CAudioSegment to be heard.    -//
  19. //------------------------------------------------------------------//
  20. void CAudioSegment::Set3DDistances(float minDistance, float maxDistance)
  21. {
  22. if(ds3DBuffer)
  23. {
  24. ds3DBuffer->SetMinDistance(minDistance, DS3D_IMMEDIATE);
  25. ds3DBuffer->SetMaxDistance(maxDistance, DS3D_IMMEDIATE);
  26. }
  27. }
  28. //------------------------------------------------------------------//
  29. //- void CAudioSegment::Shutdown(void) -------------------------------------//
  30. //------------------------------------------------------------------//
  31. //- Shutdown the CAudioSegment, I originally had this in the destructor,   -//
  32. //- but it was acting screwy... so I now it has it's own function. -//
  33. //------------------------------------------------------------------//
  34. void CAudioSegment::Shutdown(void)
  35. {
  36. if(dmSegment!=NULL)
  37. {
  38. dmSegment->Release();
  39. dmSegment= NULL;
  40. }
  41. if(ds3DBuffer!=NULL)
  42. {
  43. ds3DBuffer->Release(); 
  44. ds3DBuffer= NULL;
  45. }
  46. if(vPosition!=NULL)
  47. {
  48. delete vPosition; 
  49. vPosition= NULL;
  50. }
  51. }
  52. /////////////////////////////////////////////////////////
  53. //////////////// class CAudio
  54. LPDIRECTMUSICLOADER8   CAudio::dmLoader=NULL; // the loader
  55. LPDIRECTMUSICPERFORMANCE8 CAudio::dmPerformance=NULL;             // the performance
  56. LPDIRECTMUSICAUDIOPATH    CAudio::dm3DAudioPath=NULL;             // the audiopath
  57.     //////////////////////////////////
  58. CAudioSegment  *CAudio::pSound=NULL;
  59. char           *CAudio::pSoundState=NULL;
  60. VERTEX          CAudio::vListenerPos=VERTEX(0,0,0);
  61. float           CAudio::froty=0;
  62. bool            CAudio::bEnable=true;
  63. bool            CAudio::bActive=true;
  64. int             CAudio::m_numUser=0;
  65. //////////////////////////////////////////////////////////////////////
  66. // Construction/Destruction
  67. //////////////////////////////////////////////////////////////////////
  68. CAudio::CAudio()
  69. {
  70. if(m_numUser==0)
  71. {
  72. if(!InitAudio())
  73. {
  74. bEnable=false;
  75. bActive=false;
  76. }
  77. }
  78. m_numUser++;
  79. }
  80. CAudio::~CAudio()
  81. {
  82. m_numUser--;
  83. if(m_numUser==0)
  84. {
  85.         ReleaseAudio();
  86. }
  87. }
  88. ////////////////////////////////////////////////////
  89. //------------------------------------------------------------------//
  90. //- bool CAudio::Init(void) ----------------------------------//
  91. //------------------------------------------------------------------//
  92. //- Initiates DirectAudio.  This function must be called by the    -//
  93. //- programmer, though the shutdown function is automatically    -//
  94. //- called by the destructor (as, not shutting down DAudio    -//
  95. //- correctly can have some bad consequences).    -//
  96. //------------------------------------------------------------------//
  97. bool CAudio::InitAudio()
  98. {
  99. HRESULT hr;
  100. WCHAR wcharStr[MAX_PATH];
  101. char pathStr[MAX_PATH];
  102. hr=CoInitialize(NULL);
  103. if(FAILED(hr))
  104. {
  105. // MessageBox(NULL, "Unable to CoInitialize", "ERROR", MB_OK);
  106. return false;
  107. }
  108. //Create the loader object, load it... and load it good.
  109. hr= CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,
  110. IID_IDirectMusicLoader8, (void**)&dmLoader);
  111. if(FAILED(hr))
  112. {
  113. // MessageBox(NULL, "Unable to create main DirectAudio file loader", "ERROR", MB_OK);
  114. return false;
  115. }
  116. //Create the performance object for that.... performance stuff. 
  117. hr= CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
  118.  IID_IDirectMusicPerformance8, (void**)&dmPerformance);
  119. if(FAILED(hr))
  120. {
  121. // MessageBox(NULL, "Unable to create main DirectAudio performance object", "ERROR", MB_OK);
  122.         ReleaseAudio();
  123. return false;
  124. }
  125. //Initialize the performance with the standard audio path information
  126. dmPerformance->InitAudio(NULL, NULL, NULL, DMUS_APATH_DYNAMIC_3D   , 64,
  127.  DMUS_AUDIOF_ALL, NULL);
  128.      //Create a simple 3D audiopath
  129.  hr= dmPerformance->CreateStandardAudioPath(DMUS_APATH_DYNAMIC_3D,
  130. 64, TRUE, &dm3DAudioPath);
  131.      if(FAILED(hr))
  132. {
  133. // MessageBox(NULL, "Unable to create the DirectAudio audio path", "ERROR", MB_OK);
  134.         ReleaseAudio();
  135. return false;
  136. }
  137. //Retrieve the current directory
  138. GetCurrentDirectory(MAX_PATH, pathStr);
  139. //Convert the file name to a unicode string... as thats what COM needs
  140. MultiByteToWideChar(CP_ACP, 0, pathStr, -1, wcharStr, MAX_PATH);
  141. //Set the search directory
  142. dmLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wcharStr, FALSE);
  143. ///////////////////
  144. ////////////////////////////////////
  145. pSound=new CAudioSegment[MAX_SOUND_NUM];
  146. pSoundState=new char [MAX_SOUND_NUM];
  147. for(unsigned int i=0;i<MAX_SOUND_NUM;i++)
  148. pSoundState[i]=SOUND_NULL;
  149. return true;
  150. }
  151. //------------------------------------------------------------------//
  152. //- bool CAudio::Create(CAudioSegment*, char*, bool) -----------------//
  153. //------------------------------------------------------------------//
  154. //- Use the audio manager to create an individual CAudioSegment effect from-//
  155. //- a file.    -//
  156. //------------------------------------------------------------------//
  157. bool CAudio::CreateSound(unsigned int NumOfSound, char* filename, bool is3DSound)
  158. {
  159.     if(!bEnable)return false;
  160. if(NumOfSound>(MAX_SOUND_NUM-1) || pSoundState[NumOfSound]!=SOUND_NULL)  return false ;
  161. HRESULT hr;
  162. WCHAR wcharStr[MAX_PATH];
  163. //Convert the file name to the string that DirectAudio needs
  164. MultiByteToWideChar(CP_ACP, 0, filename, -1, wcharStr, MAX_PATH);
  165. //Load the audio segment from a file
  166. hr= dmLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,
  167.  IID_IDirectMusicSegment8,
  168.  wcharStr,
  169.  (void**)&pSound[NumOfSound].dmSegment);
  170. if(FAILED(hr))
  171. return false;
  172. //Do code specific for 3D CAudioSegments
  173. if(is3DSound)
  174. {
  175. //Get the 3D buffer, and audio path
  176. hr= dm3DAudioPath->GetObjectInPath(DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, 0, 
  177.    GUID_NULL, 0, IID_IDirectSound3DBuffer,
  178.    (void**)&pSound[NumOfSound].ds3DBuffer);
  179. if(FAILED(hr))
  180. return false;
  181. //Get the 3D buffer paramters
  182. pSound[NumOfSound].vPosition = new VERTEX; 
  183. pSound[NumOfSound].vPosition->xpos=0;
  184. pSound[NumOfSound].vPosition->ypos=0;
  185. pSound[NumOfSound].vPosition->zpos=0;
  186. DS3DBUFFER dsBufferParams; 
  187. dsBufferParams.dwSize= sizeof(DS3DBUFFER);
  188. pSound[NumOfSound].ds3DBuffer->GetAllParameters(&dsBufferParams);
  189. //Set some new parameters
  190. dsBufferParams.dwMode= DS3DMODE_HEADRELATIVE;    // relative to the listener
  191.         dsBufferParams.flMinDistance=100;
  192. dsBufferParams.flMaxDistance=3000;
  193. pSound[NumOfSound].ds3DBuffer->SetAllParameters(&dsBufferParams, DS3D_IMMEDIATE);
  194. //Set the 3D CAudioSegment flag to true
  195. pSound[NumOfSound].is3DSound = true;
  196. pSoundState[NumOfSound]=SOUND_3D_IDLE;
  197. }
  198. else//Do code specific to non-3D CAudioSegments (background music)
  199. {
  200. //Set the 3D buffer to null since we don't need it
  201. pSound[NumOfSound].ds3DBuffer= NULL;
  202. //Set the 3D CAudioSegment flag to false, since we don't need it either
  203. pSound[NumOfSound].is3DSound= false;
  204. pSoundState[NumOfSound]=SOUND_2D_IDLE;
  205. }
  206.     
  207. ////////////////////////////
  208. return true;
  209. }
  210. //------------------------------------------------------------------//
  211. //- void CAudio::Play(CAudioSegment*, DWORD) -------------------------//
  212. //------------------------------------------------------------------//
  213. //- Play the CAudioSegment, and repeat it numRepeats amount of times.    -//
  214. //------------------------------------------------------------------//
  215. void CAudio::Play(unsigned int NumOfSound, DWORD numRepeats, bool bPrimary,bool bCheckOlyOne )
  216. {
  217. if(!bEnable || !bActive)return;
  218. if(NumOfSound>(MAX_SOUND_NUM-1) || pSoundState[NumOfSound]==SOUND_NULL) return  ;
  219.     if(bCheckOlyOne && CheckSoundPlaying(NumOfSound))return;
  220. //Set the number of repeats that we want for the specific CAudioSegment
  221. pSound[NumOfSound].dmSegment->SetRepeats(numRepeats);
  222. DWORD dwFlags;
  223. if(bPrimary)dwFlags=DMUS_SEGF_DEFAULT;
  224. else dwFlags=DMUS_SEGF_DEFAULT | DMUS_SEGF_SECONDARY;
  225. if(pSound[NumOfSound].is3DSound)
  226. {
  227. pSound[NumOfSound].dmSegment->Download(dmPerformance);
  228. //Play the segment using the 3D audio path
  229. dmPerformance->PlaySegmentEx(pSound[NumOfSound].dmSegment, NULL, NULL, 
  230.  dwFlags , 0,
  231.  NULL, NULL, dm3DAudioPath);
  232. pSoundState[NumOfSound]=SOUND_3D_PLAYING;
  233.     }
  234. else
  235. {
  236. //Download the segment's performance object
  237. pSound[NumOfSound].dmSegment->Download(dmPerformance);
  238. //Play the non-3D CAudioSegment segment
  239. dmPerformance->PlaySegmentEx(pSound[NumOfSound].dmSegment, NULL, NULL, 
  240.  dwFlags, 0,
  241.  NULL, NULL, NULL);
  242. pSoundState[NumOfSound]=SOUND_2D_PLAYING;
  243. }
  244. }
  245. //------------------------------------------------------------------//
  246. //- void CAudio::Stop(CAudioSegment*) --------------------------------//
  247. //------------------------------------------------------------------//
  248. //- Stop playing the specified CAudioSegment.    -//
  249. //------------------------------------------------------------------//
  250. void CAudio::Stop(unsigned int NumOfSound)
  251. {
  252. if(!bEnable)return;
  253. if(NumOfSound>(MAX_SOUND_NUM-1) ||
  254.    pSoundState[NumOfSound]==SOUND_NULL ||
  255.    pSoundState[NumOfSound]==SOUND_2D_IDLE  ) return  ;
  256.     
  257. dmPerformance->StopEx(pSound[NumOfSound].dmSegment, 0, 0);
  258. if(pSound[NumOfSound].is3DSound)
  259. pSoundState[NumOfSound]=SOUND_3D_IDLE;
  260. else
  261. pSoundState[NumOfSound]=SOUND_2D_IDLE;
  262. }
  263. void CAudio::StopAll()
  264. {
  265. if(!bEnable)return;
  266. dmPerformance->StopEx(0, 0, 0);
  267. for(unsigned int i=0;i< MAX_SOUND_NUM;i++)
  268. if(pSoundState[i]!=SOUND_NULL)
  269. {
  270. if(pSound[i].is3DSound)
  271.         pSoundState[i]=SOUND_3D_IDLE;
  272.          else
  273.          pSoundState[i]=SOUND_2D_IDLE;
  274. }
  275. }
  276. void CAudio::SetVolume(int iVolume)
  277. {   
  278. if(!bEnable)return;
  279. if(iVolume<0)iVolume=0;
  280. if(iVolume>100)iVolume=100;
  281.     int volume=-4000+iVolume*60;
  282. dmPerformance->SetGlobalParam( GUID_PerfMasterVolume, 
  283.                                            (void*)&volume, sizeof(int) );      
  284. }
  285. //------------------------------------------------------------------//
  286. //- void CAudio::SetListenerPos(float, float, float) ---------//
  287. //------------------------------------------------------------------//
  288. //- Set the listener's (player's) position in 3D space.    -//
  289. //------------------------------------------------------------------//
  290. void CAudio::SetListenerPos(VERTEX *pos,float roty)
  291. {
  292. if(!bEnable)return;
  293. VERTEX v0;
  294. froty=roty;
  295. vListenerPos.xpos=pos->xpos;
  296. vListenerPos.ypos=pos->ypos;
  297. vListenerPos.zpos=pos->zpos;
  298. /*
  299. for(unsigned int i=0;i<MAX_SOUND_NUM;i++)
  300. {
  301. if(pSound[i].is3DSound && pSoundState[i]!=SOUND_NULL)
  302. {
  303. v0=GetTransformSoundPos(pSound[i].vPosition);
  304.      pSound[i].Set3DPos(&v0);
  305.         }
  306. }*/
  307. }
  308. //------------------------------------------------------------------//
  309. //- void CAudio::SetSoundPos(int ,float, float, float) ---------//
  310. //------------------------------------------------------------------//
  311. //- Set the sound's  position in 3D space.    -//
  312. void CAudio::SetSoundPos(unsigned int NumOfSound,VERTEX *pos)
  313. {
  314. if(!bEnable)return;
  315. if(NumOfSound>(MAX_SOUND_NUM-1) || pSoundState[NumOfSound]==SOUND_NULL)  return  ;
  316. if(pSound[NumOfSound].is3DSound)
  317. {
  318.         pSound[NumOfSound].vPosition->xpos=pos->xpos;
  319.         pSound[NumOfSound].vPosition->ypos=pos->ypos;
  320.         pSound[NumOfSound].vPosition->zpos=pos->zpos;
  321.         VERTEX v0=GetTransformSoundPos(pos);
  322. pSound[NumOfSound].Set3DPos(&v0);
  323.     }
  324. }
  325. //------------------------------------------------------------------//
  326. //- void CAudio::GetTransformSoundPos(VERTEX *vSoundPos)------------------//
  327. //------------------------------------------------------------------//
  328. VERTEX CAudio::GetTransformSoundPos(VERTEX *vSoundPos)
  329. {
  330.     //////// translation
  331.     VERTEX v0=VERTEX(vSoundPos->xpos - vListenerPos.xpos,
  332.                  vSoundPos->ypos - vListenerPos.ypos,
  333.                  vSoundPos->zpos - vListenerPos.zpos);
  334.     //////// y rotate
  335.     VERTEX v1=VERTEX(v0.xpos*cosf(froty*0.0174533f)-
  336.                      v0.zpos*sinf(froty*0.0174533f),
  337.                  v0.ypos,
  338.                      v0.xpos*sinf(froty*0.0174533f)+
  339.                      v0.zpos*cosf(froty*0.0174533f));
  340. return v1;
  341. }
  342. //------------------------------------------------------------------//
  343. //- void CAudio::CheckSoundPlaying(unsigned int NumOfSound)-------------------//
  344. //------------------------------------------------------------------//
  345. bool CAudio::CheckSoundPlaying(unsigned int NumOfSound)
  346. {
  347. if(!bEnable)return false;
  348. if(NumOfSound>(MAX_SOUND_NUM-1) || pSoundState[NumOfSound]==SOUND_NULL)return false ;
  349. HRESULT hr=dmPerformance->IsPlaying(pSound[NumOfSound].dmSegment,0);
  350. if(hr==S_OK)
  351. {
  352. if(pSound[NumOfSound].is3DSound)
  353.     pSoundState[NumOfSound]=SOUND_3D_PLAYING;
  354.         else
  355.         pSoundState[NumOfSound]=SOUND_2D_PLAYING;
  356.     return true;
  357. }
  358. else
  359. {
  360. if(pSound[NumOfSound].is3DSound)
  361.     pSoundState[NumOfSound]=SOUND_3D_IDLE;
  362.         else
  363.         pSoundState[NumOfSound]=SOUND_2D_IDLE;
  364.     return false;
  365. }
  366. }
  367. //------------------------------------------------------------------//
  368. //- CAudio::GetSoundState(unsigned int NumOfSound)------------------//
  369. //------------------------------------------------------------------//
  370. int  CAudio::GetSoundState(unsigned int NumOfSound)
  371. {
  372. if(!bEnable)return 0;
  373. if(pSoundState[NumOfSound]==SOUND_3D_PLAYING || pSoundState[NumOfSound]==SOUND_2D_PLAYING)
  374. CheckSoundPlaying(NumOfSound);
  375. return (int)pSoundState[NumOfSound];
  376. }
  377. //------------------------------------------------------------------//
  378. //- void CAudio::SetListenerRolloff(float) -------------------//
  379. //------------------------------------------------------------------//
  380. //- Set the listener's CAudioSegment volume rolloff with distance.    -//
  381. //------------------------------------------------------------------//
  382. void CAudio::SetSoundRolloff(float rolloff)
  383. {
  384. }
  385. //------------------------------------------------------------------//
  386. //- void CAudio::ShutdowSound(unsigned int NumOfSound) ------------------------//
  387. //------------------------------------------------------------------//
  388. void CAudio::DeleteSound(unsigned int NumOfSound)
  389. {
  390. if(!bEnable)return;
  391.     if(pSoundState[NumOfSound]!=SOUND_NULL)
  392. {
  393. pSound[NumOfSound].Shutdown();
  394.         pSoundState[NumOfSound]=SOUND_NULL;
  395. }
  396. }
  397. bool CAudio::SetAudioActive(bool bAudioActive)
  398. {
  399. if(!bEnable)return false;
  400.     bActive=bAudioActive;
  401. return true;
  402. }
  403. bool CAudio::IsAudioEnable()
  404. {
  405. return bEnable;
  406. }
  407. bool CAudio::IsAudioActive()
  408. {
  409. return bActive;
  410. }
  411. //------------------------------------------------------------------//
  412. //- void CAudio::ReleaseAudio(void) ------------------------//
  413. //------------------------------------------------------------------//
  414. //- Shuts down DirectAudio.  This function is called automatically -//
  415. //- by the CAudio destructor, hence the reason why this    -//
  416. //- function is private.    -//
  417. //------------------------------------------------------------------//
  418. void CAudio::ReleaseAudio(void)
  419. {
  420. if(pSound!=NULL && pSoundState!=NULL)
  421. {
  422.         for(unsigned int i=0;i < MAX_SOUND_NUM;i++)
  423. {
  424.     if(pSoundState[i]!=SOUND_NULL)pSound[i].Shutdown();
  425. }
  426.         delete [] pSound;
  427.     delete [] pSoundState;
  428.     pSound=NULL;
  429.     pSoundState=NULL;
  430. }
  431. //Shut down the direct music performance information
  432. if(dmPerformance!=NULL)
  433. {
  434. dmPerformance->Stop(NULL, NULL, 0, 0);
  435. dmPerformance->CloseDown();
  436. dmPerformance->Release();
  437. dmPerformance=NULL;
  438. }
  439. //Shut down the direct music audiopath
  440. if(dm3DAudioPath!=NULL)
  441. {
  442. dm3DAudioPath->Release();
  443. dm3DAudioPath=NULL;
  444. }
  445. //Shut down the direct music loader
  446.    if(dmLoader!=NULL)
  447. {
  448.      dmLoader->Release();
  449. dmLoader=NULL;
  450. }
  451. //Uninitialize COM (*MUST* be done, or you're asking for trouble)
  452. CoUninitialize();
  453. }