NLSOUND::CSoundDriverDSound Class Reference

#include <sound_driver_dsound.h>

Inheritance diagram for NLSOUND::CSoundDriverDSound:

NLSOUND::ISoundDriver

Public Member Functions

virtual void commit3DChanges ()
 Commit all the changes made to 3D settings of listener and sources.

uint countHw2DBuffers ()
 Count the number of available hardware streaming 2D buffers.

uint countHw3DBuffers ()
 Count the number of available hardware streaming 3D buffers.

virtual uint countMaxSources ()
 Return the maximum number of sources that can created.

uint countPlayingSources ()
 Count the number of sources that are actually playing.

virtual IBuffercreateBuffer ()
 Create a sound buffer.

virtual IListenercreateListener ()
 Create the listener instance.

virtual ISourcecreateSource ()
 Create a source.

 CSoundDriverDSound ()
 Constructor.

float getGain ()
 Get the gain.

IStringMapperProvider * getStringMapper ()
 Return the string mapper.

virtual bool init (HWND wnd, bool useEax, IStringMapperProvider *stringMapper)
 Initialization.

virtual bool readRawBuffer (IBuffer *destbuffer, const std::string &name, uint8 *rawData, uint dataSize, TSampleFormat format, uint32 frequency)
virtual bool readWavBuffer (IBuffer *destbuffer, const std::string &name, uint8 *wavData, uint dataSize)
 Load a wave file in to the buffer.

void setGain (float gain)
void update ()
 Update all the driver and its sources. To be called only by the timer callback.

void writeProfile (std::ostream &out)
 Write information about the driver to the output stream.

virtual ~CSoundDriverDSound ()

Static Public Member Functions

ISoundDrivercreateDriver (bool useEax, IStringMapperProvider *stringMapper)
CSoundDriverDSoundinstance ()
 Return the instance of the singleton.


Static Public Attributes

const uint32 InterfaceVersion = 0x08
 Version of the driver interface. To increment when the interface change.


Private Member Functions

friend CBufferDSound::~CBufferDSound ()
friend CSourceDSound::~CSourceDSound ()
virtual void displayBench (NLMISC::CLog *log)
virtual void endBench ()
virtual void removeBuffer (IBuffer *buffer)
 Remove a buffer (should be called by the friend destructor of the buffer class).

virtual void removeSource (ISource *source)
 Remove a source (should be called by the friend destructor of the source class).

virtual void startBench ()

Static Private Member Functions

void CALLBACK TimerCallback (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)

Private Attributes

DSCAPS _Caps
LPDIRECTSOUND8 _DirectSound
LPDIRECTSOUNDBUFFER _PrimaryBuffer
uint _SourceCount
std::set< CSourceDSound * > _Sources
IStringMapperProvider * _StringMapper
 The string mapper provided by client code.

UINT _TimerID
uint32 _TimerResolution
bool _UseEAX
 The EAX support is requested and accepted (ie, there is enougth hardware 3D buffer).


Static Private Attributes

CSoundDriverDSound_Instance = NULL
uint32 _TimerPeriod = 100

Constructor & Destructor Documentation

NLSOUND::CSoundDriverDSound::CSoundDriverDSound  ) 
 

Constructor.

NLSOUND::CSoundDriverDSound::~CSoundDriverDSound  )  [virtual]
 

Definition at line 561 of file sound_driver_dsound.cpp.

References _DirectSound, _PrimaryBuffer, _TimerID, _TimerResolution, and nldebug.

00562 {
00563         nldebug("Destroying DirectSound driver");
00564 
00565     if (_TimerID != NULL)
00566     {
00567         timeKillEvent(_TimerID);
00568         timeEndPeriod(_TimerResolution); 
00569     }
00570 
00571 
00572         // Assure that the remaining sources have released all their DSBuffers 
00573         // before closing down DirectSound
00574         set<CSourceDSound*>::iterator iter;
00575 
00576         for (iter = _Sources.begin(); iter != _Sources.end(); iter++)
00577         {
00578                 (*iter)->release();
00579         }
00580 
00581 
00582         // Assure that the listener has released all resources before closing 
00583         // down DirectSound
00584         if (CListenerDSound::instance() != 0)
00585         {
00586                 CListenerDSound::instance()->release();
00587         }
00588 
00589 
00590     if (_PrimaryBuffer != NULL) 
00591     {
00592         _PrimaryBuffer->Release(); 
00593         _PrimaryBuffer = NULL;
00594     }
00595 
00596     if (_DirectSound != NULL) 
00597     {
00598         _DirectSound->Release(); 
00599         _DirectSound = NULL;
00600     }
00601 
00602         _Instance = 0;
00603 
00604         // free the enumerated list
00605         if (CDeviceDescription::_List)
00606         {
00607                 delete CDeviceDescription::_List;
00608                 CDeviceDescription::_List = NULL;
00609         }
00610 }

