home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioScript / SoundMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-06-28  |  26.8 KB  |  853 lines

  1. /***********************************************************\
  2. Copyright (C) James Boer, 2002. 
  3. All rights reserved worldwide.
  4.  
  5. This software is provided "as is" without express or implied
  6. warranties. You may freely copy and compile this source into
  7. applications you distribute provided that the copyright text
  8. below is included in the resulting source code, for example:
  9. "Portions Copyright (C) James Boer, 2002"
  10. \***********************************************************/
  11.  
  12. #include "SoundMgr.h"
  13. #include "Script.h"
  14. #include "SoundScape.h"
  15.  
  16. using namespace std;
  17. using namespace Audio;
  18.  
  19. #define CHECK_INIT() if(!IsInitialized())    return Error::Handle("Sound manager has not been properly initialized yet");
  20.  
  21. // Comment out this line if you don't want the sound manager to
  22. // require keywords to be case sensitive
  23. #define SNDMGR_CASE_SENSITIVE
  24.  
  25. #ifdef SNDMGR_CASE_SENSITIVE
  26. #define SNDMGR_STRCMP strcmp
  27. #else
  28. #define SNDMGR_STRCMP strcmpi
  29. #endif
  30.  
  31. //------------------------------------------------------------------------//
  32. SoundManager::SoundManager()
  33. {
  34.     FN("SoundManager::SoundManager()");
  35.     Clear();
  36. }
  37.  
  38. //------------------------------------------------------------------------//
  39. SoundManager::~SoundManager()
  40. {
  41.     FN("SoundManager::~SoundManager()");
  42.     Term();
  43. }
  44.  
  45.  
  46. //------------------------------------------------------------------------//
  47. void SoundManager::Clear()
  48. {
  49.     FN("SoundManager::Clear()");
  50.     m_bInitialized = false;
  51.     m_SoundScapeUpdateList.clear();
  52.     m_Loader.Clear();
  53.     m_SndMap.clear();
  54.     m_SndItr = m_SndMap.end();
  55.     m_Snd3DMap.clear();
  56.     m_Snd3DItr = m_Snd3DMap.end();
  57.     m_SSMap.clear();
  58.     m_SSItr = m_SSMap.end();
  59.     m_hTerm = 0;
  60.     ZeroMemory(&m_csSoundMgrUpdate, sizeof(CRITICAL_SECTION));
  61.     m_fCurrentTime = 0.0f;
  62.     m_fFrameTime = 0.0f;
  63.  
  64. }
  65.  
  66.  
  67. //------------------------------------------------------------------------//
  68. bool SoundManager::Init()
  69. {
  70.     FN("SoundManager::Init()");
  71.     if(!m_Loader.Init())
  72.         return Error::Handle("Could not initialize script loader in SoundManager.");
  73.     m_bInitialized = true;
  74.  
  75.     m_fCurrentTime = float(timeGetTime()) / 1000.0f;
  76.  
  77.     SoundScape::ReservePool(8);
  78.  
  79.     InitializeCriticalSection(&m_csSoundMgrUpdate);
  80.  
  81.     // Set the callback for the timer function used for general events that 
  82.     // need to happen ten times per second.
  83.     if(_beginthread(&SoundManager::TimeEvent, 4096, NULL) == -1)
  84.         return false;
  85.  
  86.     return true;
  87. }
  88.  
  89. //------------------------------------------------------------------------//
  90. void SoundManager::Term()
  91. {
  92.     FN("SoundManager::Term()");
  93.     if(m_bInitialized)
  94.     {
  95.         // Create event objects to be used by the thread to signal
  96.         // a successful shutdown.
  97.         m_hTerm = CreateEvent(NULL, FALSE, FALSE, NULL);
  98.         // Indicates the audio manager is now terminating
  99.         m_bInitialized = false;
  100.         // Wait for the thread to shut down before continuing
  101.         WaitForSingleObject(m_hTerm, INFINITE);
  102.         // Close the event object now that we're done with it
  103.         CloseHandle(m_hTerm);
  104.  
  105.         // Delete all soundscape objects
  106.         //for(int i = 0; i < m_MasterSoundScape.size(); i++)
  107.         //    delete m_MasterSoundScape[i];
  108.         //m_MasterSoundScape.clear();
  109.         SoundScape::TermPool();
  110.  
  111.         // Enter and leave the critical section to ensure that the
  112.         // soundscape update loop is done
  113.         EnterCriticalSection(&m_csSoundMgrUpdate);
  114.         LeaveCriticalSection(&m_csSoundMgrUpdate);
  115.  
  116.         // Remove the soundscape critical section
  117.         DeleteCriticalSection(&m_csSoundMgrUpdate);
  118.  
  119.         // Clear all registration entries
  120.         RemoveAll();
  121.  
  122.     }
  123.     m_Loader.Term();
  124.     Clear();
  125. }
  126.  
  127.  
  128. //------------------------------------------------------------------------//
  129. bool SoundManager::LoadScript(string sFileName)
  130. {
  131.     FN("SoundManager::LoadScript()");
  132.     CHECK_INIT();
  133.     Script script;
  134.     if(!m_Loader.Load(sFileName, script))
  135.         return Error::Handle("Could not load script %s", sFileName.c_str());
  136.  
  137.     ScriptNode* pNode = script.GetRoot();
  138.     while(pNode)
  139.     {
  140.         // Look for named "Sound" nodes in the script
  141.         if(SNDMGR_STRCMP(pNode->GetName(), "Sound") == 0)
  142.         {
  143.             if(!LoadSound(pNode))
  144.                 return false;
  145.         }
  146.         // Look for named "Sound3D" nodes in the script
  147.         else if(SNDMGR_STRCMP(pNode->GetName(), "Sound3D") == 0)
  148.         {
  149.             if(!LoadSound3D(pNode))
  150.                 return false;
  151.         }
  152.         // Look for named "soundscape" nodes in the script
  153.         else if(SNDMGR_STRCMP(pNode->GetName(), "SoundScape") == 0)
  154.         {
  155.             if(!LoadSoundScape(pNode))
  156.                 return false;
  157.         }
  158.         
  159.         // advance to the next sibling node if one exists
  160.         pNode = pNode->GetSibling();
  161.     };
  162.  
  163.     return true;
  164. }
  165.  
  166.  
  167. //------------------------------------------------------------------------//
  168. bool SoundManager::RemoveAll()
  169. {
  170.     FN("SoundManager::RemoveAll()");
  171.     CHECK_INIT();
  172.     bool bRet = true;
  173.     if(!RemoveAllSounds())
  174.         bRet = false;
  175.     if(!RemoveAllSounds3D())
  176.         bRet = false;
  177.     if(!RemoveAllSoundScapes())
  178.         bRet = false;
  179.     return bRet;
  180. }
  181.  
  182.  
  183. //------------------------------------------------------------------------//
  184. bool SoundManager::IsSoundRegistered(std::string sSoundName)
  185. {
  186.     FN("SoundManager::IsSoundRegistered()");
  187.     CHECK_INIT();
  188.     StrSndPoolMap::iterator itr = m_SndMap.find(sSoundName);
  189.     if(itr == m_SndMap.end())
  190.         return false;
  191.     else
  192.         return true;
  193. }
  194.  
  195.  
  196. //------------------------------------------------------------------------//
  197. bool SoundManager::GetSoundInit(std::string sSoundName, SoundInit& init)
  198. {
  199.     FN("SoundManager::GetSoundInit()");
  200.     CHECK_INIT();
  201.     StrSndPoolMap::iterator itr = m_SndMap.find(sSoundName);
  202.     if(itr == m_SndMap.end())
  203.         return Error::Handle("Sound definition %s does not exist in map.", sSoundName.c_str());
  204.     init = itr->second.m_Init;
  205.     return true;
  206. }
  207.  
  208.  
  209. //------------------------------------------------------------------------//
  210. bool SoundManager::GetSound(std::string sSoundName, ISound*& pSound)
  211. {
  212.     FN("SoundManager::GetSound()");
  213.     CHECK_INIT();
  214.     StrSndPoolMap::iterator itr = m_SndMap.find(sSoundName);
  215.     if(itr == m_SndMap.end())
  216.         return Error::Handle("Sound definition %s does not exist in map.", sSoundName.c_str());
  217.     // If there are existing free sounds, use these first
  218.     if(itr->second.m_Free.size() && !itr->second.m_Free.front()->IsPlaying())
  219.     {
  220.         pSound = itr->second.m_Free.front();
  221.         itr->second.m_Free.pop();
  222.         itr->second.m_Used.push_back(pSound);
  223.     }
  224.     // Otherwise, create a new sound object
  225.     else
  226.     {
  227.         if(!AudioMgr()->CreateSound(pSound))
  228.             return Error::Handle("Error creating sound from definition %s.", sSoundName.c_str());
  229.         itr->second.m_Used.push_back(pSound);
  230.         if(!pSound->Init(itr->second.m_Init))
  231.             return Error::Handle("Sound definition %s could not be initialized.", sSoundName.c_str());
  232.     }
  233.     return true;
  234. }
  235.  
  236.  
  237. //------------------------------------------------------------------------//
  238. bool SoundManager::ReleaseSound(std::string sSoundName, ISound* pSound)
  239. {
  240.     FN("SoundManager::ReleaseSound()");
  241.     CHECK_INIT();
  242.     StrSndPoolMap::iterator itr = m_SndMap.find(sSoundName);
  243.     if(itr == m_SndMap.end())
  244.         return Error::Handle("Sound definition %s does not exist in map.", sSoundName.c_str());
  245.     ISoundVector::iterator snditr;
  246.     snditr = find(itr->second.m_Used.begin(), itr->second.m_Used.end(), pSound); 
  247.     if(snditr == itr->second.m_Used.end())
  248.         return Error::Handle("No sound instances of %s to release", sSoundName.c_str());
  249.     itr->second.m_Used.erase(snditr);
  250.     itr->second.m_Free.push(pSound);
  251.     return true;
  252. }
  253.  
  254.  
  255. //------------------------------------------------------------------------//
  256. void SoundManager::ResetSoundItr()
  257. {
  258.     FN("SoundManager::ResetSoundItr()");
  259.     m_SndItr = m_SndMap.begin();
  260. }
  261.  
  262.  
  263. //------------------------------------------------------------------------//
  264. bool SoundManager::GetNextSound(std::string& sSoundName)
  265. {
  266.     FN("SoundManager::GetNextSound()");
  267.     CHECK_INIT();
  268.     if(m_SndItr == m_SndMap.end())
  269.         return false;
  270.     sSoundName = (m_SndItr->first);
  271.     ++m_SndItr;
  272.     return true;
  273. }
  274.  
  275.  
  276. //------------------------------------------------------------------------//
  277. bool SoundManager::RemoveSound(std::string sSoundName)
  278. {
  279.     FN("SoundManager::RemoveSound()");
  280.     CHECK_INIT();
  281.     StrSndPoolMap::iterator itr = m_SndMap.find(sSoundName);
  282.     if(itr == m_SndMap.end())
  283.         return false;
  284.     while(!itr->second.m_Free.empty())
  285.     {
  286.         itr->second.m_Free.front()->Destroy();
  287.         itr->second.m_Free.pop();
  288.     }
  289.     for(int i = 0; i < itr->second.m_Used.size(); i++)
  290.         itr->second.m_Used[i]->Destroy();
  291.     m_SndMap.erase(itr);
  292.     return true;
  293. }
  294.  
  295.  
  296. //------------------------------------------------------------------------//
  297. bool SoundManager::RemoveAllSounds()
  298. {
  299.     FN("SoundManager::RemoveAllSounds()");
  300.     CHECK_INIT();
  301.     StrSndPoolMap::iterator itr;
  302.     for(itr = m_SndMap.begin(); itr != m_SndMap.end(); ++itr)
  303.     {
  304.         while(!itr->second.m_Free.empty())
  305.         {
  306.             itr->second.m_Free.front()->Destroy();
  307.             itr->second.m_Free.pop();
  308.         }
  309.         for(int i = 0; i < itr->second.m_Used.size(); i++)
  310.             itr->second.m_Used[i]->Destroy();
  311.     }
  312.     m_SndMap.clear();
  313.     return true;
  314. }
  315.  
  316.  
  317.  
  318. //------------------------------------------------------------------------//
  319. bool SoundManager::IsSound3DRegistered(std::string sSound3DName)
  320. {
  321.     FN("SoundManager::IsSound3DRegistered()");
  322.     CHECK_INIT();
  323.     StrSnd3DPoolMap::iterator itr = m_Snd3DMap.find(sSound3DName);
  324.     if(itr == m_Snd3DMap.end())
  325.         return false;
  326.     else
  327.         return true;
  328. }
  329.  
  330.  
  331. //------------------------------------------------------------------------//
  332. bool SoundManager::GetSound3DInit(std::string sSound3DName, Sound3DInit& init)
  333. {
  334.     FN("SoundManager::GetSound3DInit()");
  335.     CHECK_INIT();
  336.     StrSnd3DPoolMap::iterator itr = m_Snd3DMap.find(sSound3DName);
  337.     if(itr == m_Snd3DMap.end())
  338.         return Error::Handle("Sound3D definition %s does not exist in map.", sSound3DName.c_str());
  339.     init = itr->second.m_Init;
  340.     return true;
  341. }
  342.  
  343.  
  344. //------------------------------------------------------------------------//
  345. bool SoundManager::GetSound3D(std::string sSound3DName, ISound3D*& pSound3D)
  346. {
  347.     FN("SoundManager::GetSound3D()");
  348.     CHECK_INIT();
  349.     StrSnd3DPoolMap::iterator itr = m_Snd3DMap.find(sSound3DName);
  350.     if(itr == m_Snd3DMap.end())
  351.         return Error::Handle("Sound3D definition %s does not exist in map.", sSound3DName.c_str());
  352.     // If there are existing free sounds and they are not playing, use these first
  353.     if(itr->second.m_Free.size() && !itr->second.m_Free.back()->IsPlaying())
  354.     {
  355.         pSound3D = itr->second.m_Free.front();
  356.         itr->second.m_Free.pop();
  357.         if(pSound3D->IsInitialized())
  358.             pSound3D->Destroy();
  359.     }
  360.     // Otherwise, create a new sound object
  361.     else
  362.     {
  363.         if(!AudioMgr()->CreateSound3D(pSound3D))
  364.             return Error::Handle("Error creating sound from definition %s.", sSound3DName.c_str());
  365.     }
  366.     itr->second.m_Used.push_back(pSound3D);
  367.     if(!pSound3D->Init(itr->second.m_Init))
  368.         return Error::Handle("Sound3D definition %s could not be initialized.", sSound3DName.c_str());
  369.     return true;
  370. }
  371.  
  372.  
  373. //------------------------------------------------------------------------//
  374. bool SoundManager::ReleaseSound3D(std::string sSound3DName, ISound3D* pSound3D)
  375. {
  376.     FN("SoundManager::ReleaseSound3D()");
  377.     CHECK_INIT();
  378.     StrSnd3DPoolMap::iterator itr = m_Snd3DMap.find(sSound3DName);
  379.     if(itr == m_Snd3DMap.end())
  380.         return Error::Handle("Sound3D definition %s does not exist in map.", sSound3DName.c_str());
  381.     ISound3DVector::iterator snd3Ditr;
  382.     snd3Ditr = find(itr->second.m_Used.begin(), itr->second.m_Used.end(), pSound3D); 
  383.     if(snd3Ditr == itr->second.m_Used.end())
  384.         return Error::Handle("No sound instances of %s to release", sSound3DName.c_str());
  385.     itr->second.m_Used.erase(snd3Ditr);
  386.     itr->second.m_Free.push(pSound3D);
  387.     return true;
  388. }
  389.  
  390.  
  391. //------------------------------------------------------------------------//
  392. void SoundManager::ResetSound3DItr()
  393. {
  394.     FN("SoundManager::ResetSound3DItr()");
  395.     m_Snd3DItr = m_Snd3DMap.begin();
  396. }
  397.  
  398.  
  399. //------------------------------------------------------------------------//
  400. bool SoundManager::GetNextSound3D(std::string& sSound3DName)
  401. {
  402.     FN("SoundManager::GetNextSound3D()");
  403.     CHECK_INIT();
  404.     if(m_Snd3DItr == m_Snd3DMap.end())
  405.         return false;
  406.     sSound3DName = (m_Snd3DItr->first);
  407.     ++m_Snd3DItr;
  408.     return true;
  409. }
  410.  
  411.  
  412. //------------------------------------------------------------------------//
  413. bool SoundManager::RemoveSound3D(std::string sSound3DName)
  414. {
  415.     FN("SoundManager::RemoveSound3D()");
  416.     CHECK_INIT();
  417.     StrSnd3DPoolMap::iterator itr = m_Snd3DMap.find(sSound3DName);
  418.     if(itr == m_Snd3DMap.end())
  419.         return false;
  420.     while(!itr->second.m_Free.empty())
  421.     {
  422.         itr->second.m_Free.front()->Destroy();
  423.         itr->second.m_Free.pop();
  424.     }
  425.     for(int i = 0; i < itr->second.m_Used.size(); i++)
  426.         itr->second.m_Used[i]->Destroy();
  427.     m_Snd3DMap.erase(itr);
  428.     return true;
  429. }
  430.  
  431.  
  432. //------------------------------------------------------------------------//
  433. bool SoundManager::RemoveAllSounds3D()
  434. {
  435.     FN("SoundManager::RemoveAllSounds3D()");
  436.     CHECK_INIT();
  437.     StrSnd3DPoolMap::iterator itr;
  438.     for(itr = m_Snd3DMap.begin(); itr != m_Snd3DMap.end(); ++itr)
  439.     {
  440.         while(!itr->second.m_Free.empty())
  441.         {
  442.             itr->second.m_Free.front()->Destroy();
  443.             itr->second.m_Free.pop();
  444.         }
  445.         for(int i = 0; i < itr->second.m_Used.size(); i++)
  446.             itr->second.m_Used[i]->Destroy();
  447.     }
  448.     m_Snd3DMap.clear();
  449.     return true;
  450. }
  451.  
  452.  
  453.  
  454.  
  455. //------------------------------------------------------------------------//
  456. bool SoundManager::IsSoundScapeRegistered(std::string sSoundScapeName)
  457. {
  458.     FN("SoundManager::IsSoundScapeRegistered()");
  459.     CHECK_INIT();
  460.     SSInitMap::iterator itr = m_SSMap.find(sSoundScapeName);
  461.     if(itr == m_SSMap.end())
  462.         return false;
  463.     else
  464.         return true;
  465. }
  466.  
  467.  
  468. //------------------------------------------------------------------------//
  469. bool SoundManager::CreateSoundScape(ISoundScape*& pSoundScape)
  470. {
  471.     FN("SoundManager::CreateSoundScape()");
  472.     CHECK_INIT();
  473.     pSoundScape = SoundScape::CreateObject();
  474.     if(!pSoundScape)
  475.         return false;
  476. //    m_MasterSoundScape.push_back(pSoundScape);
  477.     return true;
  478. }
  479.  
  480.  
  481. //------------------------------------------------------------------------//
  482. bool SoundManager::InitSoundScape(std::string sSoundScapeName, ISoundScape*& pSoundScape)
  483. {
  484.     FN("SoundManager::InitSoundScape()");
  485.     CHECK_INIT();
  486.     SSInitMap::iterator itr = m_SSMap.find(sSoundScapeName);
  487.     if(itr == m_SSMap.end())
  488.         return false;
  489.  
  490.     SoundScape* pSS = static_cast<SoundScape*>(pSoundScape);
  491.     if(!pSS->InternalInit(itr->second))
  492.         return false;
  493.  
  494.     return true;
  495. }
  496.  
  497.  
  498. //------------------------------------------------------------------------//
  499. void SoundManager::ResetSoundScapeItr()
  500. {
  501.     FN("SoundManager::ResetSoundScapeItr()");
  502.     m_SSItr = m_SSMap.begin();
  503. }
  504.  
  505.  
  506. //------------------------------------------------------------------------//
  507. bool SoundManager::GetNextSoundScape(std::string& sSoundScapeName)
  508. {
  509.     FN("SoundManager::GetNextSoundScape()");
  510.     CHECK_INIT();
  511.     if(m_SSItr == m_SSMap.end())
  512.         return false;
  513.     sSoundScapeName = (m_SSItr->first);
  514.     ++m_SSItr;
  515.     return true;
  516. }
  517.  
  518.  
  519. //------------------------------------------------------------------------//
  520. bool SoundManager::RemoveSoundScape(std::string sSoundScapeName)
  521. {
  522.     FN("SoundManager::RemoveSoundScape()");
  523.     CHECK_INIT();
  524.     SSInitMap::iterator itr = m_SSMap.find(sSoundScapeName);
  525.     if(itr == m_SSMap.end())
  526.         return false;
  527.     m_SSMap.erase(itr);
  528.     return true;
  529. }
  530.  
  531.  
  532. //------------------------------------------------------------------------//
  533. bool SoundManager::RemoveAllSoundScapes()
  534. {
  535.     FN("SoundManager::RemoveAllSoundScapes()");
  536.     CHECK_INIT();
  537.     m_SSMap.clear();
  538.     return true;
  539. }
  540.  
  541.  
  542. //------------------------------------------------------------------------//
  543. bool SoundManager::LoadSound(ScriptNode* pNode)
  544. {
  545.     FN("SoundManager::LoadSound()");
  546.     // We use string ids in this scripting system
  547.     if(pNode->GetDataType() != Script::STRING)
  548.         return Error::Handle("No id found for sound identifier");
  549.  
  550.     // Just return true if the sound is already registered
  551.     if(IsSoundRegistered(pNode->GetString()))
  552.         return true;
  553.  
  554.     SoundPool pool;
  555.     ScriptNode* pChildNode = pNode->GetChild();
  556.     while(pChildNode)
  557.     {
  558.         if(SNDMGR_STRCMP(pChildNode->GetName(), "FileName") == 0)
  559.             pool.m_Init.m_sFileName = pChildNode->GetString();
  560.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Looping") == 0)
  561.             pool.m_Init.m_bLooping = pChildNode->GetBool();
  562.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Streaming") == 0)
  563.             pool.m_Init.m_bStreaming = pChildNode->GetBool();
  564.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Music") == 0)
  565.             pool.m_Init.m_bMusic = pChildNode->GetBool();
  566.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Volume") == 0)
  567.             pool.m_Init.m_Prop.m_fVolume = pChildNode->GetReal();
  568.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Pan") == 0)
  569.             pool.m_Init.m_Prop.m_fPan = pChildNode->GetReal();
  570.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Pitch") == 0)
  571.             pool.m_Init.m_Prop.m_fPitch = pChildNode->GetReal();
  572.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "ReadCursor") == 0)
  573.             pool.m_Init.m_Prop.m_nReadCursor = pChildNode->GetInteger();
  574.         else
  575.             return Error::Handle("Syntax error in Sound definition");
  576.         pChildNode = pChildNode->GetSibling();
  577.     }
  578.  
  579.     // Insert the sound definition into the map
  580.     m_SndMap.insert(make_pair(pNode->GetString(), pool));
  581.     DebugOut(4, "Registering Sound \"%s\" in sound manager", pNode->GetString());
  582.     return true;
  583. }
  584.  
  585.  
  586. //------------------------------------------------------------------------//
  587. bool SoundManager::LoadSound3D(ScriptNode* pNode)
  588. {
  589.     FN("SoundManager::LoadSound3D()");
  590.     // We use string ids in this scripting system
  591.     if(pNode->GetDataType() != Script::STRING)
  592.         return Error::Handle("No id found for sound3d identifier");
  593.  
  594.     // Just return true if the sound3d is already registered
  595.     if(IsSound3DRegistered(pNode->GetString()))
  596.         return true;
  597.  
  598.     Sound3DPool pool;
  599.     ScriptNode* pChildNode = pNode->GetChild();
  600.     while(pChildNode)
  601.     {
  602.         if(SNDMGR_STRCMP(pChildNode->GetName(), "FileName") == 0)
  603.             pool.m_Init.m_sFileName = pChildNode->GetString();
  604.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Looping") == 0)
  605.             pool.m_Init.m_bLooping = pChildNode->GetBool();
  606.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Streaming") == 0)
  607.             pool.m_Init.m_bStreaming = pChildNode->GetBool();
  608.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Music") == 0)
  609.             pool.m_Init.m_bMusic = pChildNode->GetBool();
  610.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Position") == 0)
  611.             pool.m_Init.m_Prop.m_vPosition = pChildNode->GetVector();
  612.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Velocity") == 0)
  613.             pool.m_Init.m_Prop.m_vVelocity = pChildNode->GetVector();
  614.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "ConeOrientation") == 0)
  615.             pool.m_Init.m_Prop.m_vConeOrientation = pChildNode->GetVector();
  616.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "InsideConeAngle") == 0)
  617.             pool.m_Init.m_Prop.m_nInsideConeAngle = pChildNode->GetInteger();
  618.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "OutsideConeAngle") == 0)
  619.             pool.m_Init.m_Prop.m_nOutsideConeAngle = pChildNode->GetInteger();
  620.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "ConeOutsideVolume") == 0)
  621.             pool.m_Init.m_Prop.m_fConeOutsideVolume = pChildNode->GetReal();
  622.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinDistance") == 0)
  623.             pool.m_Init.m_Prop.m_fMinDistance = pChildNode->GetReal();
  624.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxDistance") == 0)
  625.             pool.m_Init.m_Prop.m_fMaxDistance = pChildNode->GetReal();
  626.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Mode") == 0)
  627.         {
  628.             if(pChildNode->GetDataType() == Script::INTEGER)
  629.             {
  630.                 pool.m_Init.m_Prop.m_nMode = pChildNode->GetInteger();
  631.             }
  632.             else
  633.             {
  634.                 if(SNDMGR_STRCMP(pChildNode->GetString(), "Normal") == 0)
  635.                     pool.m_Init.m_Prop.m_nMode = MODE_NORMAL;
  636.                 else if(SNDMGR_STRCMP(pChildNode->GetString(), "HeadRelative") == 0)
  637.                     pool.m_Init.m_Prop.m_nMode = MODE_HEADRELATIVE;
  638.                 else if(SNDMGR_STRCMP(pChildNode->GetString(), "Disable") == 0)
  639.                     pool.m_Init.m_Prop.m_nMode = MODE_DISABLE;
  640.             }
  641.         }
  642.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Volume") == 0)
  643.             pool.m_Init.m_Prop.m_fVolume = pChildNode->GetReal();
  644.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Pitch") == 0)
  645.             pool.m_Init.m_Prop.m_fPitch = pChildNode->GetReal();
  646.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "ReadCursor") == 0)
  647.             pool.m_Init.m_Prop.m_nReadCursor = pChildNode->GetInteger();
  648.         else
  649.         {
  650.             return Error::Handle("Syntax error in Sound3D definition");
  651.         }
  652.         pChildNode = pChildNode->GetSibling();
  653.     }
  654.  
  655.     // Insert the sound3d definition into the map
  656.     m_Snd3DMap.insert(make_pair(pNode->GetString(), pool));
  657.     DebugOut(4, "Registering Sound3D \"%s\" in sound manager", pNode->GetString());
  658.     return true;
  659. }
  660.  
  661.  
  662. //------------------------------------------------------------------------//
  663. bool SoundManager::LoadSoundScape(ScriptNode* pNode)
  664. {
  665.     FN("SoundManager::LoadSoundScape()");
  666.     // We use string ids in this scripting system
  667.     if(pNode->GetDataType() != Script::STRING)
  668.         return Error::Handle("No id found for soundscape identifier");
  669.  
  670.     // Just return true if the soundscape is already registered
  671.     if(IsSoundScapeRegistered(pNode->GetString()))
  672.         return true;
  673.  
  674.     SoundScapeInternalInit init;
  675.     BackgroundElement bge;
  676.     PeriodicElement pe;
  677.  
  678.     ScriptNode* pChildNode = pNode->GetChild();
  679.     while(pChildNode)
  680.     {
  681.         if(SNDMGR_STRCMP(pChildNode->GetName(), "Periodic") == 0)
  682.         {
  683.             if(!LoadPeriodic(pChildNode, pe))
  684.                 return false;
  685.             init.m_aPeriodic.push_back(pe);
  686.         }
  687.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "Background") == 0)
  688.         {
  689.             if(!LoadBackground(pChildNode, bge))
  690.                 return false;
  691.             init.m_aBackground.push_back(bge);
  692.         }
  693.         else
  694.             return false;
  695.  
  696.         pChildNode = pChildNode->GetSibling();
  697.     }
  698.  
  699.     // Insert the sound definition into the map
  700.     m_SSMap.insert(make_pair(pNode->GetString(), init));
  701.     DebugOut(4, "Registering Soundscape \"%s\" in sound manager", pNode->GetString());
  702.     return true;
  703. }
  704.  
  705.  
  706. //------------------------------------------------------------------------//
  707. bool SoundManager::LoadBackground(ScriptNode* pNode, BackgroundElement& bge)
  708. {
  709.     FN("SoundManager::LoadBackground()");
  710.     // Check to see if the node has the "Default" keyword, meaning it should
  711.     // clear all values to their original defaults.
  712.     if((pNode->GetDataType() == Script::VARIABLE) &&
  713.         (strcmp(pNode->GetVariable(), "Default") == 0))
  714.         bge.Clear();
  715.  
  716.     ScriptNode* pChildNode = pNode->GetChild();
  717.     while(pChildNode)
  718.     {
  719.         if(SNDMGR_STRCMP(pChildNode->GetName(), "Sound") == 0)
  720.             bge.m_sSoundID = pChildNode->GetString();
  721.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinVolume") == 0)
  722.             bge.m_Init.m_fMinVolume = pChildNode->GetReal();
  723.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxVolume") == 0)
  724.             bge.m_Init.m_fMaxVolume = pChildNode->GetReal();
  725.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinVolumeTime") == 0)
  726.             bge.m_Init.m_fMinVolumeTime = pChildNode->GetReal();
  727.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxVolumeTime") == 0)
  728.             bge.m_Init.m_fMaxVolumeTime = pChildNode->GetReal();
  729.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinPitch") == 0)
  730.             bge.m_Init.m_fMinPitch = pChildNode->GetReal();
  731.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxPitch") == 0)
  732.             bge.m_Init.m_fMaxPitch = pChildNode->GetReal();
  733.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinPitchTime") == 0)
  734.             bge.m_Init.m_fMinPitchTime = pChildNode->GetReal();
  735.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxPitchTime") == 0)
  736.             bge.m_Init.m_fMaxPitchTime = pChildNode->GetReal();
  737.         else
  738.             return false;
  739.         pChildNode = pChildNode->GetSibling();
  740.     }
  741.  
  742.     return true;
  743. }
  744.  
  745.  
  746. //------------------------------------------------------------------------//
  747. bool SoundManager::LoadPeriodic(ScriptNode* pNode, PeriodicElement& pe)
  748. {
  749.     FN("SoundManager::LoadPeriodic()");
  750.     // Check to see if the node has the "default" keyword, meaning it should
  751.     // clear all values to their original defaults.
  752.     if((pNode->GetDataType() == Script::VARIABLE) &&
  753.         (strcmp(pNode->GetVariable(), "Default") == 0))
  754.         pe.Clear();
  755.  
  756.     ScriptNode* pChildNode = pNode->GetChild();
  757.     while(pChildNode)
  758.     {
  759.         if(SNDMGR_STRCMP(pChildNode->GetName(), "Sound3D") == 0)
  760.             pe.m_sSound3DID = pChildNode->GetString();
  761.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinPitch") == 0)
  762.             pe.m_Init.m_fMinPitch = pChildNode->GetReal();
  763.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxPitch") == 0)
  764.             pe.m_Init.m_fMaxPitch = pChildNode->GetReal();
  765.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinDelay") == 0)
  766.             pe.m_Init.m_fMinDelay = pChildNode->GetReal();
  767.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MaxDelay") == 0)
  768.             pe.m_Init.m_fMaxDelay = pChildNode->GetReal();
  769.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "XRange") == 0)
  770.             pe.m_Init.m_fXRange = pChildNode->GetReal();
  771.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "YRange") == 0)
  772.             pe.m_Init.m_fYRange = pChildNode->GetReal();
  773.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "ZRange") == 0)
  774.             pe.m_Init.m_fZRange = pChildNode->GetReal();
  775.         else if(SNDMGR_STRCMP(pChildNode->GetName(), "MinDistance") == 0)
  776.             pe.m_Init.m_fMinDistance = pChildNode->GetReal();
  777.         else
  778.             return false;
  779.         pChildNode = pChildNode->GetSibling();
  780.     }
  781.  
  782.     return true;
  783. }
  784.  
  785.  
  786. //------------------------------------------------------------------------//
  787. void SoundManager::InsertSoundScape(ISoundScape* pSoundScape)
  788. {
  789.     FN("SoundManager::InsertSoundScape()");
  790.     CRITICAL_FUNCTION(&m_csSoundMgrUpdate);
  791.     m_SoundScapeUpdateList.push_back(pSoundScape);
  792. }
  793.  
  794. //------------------------------------------------------------------------//
  795. void SoundManager::RemoveSoundScape(ISoundScape* pSoundScape)
  796. {
  797.     FN("SoundManager::RemoveSoundScape()");
  798.     CRITICAL_FUNCTION(&m_csSoundMgrUpdate);
  799.     SoundScapeList::iterator itr = find(
  800.         m_SoundScapeUpdateList.begin(),
  801.         m_SoundScapeUpdateList.end(),
  802.         pSoundScape);
  803.     if(itr != m_SoundScapeUpdateList.end())
  804.         m_SoundScapeUpdateList.erase(itr);
  805. }
  806.  
  807. //------------------------------------------------------------------------//
  808. void SoundManager::TimeEvent(LPVOID lpv)
  809. {
  810.     FN("SoundManager::TimeEvent()");
  811.     while(true)
  812.     {
  813.         // Wake up every 50ms (20fps) to perform some timed actions
  814.         Sleep(50);
  815.  
  816.         // If the manager has been shut down then terminate this thread
  817.         if(!CSoundMgr()->m_bInitialized)
  818.         {
  819.             SetEvent(CSoundMgr()->m_hTerm);
  820.             return;
  821.         }
  822.  
  823.         CRITICAL_FUNCTION(&CSoundMgr()->m_csSoundMgrUpdate);
  824.         
  825.         // Calculate the current time and elapsed frame time 
  826.         // (in case we want to tweak timing).  Note that the frame value
  827.         // is always clamped between .01 and .2 seconds.
  828.         CSoundMgr()->m_fFrameTime = Clamp<float>(((float(timeGetTime()) / 1000.0f) - 
  829.             CSoundMgr()->m_fCurrentTime),
  830.             0.01f,
  831.             0.2f);
  832.         CSoundMgr()->m_fCurrentTime += CSoundMgr()->m_fFrameTime;
  833.  
  834.         // Update all currently loaded soundscapes
  835.         CSoundMgr()->ServiceSoundScapes();
  836.     }
  837. }
  838.  
  839.  
  840. //------------------------------------------------------------------------//
  841. void SoundManager::ServiceSoundScapes()
  842. {
  843.     FN("SoundManager::ServiceSoundScapes()");
  844.     SoundScapeList::iterator itr;
  845.     SoundScape* pSoundScape;
  846.     for(itr = m_SoundScapeUpdateList.begin(); itr != m_SoundScapeUpdateList.end(); ++itr)
  847.     {
  848.         pSoundScape = static_cast<SoundScape*>(*itr);
  849.         pSoundScape->Update();
  850.     }
  851. }
  852.  
  853.