home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioLib / AudioMgr.cpp < prev    next >
C/C++ Source or Header  |  2002-09-10  |  40KB  |  1,272 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 "AudioMgr.h"
  13. #include "AudioCommon.h"
  14. #include "Sound.h"
  15. #include "Sound3D.h"
  16. #include "Segment.h"
  17. #include "DLS.h"
  18. #include "AudioScript.h"
  19. #include "Listener.h"
  20. #include "AudioStreamFactory.h"
  21.  
  22.  
  23. const int RESERVE_SOUND        = 128;
  24. const int RESERVE_SOUND3D    = 128;
  25. const int RESERVE_SEGMENT    = 32;
  26. const int RESERVE_SCRIPT    = 16;
  27. const int RESERVE_DLS        = 4;
  28.  
  29. const int TIME_EVENT = 0;
  30. const int MUSIC_EVENT = 1;
  31.  
  32. using namespace std;
  33. using namespace Audio;
  34.  
  35. #define CHECK_INIT() if(!IsInitialized())    return Error::Handle("The audio manager has not been properly initialized yet");
  36.  
  37.  
  38. //------------------------------------------------------------------------//
  39. AudioManager::AudioManager()
  40. {
  41.     FN("AudioManager::AudioManager()");
  42.     Clear();
  43. }
  44.  
  45. //------------------------------------------------------------------------//
  46. AudioManager::~AudioManager()
  47. {
  48.     FN("AudioManager::~AudioManager()");
  49.     Term();
  50. }
  51.  
  52. //------------------------------------------------------------------------//
  53. void AudioManager::Clear()
  54. {
  55.     FN("AudioManager::Clear()");
  56.     m_pLoader = 0;
  57.     m_pMusicPerformance = 0;
  58.     m_pSoundPerformance = 0;
  59.     m_pDirectSound = 0;
  60.     m_pPrimaryBuffer = 0;
  61.     memset(&m_DSCaps, 0, sizeof(DSCAPS));
  62.     m_DSCaps.dwSize = sizeof(DSCAPS);
  63.     m_bInitialized = false;
  64.     m_Init.Clear();
  65.  
  66.     // Path information
  67.     m_pszAudioSystemPath[0] = 0;
  68.     m_pszCurrentWorkingPath[0] = 0;
  69.  
  70.     // Buffer usage members
  71.     m_Stats.Clear();
  72.  
  73.     // Volume info
  74.     m_fSoundVolume = VOLUME_MAX;
  75.     m_fMusicVolume = VOLUME_MAX;
  76.  
  77.     // Currently loaded objects
  78.     m_LoadedSound.clear();
  79.     m_LoadedSound3D.clear();
  80.     m_LoadedSegment.clear();
  81.  
  82.     // Clear the buffer cache
  83.     m_BufferCache.Clear();
  84.  
  85.     // Asyncronous load pending lists
  86.     CLEAR_STL_QUEUE(m_SoundLoadPending);
  87.     CLEAR_STL_QUEUE(m_Sound3DLoadPending);
  88.     CLEAR_STL_QUEUE(m_SegmentLoadPending);
  89.     CLEAR_STL_QUEUE(m_SoundLoadTemp);
  90.     CLEAR_STL_QUEUE(m_Sound3DLoadTemp);
  91.     CLEAR_STL_QUEUE(m_SegmentLoadTemp);
  92.  
  93.     // handle for load notification
  94.     m_hLoadNotify = 0;
  95.  
  96.     // Stream data
  97.     m_SoundStreamProcess.clear();
  98.     m_SoundStreamRemoval.clear();
  99.  
  100.     // Listener object
  101.     m_pListener = 0;
  102.  
  103.     // Music data
  104.     m_pCurrentSegment = 0;
  105.     m_pNextSegment = 0;
  106.  
  107.     // Music update notification
  108.     m_hMusicNotify = 0;
  109.  
  110.     // Shut-down synchronization handles
  111.     m_hTerm[TIME_EVENT] = 0;
  112.     m_hTerm[MUSIC_EVENT] = 0;
  113.  
  114.     // Update thread synchronization critical-section object
  115.     ZeroMemory(&m_csAudioUpdate, sizeof(CRITICAL_SECTION));
  116.     ZeroMemory(&m_csLoading, sizeof(CRITICAL_SECTION));
  117.     ZeroMemory(&m_csLoadScheduling, sizeof(CRITICAL_SECTION));
  118.  
  119.     // Audio stream factory information
  120.     m_pStreamFactory = 0;
  121.  
  122. }
  123.  
  124. //------------------------------------------------------------------------//
  125. bool AudioManager::Init(const AudioMgrInit& init)
  126. {
  127.     FN("AudioManager::Init()");
  128.  
  129.     Error::Log("Initializing audio system...");
  130.     HRESULT hr;
  131.  
  132.     // Make sure we don't initialize more than once
  133.     if(IsInitialized())
  134.         return Error::Handle("Audio system has already been initialized.");
  135.     m_Init = init;
  136.  
  137.     hr = CoInitialize(0);
  138.     if(FAILED(hr))
  139.         return Error::Handle("Could not initialize COM");
  140.  
  141.     // Initialize the buffer cache
  142.     m_BufferCache.Init();
  143.  
  144.     if(m_Init.m_bCacheBuffers && !m_Init.m_bAutoStream)
  145.     {
  146.         DebugOut(1, "WARNING: Cannot enable buffer caching without auto streaming");
  147.         DebugOut(1, "Enabling autostreaming now...");
  148.         m_Init.m_bAutoStream = true;
  149.     }
  150.  
  151.     // Pre-allocate audio objects
  152.     Sound::ReservePool(RESERVE_SOUND);
  153.     Sound3D::ReservePool(RESERVE_SOUND3D);
  154.     Segment::ReservePool(RESERVE_SEGMENT);
  155.     AudioScript::ReservePool(RESERVE_SCRIPT);
  156.     DLS::ReservePool(RESERVE_DLS);
  157.  
  158.     // First create the DirectSound object and set the cooperative level
  159.     hr = DirectSoundCreate8(NULL, &m_pDirectSound, NULL);
  160.     if(FAILED(hr))
  161.         return Error::Handle("Could not create DirectSound8 object.  Error = %s.", DXGetErrorString(hr));
  162.     hr = m_pDirectSound->SetCooperativeLevel(init.m_hWnd, DSSCL_PRIORITY);
  163.     if(FAILED(hr))
  164.         return Error::Handle("Failed to set DirectSound cooperative level.  Error = %s.", DXGetErrorString(hr));
  165.  
  166.     // Get the capabilities of this sound system
  167.     hr = m_pDirectSound->GetCaps(&m_DSCaps);
  168.     if(FAILED(hr))
  169.         return Error::Handle("Failed to get DirectSound caps.  Error = %s.", DXGetErrorString(hr));
  170.  
  171.     Error::Log("Reporting sound driver caps...");
  172.     Error::Log("\tSound Driver %s certified or is a WDM driver.", 
  173.         (m_DSCaps.dwFlags & DSCAPS_CERTIFIED) ? "is" : "is not");
  174.     Error::Log("\tSound Driver %s support variable sample rate playback.", 
  175.         (m_DSCaps.dwFlags & DSCAPS_CONTINUOUSRATE ) ? "does" : "does not");
  176.     Error::Log("\tSound Driver %s being emulated with waveform audio functions.", 
  177.         (m_DSCaps.dwFlags & DSCAPS_EMULDRIVER) ? "is" : "is not");
  178.     Error::Log("\tSound Driver %s support 16-bit primary buffers.", 
  179.         (m_DSCaps.dwFlags & DSCAPS_PRIMARY16BIT) ? "does" : "does not");
  180.     Error::Log("\tSound Driver %s support 8-bit primary buffers.", 
  181.         (m_DSCaps.dwFlags & DSCAPS_PRIMARY8BIT) ? "does" : "does not");
  182.     Error::Log("\tSound Driver %s support mono primary buffers.", 
  183.         (m_DSCaps.dwFlags & DSCAPS_PRIMARYMONO) ? "does" : "does not");
  184.     Error::Log("\tSound Driver %s support stereo primary buffers.", 
  185.         (m_DSCaps.dwFlags & DSCAPS_PRIMARYSTEREO) ? "does" : "does not");
  186.     Error::Log("\tSound Driver %s support 16-bit secondary buffers.", 
  187.         (m_DSCaps.dwFlags & DSCAPS_SECONDARY16BIT ) ? "does" : "does not");
  188.     Error::Log("\tSound Driver %s support 8-bit secondary buffers.", 
  189.         (m_DSCaps.dwFlags & DSCAPS_SECONDARY8BIT ) ? "does" : "does not");
  190.     Error::Log("\tSound Driver %s support mono secondary buffers.", 
  191.         (m_DSCaps.dwFlags & DSCAPS_SECONDARYMONO) ? "does" : "does not");
  192.     Error::Log("\tSound Driver %s support stereo secondary buffers.", 
  193.         (m_DSCaps.dwFlags & DSCAPS_SECONDARYSTEREO) ? "does" : "does not");
  194.  
  195.     Error::Log("\tMinimum secondary buffer sample rate = %d", m_DSCaps.dwMinSecondarySampleRate);
  196.     Error::Log("\tMaximum secondary buffer sample rate = %d", m_DSCaps.dwMaxSecondarySampleRate);
  197.     Error::Log("\tNumber of primary buffers = %d", m_DSCaps.dwPrimaryBuffers);
  198.     Error::Log("\tMaximum hardware buffers = %d", m_DSCaps.dwMaxHwMixingAllBuffers);
  199.     Error::Log("\tMaximum hardware static buffers = %d", m_DSCaps.dwMaxHwMixingStaticBuffers );
  200.     Error::Log("\tMaximum hardware streaming buffers = %d", m_DSCaps.dwMaxHwMixingStreamingBuffers );
  201.     Error::Log("\tFree hardware buffers = %d", m_DSCaps.dwFreeHwMixingAllBuffers );
  202.     Error::Log("\tFree hardware static buffers = %d", m_DSCaps.dwFreeHwMixingStaticBuffers );
  203.     Error::Log("\tFree hardware streaming buffers = %d", m_DSCaps.dwFreeHwMixingStreamingBuffers );
  204.     Error::Log("\tMaximum hardware 3D buffers = %d", m_DSCaps.dwMaxHw3DAllBuffers );
  205.     Error::Log("\tMaximum hardware 3D static buffers = %d", m_DSCaps.dwMaxHw3DStaticBuffers );
  206.     Error::Log("\tMaximum hardware 3D streaming buffers = %d", m_DSCaps.dwMaxHw3DStreamingBuffers );
  207.     Error::Log("\tFree hardware 3D buffers = %d", m_DSCaps.dwFreeHw3DAllBuffers );
  208.     Error::Log("\tFree hardware 3D static buffers = %d", m_DSCaps.dwFreeHw3DStaticBuffers );
  209.     Error::Log("\tFree hardware 3D streaming buffers = %d", m_DSCaps.dwFreeHw3DStreamingBuffers );
  210.     Error::Log("\tTotal hardware memory = %d", m_DSCaps.dwTotalHwMemBytes );
  211.     Error::Log("\tFree hardware memory = %d", m_DSCaps.dwFreeHwMemBytes );
  212.     Error::Log("\tMax contiguous free memory = %d", m_DSCaps.dwMaxContigFreeHwMemBytes );
  213.     Error::Log("\tHardware buffer data transfer rate = %d", m_DSCaps.dwUnlockTransferRateHwBuffers );
  214.     Error::Log("\tCPU overhead for software buffers = %d", m_DSCaps.dwPlayCpuOverheadSwBuffers );
  215.  
  216.     // Determine how to configure the system based on stats and initalization requirements
  217.     if(init.m_bForceSoftware || 
  218.         (init.m_n2DHardwareBufferMin > m_DSCaps.dwMaxHwMixingAllBuffers))
  219.         m_Stats.m_bForce2DSoftware = true;
  220.     if(init.m_bForceSoftware || 
  221.         (init.m_n3DHardwareBufferMin > m_DSCaps.dwFreeHw3DAllBuffers))
  222.         m_Stats.m_bForce3DSoftware = true;
  223.  
  224.     Error::Log("Force 2D software buffers = %s",    (m_Stats.m_bForce2DSoftware) ? "true" : "false");
  225.     Error::Log("Force 3D software buffers = %s",    (m_Stats.m_bForce3DSoftware) ? "true" : "false");
  226.  
  227.     // Create the primary sound buffer
  228.     DSBUFFERDESC desc;
  229.     ZeroMemory(&desc, sizeof(desc));
  230.     desc.dwSize = sizeof(desc);
  231.     desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
  232.     hr = m_pDirectSound->CreateSoundBuffer(&desc, &m_pPrimaryBuffer, NULL);
  233.     if(FAILED(hr))
  234.         Error::Handle("Could not create primary buffer.  Error = %s.", DXGetErrorString(hr));
  235.  
  236.     // Setting the format and playing the primary buffer does nothing 
  237.     // with modern WDM drivers, but it's good to try in case older 
  238.     // VxD model drivers are used
  239.     WAVEFORMATEX wf;
  240.     memset(&wf, 0, sizeof(WAVEFORMATEX)); 
  241.     wf.wFormatTag = WAVE_FORMAT_PCM; 
  242.     wf.nChannels = 2; 
  243.     wf.nSamplesPerSec = m_Init.m_nOptimalSampleRate; 
  244.     wf.nBlockAlign = 4; 
  245.     wf.nAvgBytesPerSec = 
  246.         wf.nSamplesPerSec * wf.nBlockAlign; 
  247.     wf.wBitsPerSample = m_Init.m_nOptimalSampleBits; 
  248.     m_pPrimaryBuffer->SetFormat(&wf);
  249.     if(FAILED(hr))
  250.         Error::Handle("Could not set primary buffer format.  Error = %s.", DXGetErrorString(hr));
  251.     m_pPrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
  252.     if(FAILED(hr))
  253.         Error::Handle("Could not play primary buffer.  Error = %s.", DXGetErrorString(hr));
  254.  
  255.     // Note that we're creating two performance objects, one for sound effects played
  256.     // through DirectMusic, and the other is for music segments to play on.  This is
  257.     // done so that playing segments as sound effects will not interfere with the
  258.     // notification system used by the music manager.  This also makes it convenient
  259.     // to set up different default audiopaths for the two types of segments.
  260.     hr = CoCreateInstance(CLSID_DirectMusicPerformance, NULL,
  261.                      CLSCTX_INPROC, IID_IDirectMusicPerformance8,
  262.                      (void**)&m_pMusicPerformance );
  263.     if(FAILED(hr))
  264.         return Error::Handle("Could not create music DirectMusic Performance object.  Error = %s.", DXGetErrorString(hr));
  265.  
  266.     uint32 nDefaultAudiopath;
  267.     if(m_Init.m_bUseMusicReverb)
  268.         nDefaultAudiopath = DMUS_APATH_SHARED_STEREOPLUSREVERB;
  269.     else
  270.         nDefaultAudiopath = DMUS_APATH_DYNAMIC_STEREO;
  271.  
  272.     // Initialize the music performance
  273.     hr = m_pMusicPerformance->InitAudio( 
  274.             NULL,                                // IDirectMusic
  275.             (IDirectSound**)&m_pDirectSound,    // IDirectSound
  276.             init.m_hWnd,                        // Window handle.
  277.             nDefaultAudiopath,                    // Specify the default audiopath
  278.             64,                                    // Number of performance channels.
  279.             DMUS_AUDIOF_ALL,                    // Features on synthesizer.
  280.             NULL                                // Audio parameters; use defaults.
  281.         );
  282.     if(FAILED(hr))
  283.         return Error::Handle("Could not init music performance.  Error = %s", DXGetErrorString(hr));
  284.  
  285.     IDirectMusicAudioPath* pAudioPath = 0;
  286.     hr = m_pMusicPerformance->GetDefaultAudioPath(&pAudioPath);
  287.     if(FAILED(hr))
  288.         return Error::Handle("Could not get music performance buffer.  Error = %s", DXGetErrorString(hr));
  289.  
  290.     // Create the sound performance object
  291.     hr = CoCreateInstance(CLSID_DirectMusicPerformance, NULL,
  292.                      CLSCTX_INPROC, IID_IDirectMusicPerformance8,
  293.                      (void**)&m_pSoundPerformance );
  294.     if(FAILED(hr))
  295.         return Error::Handle("Could not create sound DirectMusic Performance object.  Error = %s.", DXGetErrorString(hr));
  296.  
  297.     // Initialize the sound performance
  298.     hr = m_pSoundPerformance->InitAudio( 
  299.             NULL,                                // IDirectMusic
  300.             (IDirectSound**)&m_pDirectSound,    // IDirectSound
  301.             init.m_hWnd,                        // Window handle.
  302.             DMUS_APATH_DYNAMIC_STEREO,            // Standard stereo audiopath is default
  303.             64,                                    // Number of performance channels.
  304.             DMUS_AUDIOF_ALL,                    // Features on synthesizer.
  305.             NULL                                // Audio parameters; use defaults.
  306.         );
  307.     if(FAILED(hr))
  308.         return Error::Handle("Could not init sound performance.  Error = %s", DXGetErrorString(hr));
  309.  
  310.     hr = m_pSoundPerformance->GetDefaultAudioPath(&pAudioPath);
  311.     if(FAILED(hr))
  312.         return Error::Handle("Could not get music performance buffer.  Error = %s", DXGetErrorString(hr));
  313.  
  314.     // Now create the DirectMusic loader.  We don't really
  315.     // need to bother with a DirectMusic object itself.
  316.     hr = CoCreateInstance(CLSID_DirectMusicLoader, NULL, 
  317.                          CLSCTX_INPROC, IID_IDirectMusicLoader8,
  318.                          (void**)&m_pLoader);
  319.     if(FAILED(hr))
  320.         return Error::Handle("Could not create DirectMusic Loader object.  Error = %s.", DXGetErrorString(hr));
  321.  
  322.     // See if the user has provided a custom file factory object.  If not, create
  323.     // our own disk-based system by default
  324.     if(m_Init.m_pAudioStreamFactory)
  325.         m_pStreamFactory = m_Init.m_pAudioStreamFactory;
  326.     else
  327.         m_pStreamFactory = new AudioStreamFactory;
  328.  
  329.     // Create an event for music notification
  330.     m_hMusicNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
  331.     m_pMusicPerformance->SetNotificationHandle(m_hMusicNotify, 0);
  332.  
  333.     // Set notifications for the music performance
  334.     hr = m_pMusicPerformance->AddNotificationType(GUID_NOTIFICATION_MEASUREANDBEAT);
  335.     if(FAILED(hr))
  336.         return Error::Handle("Failed to set DirectMusic notification.  Error = %s", DXGetErrorString(hr));
  337.     hr = m_pMusicPerformance->AddNotificationType(GUID_NOTIFICATION_PERFORMANCE);
  338.     if(FAILED(hr))
  339.         return Error::Handle("Failed to set DirectMusic notification.  Error = %s", DXGetErrorString(hr));
  340.     hr = m_pMusicPerformance->AddNotificationType(GUID_NOTIFICATION_SEGMENT);
  341.     if(FAILED(hr))
  342.         return Error::Handle("Failed to set DirectMusic notification.  Error = %s", DXGetErrorString(hr));
  343.  
  344.     // Set the working directory
  345.     if(m_Init.m_sWorkingPath.empty())
  346.         getcwd(m_pszAudioSystemPath, MAX_PATH);
  347.     else
  348.         strcpy(m_pszAudioSystemPath, m_Init.m_sWorkingPath.c_str());
  349.  
  350.     // Create an event for loading notifications
  351.     m_hLoadNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
  352.  
  353.     // Initialize the audio update's critical section object
  354.     InitializeCriticalSection(&m_csAudioUpdate);
  355.     InitializeCriticalSection(&m_csLoading);
  356.     InitializeCriticalSection(&m_csLoadScheduling);
  357.  
  358.     // Audio system has been successfully initialized
  359.     m_bInitialized = true;
  360.  
  361.     // Note that we're using a very modest stack size of 4K in these threads.  
  362.     // If you add anything substantial to these functions, you may need to
  363.     // increase the stack size.
  364.  
  365.     // Set the callback for the timer function used for general events that 
  366.     // need to happen ten times per second.
  367.     if(_beginthread(&AudioManager::TimeEvent, 4096, NULL) == -1)
  368.         return false;
  369.  
  370.     // Begin the DirectMusic event thread
  371.     if(_beginthread(AudioManager::MusicEventThread, 4096, NULL) == -1)
  372.         return false;
  373.  
  374.     // Start the loading thread
  375.     if(_beginthread(AudioManager::LoadingThread, 4096, NULL) == -1)
  376.         return false;
  377.  
  378.     Error::Log("Successfully initialized audio system.");
  379.  
  380.     return true;
  381. }
  382.  
  383. //------------------------------------------------------------------------//
  384. void AudioManager::Term()
  385. {
  386.     FN("AudioManager::Term()");
  387.  
  388.     bool bInit = m_bInitialized;
  389.  
  390.     if(m_bInitialized)
  391.     {
  392.         // Create event objects to be used by the threads to signal
  393.         // a successful shutdown.
  394.         m_hTerm[TIME_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  395.         m_hTerm[MUSIC_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  396.  
  397.         // Indicates the audio manager is now terminating
  398.         m_bInitialized = false;
  399.  
  400.         // Tell the music notification thread to proceed.
  401.         SetEvent(m_hMusicNotify);
  402.  
  403.         // Wait for both threads to shut down before continuing
  404.         WaitForMultipleObjects(2, m_hTerm, TRUE, INFINITE);
  405.  
  406.         // Close the event objects now that we're done with them
  407.         CloseHandle(m_hTerm[TIME_EVENT]);
  408.         CloseHandle(m_hTerm[MUSIC_EVENT]);
  409.  
  410.         // Enter and leave the update critical section to ensure that the
  411.         // update loop is finished
  412.         DeleteCriticalSection(&m_csAudioUpdate);
  413.  
  414.         // Set a load notify event so the loading thread can exit
  415.         SetEvent(m_hLoadNotify);
  416.  
  417.         // Enter and leave the loading critical section to ensure that the
  418.         // loading thread is finished
  419.         EnterCriticalSection(&m_csLoading);
  420.         LeaveCriticalSection(&m_csLoading);
  421.         DeleteCriticalSection(&m_csLoading);
  422.  
  423.         EnterCriticalSection(&m_csLoadScheduling);
  424.         LeaveCriticalSection(&m_csLoadScheduling);
  425.         DeleteCriticalSection(&m_csLoadScheduling);
  426.  
  427.         // Close the load notification handle now that we're done with it
  428.         CloseHandle(m_hLoadNotify);
  429.     }
  430.  
  431.     // Clear the stream lists
  432.     m_SoundStreamProcess.clear();
  433.     m_SoundStreamRemoval.clear();
  434.  
  435.     // Destroy all cached buffers
  436.     m_BufferCache.Term();
  437.  
  438.     // Make sure the loaded lists are clear.  
  439.     m_LoadedSound.clear();
  440.     m_LoadedSound3D.clear();
  441.     m_LoadedSegment.clear();
  442.  
  443.     // Destroy all allocated objects in the reserved pools
  444.     Sound::TermPool();
  445.     Sound3D::TermPool();
  446.     Segment::TermPool();
  447.     AudioScript::TermPool();
  448.     DLS::TermPool();
  449.     
  450.     if(m_hMusicNotify)
  451.     {
  452.         CloseHandle(m_hMusicNotify);
  453.         m_hMusicNotify = 0;
  454.     }
  455.  
  456.     // See if the user has provided a custom file factory object.  If not,
  457.     // destroy the one we've created
  458.     if(!m_Init.m_pAudioStreamFactory)
  459.         SAFE_DELETE(m_pStreamFactory);
  460.  
  461.  
  462.     // Delete the listener object
  463.     Listener::DestroyObject(m_pListener);
  464.     m_pListener = 0;
  465.  
  466.     // Release all DirectMusic components 
  467.     SAFE_RELEASE(m_pLoader);
  468.     if(m_pMusicPerformance)
  469.         m_pMusicPerformance->CloseDown();
  470.     SAFE_RELEASE(m_pMusicPerformance);
  471.     if(m_pSoundPerformance)
  472.         m_pSoundPerformance->CloseDown();
  473.     SAFE_RELEASE(m_pSoundPerformance);
  474.  
  475.     // Release the primary buffer
  476.     SAFE_RELEASE(m_pPrimaryBuffer);
  477.     // Release the DirectSound interface
  478.     SAFE_RELEASE(m_pDirectSound);
  479.  
  480.     if(bInit)
  481.         CoUninitialize();
  482.  
  483.     // Make sure all errors are deleted from the error log
  484.     Error::ClearLog();
  485.  
  486.     // Clear all variables
  487.     Clear();
  488. }
  489.  
  490.  
  491. //------------------------------------------------------------------------//
  492. bool AudioManager::IsInitialized() const
  493. {
  494.     FN("AudioManager::IsInitialized()");
  495.     return m_bInitialized;
  496. }
  497.  
  498.  
  499. //------------------------------------------------------------------------//
  500. bool AudioManager::GetStats(AudioMgrStats& stats) const
  501. {
  502.     FN("AudioManager::GetStats()");
  503.     CHECK_INIT();
  504.     stats = m_Stats; 
  505.     return true;
  506. }
  507.  
  508.  
  509. //------------------------------------------------------------------------//
  510. void AudioManager::TimeEvent(LPVOID lpv)
  511. {
  512.     FN("AudioManager::TimeEvent()");
  513.     while(true)
  514.     {
  515.         // Wake up every 50ms to perform some timed actions
  516.         Sleep(50);
  517.  
  518.         // If the manager has been shut down then terminate this thread
  519.         if(!DXAudioMgr()->m_bInitialized)
  520.         {
  521.             SetEvent(DXAudioMgr()->m_hTerm[TIME_EVENT]);
  522.             return;
  523.         }
  524.  
  525.         // Enter the critical section to ensure that functions that alter the
  526.         // contents of the data through which will be looping through cannot
  527.         // continue until we are finished with this function.
  528.         EnterCriticalSection(&DXAudioMgr()->GetUpdateCS());
  529.  
  530.         // Use a static counter to make sure streams only get 
  531.         // updated five times a second.  More often is just wasteful.
  532.         static int iServiceStreams = 0;
  533.         if((iServiceStreams++) % 4 == 1)
  534.             DXAudioMgr()->ServiceStreamingBuffers();
  535.  
  536.         // Update the listener object - calculate all deferred 3D settings
  537.         if(DXAudioMgr()->m_pListener)
  538.             DXAudioMgr()->m_pListener->CommitDeferredSettings();
  539.  
  540.         // We're done with the critical section now
  541.         LeaveCriticalSection(&DXAudioMgr()->GetUpdateCS());
  542.     }
  543. }
  544.  
  545. //------------------------------------------------------------------------//
  546. void AudioManager::ServiceStreamingBuffers()
  547. {
  548.     FN("AudioManager::ServiceStreamingBuffers()");
  549.     // Iterate through all streaming buffers and update their buffer data
  550.     SoundList::iterator itr;
  551.     for(itr = m_SoundStreamProcess.begin(); itr != m_SoundStreamProcess.end(); ++itr)
  552.         (*itr)->ServiceBuffer();
  553.     // Remove any buffers marked for removal after we're done iterating through the list
  554.     for(itr = m_SoundStreamRemoval.begin(); itr != m_SoundStreamRemoval.end(); ++itr)
  555.     {
  556.         SoundList::iterator itor = find(m_SoundStreamProcess.begin(), m_SoundStreamProcess.end(), *itr);
  557.         if(itor != m_SoundStreamProcess.end())
  558.             m_SoundStreamProcess.erase(itor);
  559.     }
  560.     // Clear the removal list
  561.     m_SoundStreamRemoval.clear();
  562. }
  563.  
  564. //------------------------------------------------------------------------//
  565. void AudioManager::InsertStream(Sound* pStream)
  566. {
  567.     FN("AudioManager::InsertStream(Sound* pStream = 0x%X)", pStream);
  568.     m_SoundStreamProcess.push_back(pStream);
  569. }
  570.  
  571. //------------------------------------------------------------------------//
  572. void AudioManager::RemoveStream(Sound* pStream)
  573. {
  574.     FN("AudioManager::RemoveStream(Sound* pStream = 0x%X)", pStream);
  575.     m_SoundStreamRemoval.push_back(pStream);
  576. }
  577.  
  578.  
  579. //------------------------------------------------------------------------//
  580. void AudioManager::OnLoadSound(Sound* pSound)
  581. {
  582.     FN("AudioManager::OnLoadSound(Sound* pSound = 0x%X)", pSound);
  583.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  584.     m_Stats.m_n2DSoundsLoaded++;
  585.     m_LoadedSound.push_back(pSound);
  586.     DebugOut(3, "Sound added: %d sound(s) currently loaded.", m_Stats.m_n2DSoundsLoaded);
  587. }
  588.  
  589. //------------------------------------------------------------------------//
  590. void AudioManager::OnUnloadSound(Sound* pSound)
  591. {
  592.     FN("AudioManager::OnUnloadSound(Sound* pSound = 0x%X)", pSound);
  593.     if(!IsInitialized())
  594.         return;
  595.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  596.     SoundVector::iterator itr;
  597.     for(itr = m_LoadedSound.begin(); itr != m_LoadedSound.end(); ++itr)
  598.     {
  599.         if((*itr) == pSound)
  600.         {
  601.             m_LoadedSound.erase(itr);
  602.             m_Stats.m_n2DSoundsLoaded--;
  603.             DebugOut(3, "Sound removed: %d sound(s) currently loaded.", m_Stats.m_n2DSoundsLoaded);
  604.             return;
  605.         }
  606.     }
  607. }
  608.  
  609. //------------------------------------------------------------------------//
  610. void AudioManager::OnLoadSound3D(Sound3D* pSound3D)
  611. {
  612.     FN("AudioManager::OnLoadSound3D(Sound3D* pSound3D = 0x%X)", pSound3D);
  613.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  614.     m_Stats.m_n3DSoundsLoaded++;
  615.     m_LoadedSound3D.push_back(pSound3D);
  616.     DebugOut(3, "3D Sound added: %d sound(s) currently loaded.", m_Stats.m_n3DSoundsLoaded);
  617. }
  618.  
  619. //------------------------------------------------------------------------//
  620. void AudioManager::OnUnloadSound3D(Sound3D* pSound3D)
  621. {
  622.     FN("AudioManager::OnUnloadSound3D(Sound3D* pSound3D = 0x%X)", pSound3D);
  623.     if(!IsInitialized())
  624.         return;
  625.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  626.     Sound3DVector::iterator itr;
  627.     for(itr = m_LoadedSound3D.begin(); itr != m_LoadedSound3D.end(); ++itr)
  628.     {
  629.         if((*itr) == pSound3D)
  630.         {
  631.             m_LoadedSound3D.erase(itr);
  632.             m_Stats.m_n3DSoundsLoaded--;
  633.             DebugOut(3, "3D Sound removed: %d sound(s) currently loaded.", m_Stats.m_n3DSoundsLoaded);
  634.             return;
  635.         }
  636.     }
  637. }
  638.  
  639. //------------------------------------------------------------------------//
  640. void AudioManager::OnLoadSegment(Segment* pSegment)
  641. {
  642.     FN("AudioManager::OnLoadSegment(Segment* pSegment = 0x%X)", pSegment);
  643.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  644.     m_Stats.m_nSegmentsLoaded++;
  645.     m_LoadedSegment.push_back(pSegment);
  646.     DebugOut(3, "Segment added: %d segment(s) currently loaded.", m_Stats.m_nSegmentsLoaded);
  647. }
  648.  
  649. //------------------------------------------------------------------------//
  650. void AudioManager::OnUnloadSegment(Segment* pSegment)
  651. {
  652.     FN("AudioManager::OnUnloadSegment(Segment* pSegment = 0x%X)", pSegment);
  653.     if(!IsInitialized())
  654.         return;
  655.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  656.     SegmentVector::iterator itr;
  657.     for(itr = m_LoadedSegment.begin(); itr != m_LoadedSegment.end(); ++itr)
  658.     {
  659.         if((*itr) == pSegment)
  660.         {
  661.             m_LoadedSegment.erase(itr);
  662.             m_Stats.m_nSegmentsLoaded--;
  663.             DebugOut(3, "Segment removed: %d segment(s) currently loaded.", m_Stats.m_nSegmentsLoaded);
  664.             return;
  665.         }
  666.     }
  667. }
  668.  
  669.  
  670.  
  671. //------------------------------------------------------------------------//
  672. void AudioManager::LoadingThread(LPVOID lpv)
  673. {
  674.     CoInitialize(NULL);
  675.     DXAudioMgr()->ServiceLoading();
  676.     CoUninitialize();
  677. }
  678.  
  679.  
  680. //------------------------------------------------------------------------//
  681. void AudioManager::ServiceLoading()
  682. {
  683.     while(true)
  684.     {
  685.         // Wait until an loading notification event is received
  686.         WaitForSingleObject(m_hLoadNotify, INFINITE);
  687.  
  688.         // If the audio manager is terminating, then exit the thread
  689.         if(!m_bInitialized)
  690.             return;
  691.  
  692.         // Copy the temporary queues to the main loading queues
  693.         EnterCriticalSection(&m_csLoadScheduling);
  694.         while(!m_SoundLoadTemp.empty())
  695.         {
  696.             m_SoundLoadPending.push(m_SoundLoadTemp.front());
  697.             m_SoundLoadTemp.pop();
  698.         }
  699.         while(!m_Sound3DLoadTemp.empty())
  700.         {
  701.             m_Sound3DLoadPending.push(m_Sound3DLoadTemp.front());
  702.             m_Sound3DLoadTemp.pop();
  703.         }
  704.         while(!m_SegmentLoadTemp.empty())
  705.         {
  706.             m_SegmentLoadPending.push(m_SegmentLoadTemp.front());
  707.             m_SegmentLoadTemp.pop();
  708.         }
  709.         LeaveCriticalSection(&m_csLoadScheduling);
  710.  
  711.         // Do loading work
  712.         bool bFinishedLoading = false;
  713.         EnterCriticalSection(&m_csLoading);
  714.         while(!bFinishedLoading)
  715.         {
  716.  
  717.             if(!m_SoundLoadPending.empty())
  718.             {
  719.                 if(!m_SoundLoadPending.front()->DoLoad())
  720.                     Error::Handle("WARNING! Unable to load sound!");
  721.                 m_SoundLoadPending.pop();
  722.             }
  723.             if(!m_Sound3DLoadPending.empty())
  724.             {
  725.                 if(!m_Sound3DLoadPending.front()->DoLoad())
  726.                     Error::Handle("WARNING! Unable to load 3D sound!");
  727.                 m_Sound3DLoadPending.pop();
  728.             }
  729.             if(!m_SegmentLoadPending.empty())
  730.             {
  731.                 if(!m_SegmentLoadPending.front()->DoLoad())
  732.                     Error::Handle("WARNING! Unable to load segment!");
  733.                 m_SegmentLoadPending.pop();
  734.             }
  735.  
  736.             if(m_SoundLoadPending.empty() && m_Sound3DLoadPending.empty() &&
  737.                 m_SegmentLoadPending.empty())
  738.                 bFinishedLoading = true;
  739.         }
  740.         LeaveCriticalSection(&m_csLoading);
  741.     }
  742. }
  743.  
  744.  
  745.  
  746. //------------------------------------------------------------------------//
  747. void AudioManager::ScheduleLoad(Sound* pSound)
  748. {
  749.     EnterCriticalSection(&m_csLoadScheduling);
  750.     m_SoundLoadTemp.push(pSound);
  751.     LeaveCriticalSection(&m_csLoadScheduling);
  752.     SetEvent(m_hLoadNotify);
  753. }
  754.  
  755.  
  756. //------------------------------------------------------------------------//
  757. void AudioManager::ScheduleLoad(Sound3D* pSound3D)
  758. {
  759.     EnterCriticalSection(&m_csLoadScheduling);
  760.     m_Sound3DLoadTemp.push(pSound3D);
  761.     LeaveCriticalSection(&m_csLoadScheduling);
  762.     SetEvent(m_hLoadNotify);
  763. }
  764.  
  765.  
  766. //------------------------------------------------------------------------//
  767. void AudioManager::ScheduleLoad(Segment* pSegment)
  768. {
  769.     EnterCriticalSection(&m_csLoadScheduling);
  770.     m_SegmentLoadTemp.push(pSegment);
  771.     LeaveCriticalSection(&m_csLoadScheduling);
  772.     SetEvent(m_hLoadNotify);
  773. }
  774.  
  775.  
  776. //------------------------------------------------------------------------//
  777. void AudioManager::MusicEventThread(LPVOID lpv)
  778. {
  779.     DXAudioMgr()->UpdateMusic();
  780. }
  781.  
  782.  
  783. //------------------------------------------------------------------------//
  784. void AudioManager::UpdateMusic()
  785. {
  786.     FN("AudioManager::UpdateMusic()");
  787.  
  788.     DMUS_NOTIFICATION_PMSG* pPmsg;
  789.     while(true)
  790.     {
  791.         WaitForSingleObject(m_hMusicNotify, INFINITE);
  792.         if(!m_bInitialized)
  793.         {
  794.             SetEvent(m_hTerm[MUSIC_EVENT]);
  795.             return;
  796.         }
  797.         while (S_OK == m_pMusicPerformance->GetNotificationPMsg(&pPmsg))
  798.         {
  799.             if(pPmsg->guidNotificationType == GUID_NOTIFICATION_MEASUREANDBEAT)
  800.             {
  801.                 DebugOut(5, "Music notification: Beat = %d", pPmsg->dwField1);
  802.             }
  803.             else if(pPmsg->guidNotificationType == GUID_NOTIFICATION_PERFORMANCE)
  804.             {
  805.                 if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_MUSICALMOSTEND)
  806.                 {
  807.                     DebugOut(5, "Music notification: Music almost at end");
  808.  
  809.                     if(!m_pCurrentSegment)
  810.                         break;
  811.  
  812.                     if(m_pCurrentSegment->IsLooping() && !m_pNextSegment)
  813.                     {
  814.                         ISegment* pSeg = m_pCurrentSegment;
  815.                         m_pCurrentSegment = 0;
  816.                         m_pNextSegment = 0;
  817.                         pSeg->Play();
  818.                     }
  819.                     else if(m_pNextSegment)
  820.                     {
  821.                         ISegment* pSeg = m_pNextSegment;
  822.                         m_pCurrentSegment = 0;
  823.                         m_pNextSegment = 0;
  824.                         pSeg->Play();
  825.                     }
  826.                 }
  827.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_MUSICSTARTED)
  828.                 {
  829.                     DebugOut(5, "Music notification: Music started");
  830.                 }
  831.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_MUSICSTOPPED)
  832.                 {
  833.                     DebugOut(5, "Music notification: Music stopped");
  834.                 }
  835.             }
  836.             else if(pPmsg->guidNotificationType == GUID_NOTIFICATION_SEGMENT)
  837.             {
  838.                 if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_SEGABORT)
  839.                 {
  840.                     DebugOut(5, "Music notification: Segment aborted");
  841.                 }
  842.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_SEGALMOSTEND)
  843.                 {
  844.                     DebugOut(5, "Music notification: Segment almost at end");
  845.                 }
  846.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_SEGEND)
  847.                 {
  848.                     DebugOut(5, "Music notification: Segment at end");
  849.                 }
  850.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_SEGLOOP)
  851.                 {
  852.                     DebugOut(5, "Music notification: Segment has looped");
  853.                 }
  854.                 else if(pPmsg->dwNotificationOption == DMUS_NOTIFICATION_SEGSTART)
  855.                 {
  856.                     DebugOut(5, "Music notification: Segment has started");
  857.  
  858.                     if(m_Init.m_pMusicCallback)
  859.                         m_Init.m_pMusicCallback->OnSegmentStart();
  860.                 }
  861.             }
  862.             m_pMusicPerformance->FreePMsg((DMUS_PMSG*)pPmsg); 
  863.         }
  864.     }
  865. }
  866.  
  867.  
  868. //------------------------------------------------------------------------//
  869. bool AudioManager::CreateSound(ISound*& pSound)
  870. {
  871.     FN("AudioManager::CreateSound()");
  872.     CHECK_INIT();
  873.     pSound = Sound::CreateObject();
  874.     return true;
  875. }
  876.  
  877.  
  878. //------------------------------------------------------------------------//
  879. bool AudioManager::CreateSound3D(ISound3D*& pSound3D)
  880. {
  881.     FN("AudioManager::CreateSound3D()");
  882.     CHECK_INIT();
  883.     pSound3D = Sound3D::CreateObject();
  884.     return true;
  885. }
  886.  
  887.  
  888. //------------------------------------------------------------------------//
  889. bool AudioManager::CreateSegment(ISegment*& pSegment)
  890. {
  891.     FN("AudioManager::CreateSegment()");
  892.     CHECK_INIT();
  893.     pSegment = Segment::CreateObject();
  894.     return true;
  895. }
  896.  
  897.  
  898. //------------------------------------------------------------------------//
  899. bool AudioManager::CreateDLS(IDLS*& pDLS)
  900. {
  901.     FN("AudioManager::CreateDLS()");
  902.     CHECK_INIT();
  903.     pDLS = DLS::CreateObject();
  904.     return true;
  905. }
  906.  
  907.  
  908. //------------------------------------------------------------------------//
  909. bool AudioManager::CreateAudioScript(IAudioScript*& pScript)
  910. {
  911.     FN("AudioManager::CreateAudioScript()");
  912.     CHECK_INIT();
  913.     pScript = AudioScript::CreateObject();
  914.     return true;
  915. }
  916.  
  917.  
  918. //------------------------------------------------------------------------//
  919. bool AudioManager::GetListener(IListener*& pListener)
  920. {
  921.     FN("AudioManager::GetListener()");
  922.     CHECK_INIT();
  923.     if(!m_pListener)
  924.         m_pListener = Listener::CreateObject();
  925.     pListener = m_pListener;
  926.     return true;
  927. }
  928.  
  929. //------------------------------------------------------------------------//
  930. bool AudioManager::SetSoundVolume(float fVolume)
  931. {
  932.     FN("AudioManager::SetSoundVolume(float fVolume = %f)", fVolume);
  933.     CHECK_INIT();
  934.  
  935.     // Ensure the volume stays within the allowed range
  936.     m_fSoundVolume = Clamp<float>(fVolume, VOLUME_MIN, VOLUME_MAX);
  937.  
  938.     // Iterate through all the sounds designated as sound fx, getting
  939.     // and setting the volume to ensure it applies the new global
  940.     // sound setting.
  941.     SoundVector::iterator itr;
  942.     float fVol;
  943.     for(itr = m_LoadedSound.begin(); itr != m_LoadedSound.end(); ++itr)
  944.     {
  945.         if(!(*itr)->IsMusic())
  946.         {
  947.             (*itr)->GetVolume(fVol);
  948.             (*itr)->SetVolume(fVol);
  949.         }
  950.     }
  951.     Sound3DVector::iterator itr3d;
  952.     for(itr3d = m_LoadedSound3D.begin(); itr3d != m_LoadedSound3D.end(); ++itr3d)
  953.     {
  954.         if(!(*itr3d)->IsMusic())
  955.         {
  956.             (*itr3d)->GetVolume(fVol);
  957.             (*itr3d)->SetVolume(fVol);
  958.         }
  959.     }
  960.  
  961.     return true;
  962. }
  963.  
  964.  
  965. //------------------------------------------------------------------------//
  966. bool AudioManager::GetSoundVolume(float& fVolume) const
  967. {
  968.     FN("AudioManager::GetSoundVolume()");
  969.     fVolume = 0.0f;
  970.     CHECK_INIT();
  971.     fVolume = m_fSoundVolume;
  972.     return true;
  973. }
  974.  
  975.  
  976. //------------------------------------------------------------------------//
  977. bool AudioManager::SetMusicVolume(float fVolume)
  978. {
  979.     FN("AudioManager::SetMusicVolume(float fVolume = %f)", fVolume);
  980.     CHECK_INIT();
  981.  
  982.  
  983.     // Ensure the volume stays within the allowed range
  984.     m_fMusicVolume = Clamp<float>(fVolume, VOLUME_MIN, VOLUME_MAX);
  985.  
  986.     // Iterate through all the sounds designated as sound fx, getting
  987.     // and setting the volume to ensure it applies the new global
  988.     // sound setting.
  989.     SoundVector::iterator itr;
  990.     float fVol;
  991.     for(itr = m_LoadedSound.begin(); itr != m_LoadedSound.end(); ++itr)
  992.     {
  993.         if((*itr)->IsMusic())
  994.         {
  995.             (*itr)->GetVolume(fVol);
  996.             (*itr)->SetVolume(fVol);
  997.         }
  998.     }
  999.     Sound3DVector::iterator itr3d;
  1000.     for(itr3d = m_LoadedSound3D.begin(); itr3d != m_LoadedSound3D.end(); ++itr3d)
  1001.     {
  1002.         if((*itr3d)->IsMusic())
  1003.         {
  1004.             (*itr3d)->GetVolume(fVol);
  1005.             (*itr3d)->SetVolume(fVol);
  1006.         }
  1007.     }
  1008.  
  1009.  
  1010.     // Set the global volume on the
  1011.     int32 nVol = LinearToLogVol(m_fMusicVolume);
  1012.     Performance(true)->SetGlobalParam(GUID_PerfMasterVolume, &nVol, sizeof(int32));
  1013.  
  1014.     return true;
  1015.  
  1016. }
  1017.  
  1018.  
  1019. //------------------------------------------------------------------------//
  1020. bool AudioManager::GetMusicVolume(float& fVolume) const
  1021. {
  1022.     FN("AudioManager::GetMusicVolume()");
  1023.     fVolume = 0.0f;
  1024.     CHECK_INIT();
  1025.     fVolume = m_fMusicVolume;
  1026.     return true;
  1027. }
  1028.  
  1029.  
  1030. //------------------------------------------------------------------------//
  1031. bool AudioManager::StopAll()
  1032. {
  1033.     FN("AudioManager::StopAll()");
  1034.     CHECK_INIT();
  1035.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1036.  
  1037.     // Stop Music
  1038.     if(m_pCurrentSegment)
  1039.         m_pCurrentSegment->Stop();
  1040.  
  1041.     // Stop 2d sounds
  1042.     SoundVector::iterator snditr;
  1043.     for(snditr = m_LoadedSound.begin(); snditr != m_LoadedSound.end(); ++snditr)
  1044.         (*snditr)->Stop();
  1045.  
  1046.     // Stop 3d sounds
  1047.     Sound3DVector::iterator snd3ditr;
  1048.     for(snd3ditr = m_LoadedSound3D.begin(); snd3ditr != m_LoadedSound3D.end(); ++snd3ditr)
  1049.         (*snd3ditr)->Stop();
  1050.  
  1051.     // Stop Segments
  1052.     SegmentVector::iterator segitr;
  1053.     for(segitr = m_LoadedSegment.begin(); segitr != m_LoadedSegment.end(); ++segitr)
  1054.         (*segitr)->Stop();
  1055.  
  1056.     return true;
  1057. }
  1058.  
  1059.  
  1060. //------------------------------------------------------------------------//
  1061. bool AudioManager::PauseAll()
  1062. {
  1063.     FN("AudioManager::PauseAll()");
  1064.     CHECK_INIT();
  1065.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1066.  
  1067.     // Pause Music
  1068.     if(m_pCurrentSegment)
  1069.         m_pCurrentSegment->Pause();
  1070.  
  1071.     // Pause 2d sounds
  1072.     SoundVector::iterator snditr;
  1073.     for(snditr = m_LoadedSound.begin(); snditr != m_LoadedSound.end(); ++snditr)
  1074.         (*snditr)->Pause();
  1075.  
  1076.     // Pause 3d sounds
  1077.     Sound3DVector::iterator snd3ditr;
  1078.     for(snd3ditr = m_LoadedSound3D.begin(); snd3ditr != m_LoadedSound3D.end(); ++snd3ditr)
  1079.         (*snd3ditr)->Pause();
  1080.  
  1081.     // Pause Segments
  1082.     SegmentVector::iterator segitr;
  1083.     for(segitr = m_LoadedSegment.begin(); segitr != m_LoadedSegment.end(); ++segitr)
  1084.         (*segitr)->Pause();
  1085.  
  1086.     return true;
  1087. }
  1088.  
  1089.  
  1090. //------------------------------------------------------------------------//
  1091. bool AudioManager::ResumeAll()
  1092. {
  1093.     FN("AudioManager::ResumeAll()");
  1094.     CHECK_INIT();
  1095.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1096.  
  1097.     // Resume Music
  1098.     if(m_pCurrentSegment)
  1099.         if(m_pCurrentSegment->IsPaused())
  1100.             m_pCurrentSegment->Play();
  1101.  
  1102.     // Stop 2d sounds
  1103.     SoundVector::iterator snditr;
  1104.     for(snditr = m_LoadedSound.begin(); snditr != m_LoadedSound.end(); ++snditr)
  1105.         if((*snditr)->IsPaused())
  1106.             (*snditr)->Play();
  1107.  
  1108.     // Stop 3d sounds
  1109.     Sound3DVector::iterator snd3ditr;
  1110.     for(snd3ditr = m_LoadedSound3D.begin(); snd3ditr != m_LoadedSound3D.end(); ++snd3ditr)
  1111.         if((*snd3ditr)->IsPaused())
  1112.             (*snd3ditr)->Play();
  1113.  
  1114.     // Stop Segments
  1115.     SegmentVector::iterator segitr;
  1116.     for(segitr = m_LoadedSegment.begin(); segitr != m_LoadedSegment.end(); ++segitr)
  1117.         if((*segitr)->IsPaused())
  1118.         (*segitr)->Play();
  1119.  
  1120.     return true;
  1121. }
  1122.  
  1123.  
  1124. //------------------------------------------------------------------------//
  1125. bool AudioManager::GetCurrentSegment(ISegment*& pSegment) const
  1126. {
  1127.     FN("AudioManager::GetCurrentSegment()");
  1128.     CHECK_INIT();
  1129.     pSegment = m_pCurrentSegment;
  1130.     return true;
  1131. }
  1132.  
  1133.  
  1134. //------------------------------------------------------------------------//
  1135. bool AudioManager::GetNextSegment(ISegment*& pSegment) const
  1136. {
  1137.     FN("AudioManager::GetNextSegment()");
  1138.     CHECK_INIT();
  1139.     pSegment = m_pNextSegment;
  1140.     return true;
  1141. }
  1142.  
  1143.  
  1144. //------------------------------------------------------------------------//
  1145. bool AudioManager::CanAddSound() const
  1146. {
  1147.     FN("AudioManager::CanAddSound()");
  1148.     if(m_Stats.m_bForce2DSoftware)
  1149.     {
  1150.         if((m_Stats.m_n2DSoundsLoaded) >= m_Init.m_n2DSoftwareBufferMax)
  1151.             return false;
  1152.     }
  1153.     else
  1154.     {
  1155.         if((m_Stats.m_n2DSoundsLoaded) >= m_Init.m_n2DHardwareBufferMax)
  1156.             return false;
  1157.     }
  1158.     return true;
  1159. }
  1160.  
  1161. //------------------------------------------------------------------------//
  1162. bool AudioManager::CanAddSound3D() const
  1163. {
  1164.     FN("AudioManager::CanAddSound3D()");
  1165.     if(m_Stats.m_bForce3DSoftware)
  1166.     {
  1167.         if((m_Stats.m_n3DSoundsLoaded) >= m_Init.m_n3DSoftwareBufferMax)
  1168.             return false;
  1169.     }
  1170.     else
  1171.     {
  1172.         if((m_Stats.m_n3DSoundsLoaded) >= m_Init.m_n3DHardwareBufferMax)
  1173.             return false;
  1174.     }
  1175.     return true;
  1176. }
  1177.  
  1178. //------------------------------------------------------------------------//
  1179. bool AudioManager::CanAddSegment() const
  1180. {
  1181.     FN("AudioManager::CanAddSegment()");
  1182.     if((m_Stats.m_nSegmentsLoaded) >= m_Init.m_nSegmentMax)
  1183.         return false;
  1184.     return true;
  1185. }
  1186.  
  1187.  
  1188. //------------------------------------------------------------------------//
  1189. bool AudioManager::RemoveSound(Sound* pSound)
  1190. {
  1191.     FN("AudioManager::RemoveSound()");
  1192.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1193.     // Check for the lowest priority item in the segment set
  1194.     sort(m_LoadedSound.begin(), m_LoadedSound.end(), ptr_less<Sound*>() );
  1195.     if(m_LoadedSound.empty())
  1196.         return true;
  1197.     if(!pSound)
  1198.         return true;
  1199.     Sound* pFront = m_LoadedSound.front();
  1200.     if(*pSound < *pFront)
  1201.         return false;
  1202.     pFront->Unload();
  1203.     return true;
  1204. }
  1205.  
  1206.  
  1207. //------------------------------------------------------------------------//
  1208. bool AudioManager::RemoveSound3D(Sound3D* pSound3D)
  1209. {
  1210.     FN("AudioManager::RemoveSound3D()");
  1211.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1212.     // Check for the lowest priority item in the segment set
  1213.     sort(m_LoadedSound3D.begin(), m_LoadedSound3D.end(), ptr_less<Sound3D*>() );
  1214.     if(m_LoadedSound3D.empty())
  1215.         return true;
  1216.     if(!pSound3D)
  1217.         return true;
  1218.     Sound3D* pFront = m_LoadedSound3D.front();
  1219.     if(*pSound3D < *pFront)
  1220.         return false;
  1221.     pFront->Unload();
  1222.     return true;
  1223. }
  1224.  
  1225.  
  1226. //------------------------------------------------------------------------//
  1227. void AudioManager::ResetSoundLimit()
  1228. {
  1229.     m_Init.m_n2DHardwareBufferMax = m_LoadedSound.size();
  1230. }
  1231.  
  1232.  
  1233. //------------------------------------------------------------------------//
  1234. void AudioManager::ResetSound3DLimit()
  1235. {
  1236.     m_Init.m_n3DHardwareBufferMax = m_LoadedSound3D.size();
  1237. }
  1238.  
  1239.  
  1240. //------------------------------------------------------------------------//
  1241. bool AudioManager::RemoveSegment(Segment* pSegment)
  1242. {
  1243.     FN("AudioManager::RemoveSegment()");
  1244.     CRITICAL_FUNCTION(&m_csAudioUpdate);
  1245.     // Check for the lowest priority item in the segment set
  1246.     sort(m_LoadedSegment.begin(), m_LoadedSegment.end(), ptr_less<Segment*>() );
  1247.     if(m_LoadedSegment.empty())
  1248.         return true;
  1249.     if(!pSegment)
  1250.         return true;
  1251.     Segment* pFront = m_LoadedSegment.front();
  1252.     if(*pSegment < *pFront)
  1253.         return false;
  1254.     pFront->Unload();
  1255.     return true;
  1256. }
  1257.  
  1258.  
  1259. //------------------------------------------------------------------------//
  1260. bool AudioManager::CreateAudioStream(IAudioStream*& pStream)
  1261. {
  1262.     FN("AudioManager::CreateAudioStream()");
  1263.     CHECK_INIT();
  1264.     if(!m_pStreamFactory)
  1265.         return false;
  1266.     return m_pStreamFactory->CreateAudioStream(pStream);
  1267. }
  1268.  
  1269.  
  1270.  
  1271.  
  1272.