NLSOUND::CSoundDriverDSound::CBufferDSound::~CBufferDSound  )  [private]
 

NLSOUND::CSoundDriverDSound::CSourceDSound::~CSourceDSound  )  [private]
 


Member Function Documentation

void NLSOUND::CSoundDriverDSound::commit3DChanges  )  [virtual]
 

Commit all the changes made to 3D settings of listener and sources.

Implements NLSOUND::ISoundDriver.

Definition at line 886 of file sound_driver_dsound.cpp.

References NLSOUND::CListenerDSound::commit3DChanges(), and NLSOUND::CListenerDSound::getPos().

00887 {
00888         CListenerDSound* listener = CListenerDSound::instance();
00889         listener->commit3DChanges();
00890 
00891 
00892         const CVector &origin = listener->getPos();
00893 
00894         set<CSourceDSound*>::iterator iter;
00895 
00896         // We handle the volume of the source according to the distance
00897         // ourselves. Call updateVolume() to, well..., update the volume
00898         // according to, euh ..., the new distance!
00899         for (iter = _Sources.begin(); iter != _Sources.end(); iter++)
00900         {
00901                 if ((*iter)->isPlaying()) 
00902                 {
00903                         (*iter)->updateVolume(origin);
00904                 }
00905         }
00906 }

uint NLSOUND::CSoundDriverDSound::countHw2DBuffers  ) 
 

Count the number of available hardware streaming 2D buffers.

Definition at line 779 of file sound_driver_dsound.cpp.

References _DirectSound, and uint.

Referenced by countMaxSources(), NLSOUND::CSourceDSound::init(), and init().

00780 {
00781     DSCAPS caps;
00782     caps.dwSize = sizeof(caps); 
00783 
00784     if (_DirectSound->GetCaps(&caps) != DS_OK)  
00785     {
00786         throw ESoundDriver("Failed to query the sound device caps");
00787     }
00788 
00789     return caps.dwFreeHwMixingStreamingBuffers;
00790 }

uint NLSOUND::CSoundDriverDSound::countHw3DBuffers  ) 
 

Count the number of available hardware streaming 3D buffers.

Definition at line 764 of file sound_driver_dsound.cpp.

References _DirectSound, and uint.

Referenced by countMaxSources(), NLSOUND::CSourceDSound::init(), and init().

00765 {
00766     DSCAPS caps;
00767     caps.dwSize = sizeof(caps); 
00768 
00769     if (_DirectSound->GetCaps(&caps) != DS_OK)  
00770     {
00771         throw ESoundDriver("Failed to query the sound device caps");
00772     }
00773 
00774     return caps.dwFreeHw3DStreamingBuffers;
00775 }

uint NLSOUND::CSoundDriverDSound::countMaxSources  )  [virtual]
 

Return the maximum number of sources that can created.

Implements NLSOUND::ISoundDriver.

Definition at line 613 of file sound_driver_dsound.cpp.

References countHw2DBuffers(), countHw3DBuffers(), and uint.

00614 {
00615         // Try the hardware 3d buffers first
00616         uint n = countHw3DBuffers();
00617         if (n > 0) 
00618         {
00619                 return n;
00620         }
00621 
00622         // If not, try the hardware 2d buffers first
00623         n = countHw2DBuffers();
00624         if (n > 0)
00625         {
00626                 return n;
00627         }
00628 
00629         // Okay, we'll use 32 software buffers
00630         return 32;
00631 }

uint NLSOUND::CSoundDriverDSound::countPlayingSources  ) 
 

Count the number of sources that are actually playing.

Definition at line 911 of file sound_driver_dsound.cpp.

References uint.

Referenced by writeProfile().

00912 {
00913     uint n = 0;
00914         set<CSourceDSound*>::iterator iter;
00915 
00916         for (iter = _Sources.begin(); iter != _Sources.end(); iter++)
00917         {
00918                 if ((*iter)->isPlaying()) 
00919                 {
00920                         n++;
00921                 }
00922         }
00923 
00924     return n;
00925 }

IBuffer * NLSOUND::CSoundDriverDSound::createBuffer  )  [virtual]
 

Create a sound buffer.

Implements NLSOUND::ISoundDriver.

Definition at line 820 of file sound_driver_dsound.cpp.

References _PrimaryBuffer.

00821 {
00822         NL_ALLOC_CONTEXT(NLSOUND_CSoundDriverDSound);
00823     if (_PrimaryBuffer == 0) 
00824     {
00825         throw ESoundDriver("Corrupt driver");
00826     }
00827 
00828 
00829     // FIXME: set buffer ID
00830     return new CBufferDSound();
00831 }

ISoundDriver * NLSOUND::ISoundDriver::createDriver bool  useEax,
IStringMapperProvider stringMapper
[static, inherited]
 

The static method which builds the sound driver instance In case of failure, can throw one of these ESoundDriver exception objects: ESoundDriverNotFound, ESoundDriverCorrupted, ESoundDriverOldVersion, ESoundDriverUnknownVersion

You can request support for EAX. If EAX is requested and if there is enougth hardware buffer replay, then only hardware buffer are created when calling createBuffer. If the number of available hardware buffer is less than 10, then EAX is ignored.

Definition at line 61 of file sound_driver.cpp.

References buffer, NLSOUND::ISDRV_CREATE_PROC, NLSOUND::ISDRV_VERSION_PROC, nlinfo, and nlwarning.

00062 {
00063         ISDRV_CREATE_PROC       createSoundDriver = NULL;
00064         ISDRV_VERSION_PROC      versionDriver = NULL;
00065 
00066 #ifdef NL_OS_WINDOWS
00067 
00068         // WINDOWS code.
00069         HINSTANCE                       hInst;
00070 
00071         hInst = LoadLibrary(NLSOUND_DLL_NAME);
00072 
00073         if (!hInst)
00074         {
00075                 throw ESoundDriverNotFound();
00076         }
00077 
00078         char buffer[1024], *ptr;
00079         SearchPath (NULL, NLSOUND_DLL_NAME, NULL, 1023, buffer, &ptr);
00080         nlinfo ("Using the library '"NLSOUND_DLL_NAME"' that is in the directory: '%s'", buffer);
00081 
00082         createSoundDriver = (ISDRV_CREATE_PROC) GetProcAddress (hInst, IDRV_CREATE_PROC_NAME);
00083         if (createSoundDriver == NULL)
00084         {
00085                 nlinfo( "Error: %u", GetLastError() );
00086                 throw ESoundDriverCorrupted();
00087         }
00088 
00089         versionDriver = (ISDRV_VERSION_PROC) GetProcAddress (hInst, IDRV_VERSION_PROC_NAME);
00090         if (versionDriver != NULL)
00091         {
00092                 if (versionDriver()<ISoundDriver::InterfaceVersion)
00093                         throw ESoundDriverOldVersion();
00094                 else if (versionDriver()>ISoundDriver::InterfaceVersion)
00095                         throw ESoundDriverUnknownVersion();
00096         }
00097 
00098 #elif defined (NL_OS_UNIX)
00099 
00100         // Unix code
00101         void *handle = dlopen(NLSOUND_DLL_NAME, RTLD_NOW);
00102 
00103         if (handle == NULL)
00104         {
00105                 nlwarning ("when loading dynamic library '%s': %s", NLSOUND_DLL_NAME, dlerror());
00106                 throw ESoundDriverNotFound();
00107         }
00108 
00109         /* Not ANSI. Might produce a warning */
00110         createSoundDriver = (ISDRV_CREATE_PROC) dlsym (handle, IDRV_CREATE_PROC_NAME);
00111         if (createSoundDriver == NULL)
00112         {
00113                 nlwarning ("when getting function in dynamic library '%s': %s", NLSOUND_DLL_NAME, dlerror());
00114                 throw ESoundDriverCorrupted();
00115         }
00116 
00117         versionDriver = (ISDRV_VERSION_PROC) dlsym (handle, IDRV_VERSION_PROC_NAME);
00118         if (versionDriver != NULL)
00119         {
00120                 if (versionDriver()<ISoundDriver::InterfaceVersion)
00121                         throw ESoundDriverOldVersion();
00122                 else if (versionDriver()>ISoundDriver::InterfaceVersion)
00123                         throw ESoundDriverUnknownVersion();
00124         }
00125 
00126 #else // NL_OS_UNIX
00127 #error "Dynamic DLL loading not implemented!"
00128 #endif // NL_OS_UNIX
00129 
00130         ISoundDriver *ret = createSoundDriver(useEax, stringMapper);
00131         if ( ret == NULL )
00132         {
00133                 throw ESoundDriverCantCreateDriver();
00134         }
00135         return ret;
00136 }

IListener * NLSOUND::CSoundDriverDSound::createListener  )  [virtual]
 

Create the listener instance.

Implements NLSOUND::ISoundDriver.

Definition at line 794 of file sound_driver_dsound.cpp.

References _PrimaryBuffer, and nlwarning.

00795 {
00796         NL_ALLOC_CONTEXT(NLSOUND_CSoundDriverDSound);
00797     LPDIRECTSOUND3DLISTENER8 dsoundListener;
00798 
00799     if (CListenerDSound::instance() != NULL) 
00800     {
00801         return CListenerDSound::instance();
00802     }
00803 
00804     if (_PrimaryBuffer == 0) 
00805     {
00806         throw ESoundDriver("Corrupt driver");
00807     }
00808 
00809     if (FAILED(_PrimaryBuffer->QueryInterface(IID_IDirectSound3DListener, (LPVOID *) &dsoundListener)))
00810     {
00811                 nlwarning("The 3D listener interface is not available.");
00812         return new CListenerDSound(NULL);
00813     }
00814 
00815     return new CListenerDSound(dsoundListener);
00816 }

ISource * NLSOUND::CSoundDriverDSound::createSource  )  [virtual]
 

Create a source.

Implements NLSOUND::ISoundDriver.

Definition at line 860 of file sound_driver_dsound.cpp.

References _DirectSound, _PrimaryBuffer, _UseEAX, and src.

00861 {
00862         NL_ALLOC_CONTEXT(NLSOUND_CSoundDriverDSound);
00863     if (_PrimaryBuffer == 0) 
00864     {
00865         throw ESoundDriver("Corrupt driver");
00866     }
00867 
00868 
00869         CSourceDSound* src = new CSourceDSound(0);
00870         src->init(_DirectSound, _UseEAX);
00871         _Sources.insert(src);
00872 
00873         return src;
00874 }

void NLSOUND::CSoundDriverDSound::displayBench NLMISC::CLog log  )  [private, virtual]
 

Implements NLSOUND::ISoundDriver.

Definition at line 1064 of file sound_driver_dsound.cpp.

References NLMISC::CHTimer::display(), NLMISC::CHTimer::displayByExecutionPath(), NLMISC::CHTimer::displayHierarchical(), and NLMISC::CHTimer::displayHierarchicalByExecutionPathSorted().

01065 {
01066                 NLMISC::CHTimer::displayHierarchicalByExecutionPathSorted(log, CHTimer::TotalTime, true, 48, 2);
01067                 NLMISC::CHTimer::displayHierarchical(log, true, 48, 2);
01068                 NLMISC::CHTimer::displayByExecutionPath(log, CHTimer::TotalTime);
01069                 NLMISC::CHTimer::display(log, CHTimer::TotalTime);
01070 }

void NLSOUND::CSoundDriverDSound::endBench  )  [private, virtual]
 

Implements NLSOUND::ISoundDriver.

Definition at line 1060 of file sound_driver_dsound.cpp.

References NLMISC::CHTimer::endBench().

01061 {
01062         NLMISC::CHTimer::endBench();
01063 }

float NLSOUND::CSoundDriverDSound::getGain  ) 
 

Get the gain.

Definition at line 962 of file sound_driver_dsound.cpp.

References _PrimaryBuffer, and nldebug.

00963 {
00964         if (_PrimaryBuffer != 0)
00965         {
00966                 /* convert from hundredths of decibels to linear amplitude */
00967                 LONG volume;
00968                 HRESULT hr = _PrimaryBuffer->GetVolume(&volume);
00969 
00970                 if (hr != DS_OK)
00971                 {
00972                         nldebug("Failed to get the volume");
00973                         return 1.0;
00974                 }
00975 
00976                 return (float) pow(10, (double) volume / 20.0 / 100.0);
00977         }
00978 
00979         return 1.0;
00980 }

IStringMapperProvider* NLSOUND::CSoundDriverDSound::getStringMapper  )  [inline]
 

Return the string mapper.

Definition at line 112 of file sound_driver_dsound.h.

References _StringMapper.

00112 {return _StringMapper;}

bool NLSOUND::CSoundDriverDSound::init HWND  wnd,
bool  useEax,
IStringMapperProvider *  stringMapper
[virtual]
 

Initialization.

Definition at line 318 of file sound_driver_dsound.cpp.

References _Caps, _DirectSound, _PrimaryBuffer, _StringMapper, _TimerID, _TimerPeriod, _TimerResolution, _UseEAX, countHw2DBuffers(), countHw3DBuffers(), NLSOUND::CSoundDriverDSoundEnumCallback(), format, nldebug, nlwarning, res, uint, and uint32.

00319 {
00320         _StringMapper = stringMapper;
00321     if (FAILED(DirectSoundEnumerate(CSoundDriverDSoundEnumCallback, this)))
00322     {
00323         throw ESoundDriver("Failed to enumerate the DirectSound devices");
00324     }
00325 
00326     // Create a DirectSound object and set the cooperative level.
00327 
00328         if (useEax)
00329         {
00330                 if (EAXDirectSoundCreate8(NULL, &_DirectSound, NULL) != DS_OK) 
00331                 {
00332                         throw ESoundDriver("Failed to create the DirectSound object from EAX proxy funtion");
00333                 }
00334         }
00335         else
00336         {
00337                 if (DirectSoundCreate8(NULL, &_DirectSound, NULL) != DS_OK) 
00338                 {
00339                         throw ESoundDriver("Failed to create the DirectSound object");
00340                 }
00341         }
00342 
00343 
00344     if (_DirectSound->SetCooperativeLevel(wnd, DSSCL_PRIORITY) != DS_OK) 
00345     {
00346         throw ESoundDriver("Failed to set the cooperative level");
00347     }
00348 
00349 
00350     // Analyse the capabilities of the sound driver/device
00351 
00352     _Caps.dwSize = sizeof(_Caps); 
00353 
00354     if (_DirectSound->GetCaps(&_Caps) != DS_OK)  
00355     {
00356         throw ESoundDriver("Failed to query the sound device caps");
00357     }
00358 
00359 
00360     // Create primary buffer 
00361  
00362     DSBUFFERDESC desc;
00363 
00364     ZeroMemory(&desc, sizeof(DSBUFFERDESC));
00365     desc.dwSize = sizeof(DSBUFFERDESC);
00366 
00367 
00368     // First, try to allocate a 3D hardware buffer.
00369     // If we can't get a 3D hardware buffer, use a 2D hardware buffer.
00370     // As last option, use a 2D software buffer.
00371 
00372         // check if wa can honor eax request
00373         if (countHw3DBuffers() > 10)
00374         {
00375                 _UseEAX = useEax;
00376         }
00377         else
00378         {
00379                 // not enougth hardware buffer, can't use eax
00380                 _UseEAX = false;
00381         }
00382 
00383     if (countHw3DBuffers() > 0) 
00384     {
00385                 nldebug("Primary buffer: Allocating 3D buffer in hardware");
00386         desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_LOCHARDWARE | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
00387     } 
00388     else
00389     {
00390                 nldebug("Primary buffer: Allocating 3D buffer in software");
00391         desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
00392 //        desc.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
00393     }
00394         
00395 
00396 
00397         HRESULT res = _DirectSound->CreateSoundBuffer(&desc, &_PrimaryBuffer, NULL);
00398 
00399     if (res != DS_OK && res != DS_NO_VIRTUALIZATION)
00400     {
00401 
00402                 nlwarning("Primary buffer: Failed to create a buffer with 3D capabilities.");
00403 
00404                 ZeroMemory(&desc, sizeof(DSBUFFERDESC));
00405                 desc.dwSize = sizeof(DSBUFFERDESC);
00406 
00407                 if (countHw2DBuffers() > 0) 
00408                 {
00409                         nldebug("Primary buffer: Allocating 2D buffer in hardware");
00410                         desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_LOCHARDWARE | DSBCAPS_CTRLVOLUME;
00411                 } 
00412                 else
00413                 {
00414                         nldebug("Primary buffer: Allocating 2D buffer in software");
00415                         desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLVOLUME;
00416                 }
00417 
00418                 if (_DirectSound->CreateSoundBuffer(&desc, &_PrimaryBuffer, NULL) != DS_OK) 
00419                 {
00420                         throw ESoundDriver("Failed to create the primary buffer");
00421                 }
00422     }
00423 
00424 
00425     // Set the format of the primary buffer
00426 
00427     WAVEFORMATEX format;
00428 
00429     format.cbSize = sizeof(WAVEFORMATEX);
00430 
00431     // Make sure the sound card accepts the default settings.
00432     // For now, only the default settings are accepted. Fallback
00433     // strategy will be handled later.
00434 
00435     if ((_Caps.dwMinSecondarySampleRate > 22050) && (22050 > _Caps.dwMaxSecondarySampleRate)) {
00436         throw ESoundDriver("Unsupported sample rate range");        
00437     }   
00438 
00439     if ((_Caps.dwFlags & DSCAPS_PRIMARY16BIT) == 0) {
00440         throw ESoundDriver("Unsupported sample size [16bits]");        
00441     }   
00442 
00443     format.wBitsPerSample = 16;
00444     format.nChannels = 1;
00445     format.nSamplesPerSec = 22050;
00446     format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
00447     format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
00448     format.wFormatTag = WAVE_FORMAT_PCM;
00449 
00450 
00451     if (_PrimaryBuffer->SetFormat(&format) != DS_OK) 
00452     {
00453         throw ESoundDriver("Failed to create set the format of the primary buffer");
00454     }
00455 
00456         // Fill the buffer with silence
00457 /*      LPVOID ptr;
00458         DWORD bytes;
00459 
00460         HRESULT hr = _PrimaryBuffer->Lock(0, 0, &ptr, &bytes, NULL, NULL, DSBLOCK_ENTIREBUFFER);
00461         if (FAILED(hr))
00462         {
00463                 switch (hr)
00464                 {
00465                 case DSERR_BUFFERLOST:
00466                         throw ESoundDriver("Failed to lock the DirectSound primary buffer : DSERR_BUFFERLOST");
00467                 case DSERR_INVALIDCALL:
00468                         throw ESoundDriver("Failed to lock the DirectSound primary buffer : DSERR_INVALIDCALL");
00469                 case DSERR_INVALIDPARAM:
00470                         throw ESoundDriver("Failed to lock the DirectSound primary buffer : DSERR_INVALIDPARAM");
00471                 case DSERR_PRIOLEVELNEEDED:
00472                         throw ESoundDriver("Failed to lock the DirectSound primary buffer : DSERR_PRIOLEVELNEEDED");
00473                 default:
00474                         throw ESoundDriver("Failed to lock the DirectSound primary buffer : unkown error");
00475                 
00476                 }
00477         }
00478 
00479         memset(ptr, 0, bytes);
00480         
00481         _PrimaryBuffer->Unlock(ptr, bytes, 0, 0);
00482 */
00483 
00484     uint32 numBuffers = countHw3DBuffers();
00485         if (numBuffers == 0)
00486         {
00487                 numBuffers = 31;
00488         }
00489 
00490         /*
00491     _Sources = new CSourceDSound*[numBuffers];
00492 
00493 
00494         for (uint i = 0; i < numBuffers; i++) 
00495         {
00496                 _Sources[i] = 0;
00497         }
00498 
00499         try
00500         {
00501             for (i = 0; i < numBuffers; i++) 
00502                 {
00503                         _Sources[i] = new CSourceDSound(i);
00504                         _Sources[i]->init(_DirectSound);
00505                         _SourceCount++;
00506                 }
00507         }
00508         catch (ESoundDriver& e)
00509         {
00510                 // Okay, here's the situation: I'm listening to WinAmp while debugging.
00511                 // The caps told me there were 31 buffers available. In reality, there were
00512                 // only 30 available because WinAmp was using one. Somehow DirectSound didn't
00513                 // notice. So when creating buffer 31, an exception was thrown. 
00514                 // If something like this happens, don't bother and go on with the buffers we've 
00515                 // got. If no buffers are created at all, throw the exception again.
00516 
00517                 if (_Sources == 0)
00518                 {
00519                         throw e;
00520                 }
00521         }
00522 
00523 */
00524 
00525 
00526     TIMECAPS tcaps;
00527     
00528     timeGetDevCaps(&tcaps, sizeof(TIMECAPS));
00529     _TimerResolution = (tcaps.wPeriodMin > 10)? tcaps.wPeriodMin : 10;
00530     timeBeginPeriod(_TimerResolution); 
00531 
00532 
00533 
00534 #if NLSOUND_PROFILE
00535     for (uint i = 0; i < 1024; i++)
00536     {
00537         _TimerInterval[i] = 0;
00538     }
00539 
00540     _TimerDate = CTime::getPerformanceTime();
00541 #endif
00542 
00543 
00544 
00545 
00546     _TimerID = timeSetEvent(_TimerPeriod, 0, &CSoundDriverDSound::TimerCallback, (DWORD)this, TIME_CALLBACK_FUNCTION | TIME_PERIODIC);
00547 
00548     if (_TimerID == NULL)
00549     {
00550         throw ESoundDriver("Failed to create the timer");
00551     }
00552 
00553         
00554 
00555 
00556     return true;
00557 }

CSoundDriverDSound* NLSOUND::CSoundDriverDSound::instance  )  [inline, static]
 

Return the instance of the singleton.

Definition at line 55 of file sound_driver_dsound.h.

00055 { return _Instance; }

bool NLSOUND::CSoundDriverDSound::readRawBuffer IBuffer destbuffer,
const std::string &  name,
uint8 rawData,
uint  dataSize,
TSampleFormat  format,
uint32  frequency
[virtual]
 

Implements NLSOUND::ISoundDriver.

Definition at line 852 of file sound_driver_dsound.cpp.

References format, uint, uint32, and uint8.

00853 {
00854         return ((CBufferDSound*) destbuffer)->readRawBuffer(name, rawData, dataSize, format, frequency);
00855 }

bool NLSOUND::CSoundDriverDSound::readWavBuffer IBuffer destbuffer,
const std::string &  name,
uint8 wavData,
uint  dataSize
[virtual]
 

Load a wave file in to the buffer.

Implements NLSOUND::ISoundDriver.

Definition at line 847 of file sound_driver_dsound.cpp.

References uint, and uint8.

00848 {
00849         return ((CBufferDSound*) destbuffer)->readWavBuffer(name, wavData, dataSize);
00850 }

void NLSOUND::CSoundDriverDSound::removeBuffer IBuffer buffer  )  [private, virtual]
 

Remove a buffer (should be called by the friend destructor of the buffer class).

Implements NLSOUND::ISoundDriver.

Definition at line 835 of file sound_driver_dsound.cpp.

References buffer.

00836 {
00837 }

void NLSOUND::CSoundDriverDSound::removeSource ISource source  )  [private, virtual]
 

Remove a source (should be called by the friend destructor of the source class).

Implements NLSOUND::ISoundDriver.

Definition at line 879 of file sound_driver_dsound.cpp.

00880 {
00881         _Sources.erase((CSourceDSound*) source);
00882 }

void NLSOUND::CSoundDriverDSound::setGain float  gain  ) 
 

Set the gain (volume value inside [0 , 1]). (default: 1) 0.0 -> silence 0.5 -> -6dB 1.0 -> no attenuation values > 1 (amplification) not supported by most drivers

Definition at line 930 of file sound_driver_dsound.cpp.

References _PrimaryBuffer, and nldebug.

00931 {
00932         if (_PrimaryBuffer != 0)
00933         {
00934                 if (gain < 0.00001f)
00935                 {
00936                         gain = 0.00001f;
00937                 }
00938 
00939                 /* convert from linear amplitude to hundredths of decibels */
00940                 LONG volume = (LONG)(100.0 * 20.0 * log10(gain));
00941 
00942                 if (volume < DSBVOLUME_MIN) 
00943                 {
00944                         volume = DSBVOLUME_MIN;
00945                 }
00946                 else if (volume > DSBVOLUME_MAX) 
00947                 {
00948                         volume = DSBVOLUME_MAX;
00949                 }
00950 
00951                 HRESULT hr = _PrimaryBuffer->SetVolume(volume);
00952 
00953                 if (hr != DS_OK)
00954                 {
00955                         nldebug("Failed to set the volume");
00956                 }
00957         }
00958 }

void NLSOUND::CSoundDriverDSound::startBench  )  [private, virtual]
 

Implements NLSOUND::ISoundDriver.

Definition at line 1056 of file sound_driver_dsound.cpp.

References NLMISC::CHTimer::startBench().

01057 {
01058         NLMISC::CHTimer::startBench();
01059 }

void CALLBACK NLSOUND::CSoundDriverDSound::TimerCallback UINT  uID,
UINT  uMsg,
DWORD  dwUser,
DWORD  dw1,
DWORD  dw2
[static, private]
 

Definition at line 679 of file sound_driver_dsound.cpp.

References _TimerPeriod, NLMISC::CTime::getLocalTime(), NLMISC::TTime, and update().

00680 {
00681         // a little speed check
00682         static NLMISC::TTime lastUpdate = NLMISC::CTime::getLocalTime();
00683         NLMISC::TTime now = NLMISC::CTime::getLocalTime();
00684 
00685         if (now - lastUpdate > _TimerPeriod * 2)
00686         {
00687 //              nlwarning("CSoundDriverDSound::TimerCallback : no update since %u millisec (nominal update = %u", uint32(now-lastUpdate), uint32(_TimerPeriod));
00688         }
00689         else
00690         {
00691 //              nldebug("Callback delay = %u ms", uint32(now-lastUpdate));
00692         }
00693 
00694         lastUpdate = now;
00695 
00696 
00697     CSoundDriverDSound* driver = (CSoundDriverDSound*) dwUser;
00698     driver->update();
00699 }

void NLSOUND::CSoundDriverDSound::update  ) 
 

Update all the driver and its sources. To be called only by the timer callback.

Definition at line 703 of file sound_driver_dsound.cpp.

References _TimerPeriod, NLMISC::CTime::getLocalTime(), H_AUTO, nlwarning, NLMISC::TTicks, NLMISC::TTime, and uint32.

Referenced by TimerCallback().

00704 {
00705         H_AUTO(NLSOUND_DSoundUpdate)
00706 #if NLSOUND_PROFILE
00707     TTicks tnow = CTime::getPerformanceTime();
00708 #endif
00709 
00710         NLMISC::TTime now = NLMISC::CTime::getLocalTime();
00711 
00712         set<CSourceDSound*>::iterator first(_Sources.begin()), last(_Sources.end());
00713         for (;first != last; ++first)
00714         {
00715                 if ((*first)->needsUpdate())
00716                 {
00717                         if ((*first)->update()) 
00718                         {
00719 #if NLSOUND_PROFILE
00720                                 _UpdateSources++;
00721 #endif
00722                         }
00723                 }
00724         }
00725 
00726 /*
00727         set<CSourceDSound*>::iterator iter;
00728 
00729         iter = _Sources.begin();
00730 
00731 
00732         if ((iter != _Sources.end()) && (*iter)->needsUpdate())
00733         {
00734                 while (iter != _Sources.end())
00735                 {
00736 //                      if ((*iter)->update2()) {
00737                         if ((*iter)->update()) 
00738                         {
00739 #if NLSOUND_PROFILE
00740                                 _UpdateSources++;
00741 #endif
00742                         }
00743                         iter++;
00744                 }
00745         }
00746 
00747 */
00748         {
00749                 NLMISC::TTime   last = CTime::getLocalTime() - now;
00750                 if (last > _TimerPeriod / 2)
00751                 {
00752                         nlwarning("CSoundDriverDSound::TimerCallback : update took %u millisec", (uint32)last);
00753                 }
00754         }
00755 
00756 #if NLSOUND_PROFILE
00757     _TotalUpdateTime += 1000.0 * CTime::ticksToSecond(CTime::getPerformanceTime() - tnow);
00758         _UpdateCount++;
00759 #endif
00760 }

void NLSOUND::CSoundDriverDSound::writeProfile std::ostream &  out  )  [virtual]
 

Write information about the driver to the output stream.

Implements NLSOUND::ISoundDriver.

Definition at line 635 of file sound_driver_dsound.cpp.

References _DirectSound, and countPlayingSources().

00636 {
00637     // Write the available sound devices
00638     CDeviceDescription* list = CDeviceDescription::_List;
00639     while (list) {
00640                 out << list->_Description << "\n";
00641         list = list->_Next;
00642     }
00643 
00644     out << "\n";
00645 
00646     // Write the buffers sizes
00647     out << "buffer size: " << (int)CSourceDSound::_SecondaryBufferSize << "\n";
00648     out << "copy size: " << (int)CSourceDSound::_UpdateCopySize << "\n";
00649     out << "swap size: " << (int)CSourceDSound::_SwapCopySize << "\n";
00650     out << "\n";
00651 
00652     // Write the number of hardware buffers 
00653     DSCAPS caps;
00654     caps.dwSize = sizeof(caps); 
00655     _DirectSound->GetCaps(&caps);  
00656 
00657     cout << "3d hw buffers: " << caps.dwMaxHw3DAllBuffers << "\n";
00658         cout << "2d hw buffers: " << caps.dwMaxHwMixingAllBuffers << "\n";
00659     out << "\n";
00660 
00661     // Write the number of hardware buffers 
00662 #if NLSOUND_PROFILE
00663     out << "update time total --- " <<  getAverageUpdateTime()<< "\n";
00664         out << "update time source --- " << CSourceDSound::getAverageUpdateTime() << "\n";
00665         out << "update --- t: " << CSourceDSound::getAverageCumulTime();
00666         out << " - p: " << CSourceDSound::getAveragePosTime();
00667         out << " - l: " << CSourceDSound::getAverageLockTime();
00668         out << " - c: " << CSourceDSound::getAverageCopyTime();
00669         out << " - u: " << CSourceDSound::getAverageUnlockTime() << "\n";
00670         out << "update percentage: --- " << getUpdatePercentage() << "\n";
00671         out << "update num sources --- " << (int)getAverageUpdateSources() << "\n";
00672         out << "update byte size --- " << CSourceDSound::getAverageUpdateSize() << "\n";
00673         out << "swap time --- " << CSourceDSound::getTestAverage() << "\n";
00674         out << "src --- " << countPlayingSources() << "\n";
00675 #endif
00676 }


Field Documentation

DSCAPS NLSOUND::CSoundDriverDSound::_Caps [private]
 

Definition at line 151 of file sound_driver_dsound.h.

Referenced by init().

LPDIRECTSOUND8 NLSOUND::CSoundDriverDSound::_DirectSound [private]
 

Definition at line 145 of file sound_driver_dsound.h.

Referenced by countHw2DBuffers(), countHw3DBuffers(), createSource(), init(), writeProfile(), and ~CSoundDriverDSound().

CSoundDriverDSound * NLSOUND::CSoundDriverDSound::_Instance = NULL [static, private]
 

Definition at line 52 of file sound_driver_dsound.cpp.

LPDIRECTSOUNDBUFFER NLSOUND::CSoundDriverDSound::_PrimaryBuffer [private]
 

Definition at line 148 of file sound_driver_dsound.h.

Referenced by createBuffer(), createListener(), createSource(), getGain(), init(), setGain(), and ~CSoundDriverDSound().

uint NLSOUND::CSoundDriverDSound::_SourceCount [private]
 

Definition at line 158 of file sound_driver_dsound.h.

std::set<CSourceDSound*> NLSOUND::CSoundDriverDSound::_Sources [private]
 

Definition at line 155 of file sound_driver_dsound.h.

IStringMapperProvider* NLSOUND::CSoundDriverDSound::_StringMapper [private]
 

The string mapper provided by client code.

Definition at line 169 of file sound_driver_dsound.h.

Referenced by getStringMapper(), and init().

UINT NLSOUND::CSoundDriverDSound::_TimerID [private]
 

Definition at line 161 of file sound_driver_dsound.h.

Referenced by init(), and ~CSoundDriverDSound().

uint32 NLSOUND::CSoundDriverDSound::_TimerPeriod = 100 [static, private]
 

Definition at line 53 of file sound_driver_dsound.cpp.

Referenced by init(), TimerCallback(), and update().

uint32 NLSOUND::CSoundDriverDSound::_TimerResolution [private]
 

Definition at line 164 of file sound_driver_dsound.h.

Referenced by init(), and ~CSoundDriverDSound().

bool NLSOUND::CSoundDriverDSound::_UseEAX [private]
 

The EAX support is requested and accepted (ie, there is enougth hardware 3D buffer).

Definition at line 167 of file sound_driver_dsound.h.

Referenced by createSource(), and init().

const uint32 NLSOUND::ISoundDriver::InterfaceVersion = 0x08 [static, inherited]
 

Version of the driver interface. To increment when the interface change.

Definition at line 48 of file sound_driver.cpp.


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 14:44:35 2004 for NeL by doxygen 1.3.6