From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/source__dsound_8cpp-source.html | 2315 ++++++++++++++++++++++ 1 file changed, 2315 insertions(+) create mode 100644 docs/doxygen/nel/source__dsound_8cpp-source.html (limited to 'docs/doxygen/nel/source__dsound_8cpp-source.html') diff --git a/docs/doxygen/nel/source__dsound_8cpp-source.html b/docs/doxygen/nel/source__dsound_8cpp-source.html new file mode 100644 index 00000000..4ac05662 --- /dev/null +++ b/docs/doxygen/nel/source__dsound_8cpp-source.html @@ -0,0 +1,2315 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

source_dsound.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2001 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 
+00027 #include "stddsound.h"
+00028 #include "source_dsound.h"
+00029 #include "sound_driver_dsound.h"
+00030 #include "buffer_dsound.h"
+00031 #include "listener_dsound.h"
+00032 
+00033 
+00034 
+00035 using namespace NLMISC;
+00036 
+00037 
+00038 namespace NLSOUND {
+00039 
+00040 
+00041 #if NLSOUND_PROFILE
+00042 
+00043         #define INITTIME(_var)   TTicks _var = CTime::getPerformanceTime()
+00044 
+00045         #define DEBUG_POSITIONS  1
+00046 
+00047         #if DEBUG_POSITIONS
+00048         #define DBGPOS(_a) nldebug ## _a
+00049         #else
+00050         #define DBGPOS(_a) 
+00051         #endif
+00052 
+00053 #else
+00054         #define INITTIME(_var)
+00055         #define DBGPOS(_a) 
+00056 #endif
+00057 
+00058 
+00059 
+00060 uint32 CSourceDSound::_SecondaryBufferSize = 65536;
+00061 uint32 CSourceDSound::_SwapCopySize = 32768;
+00062 uint32 CSourceDSound::_UpdateCopySize = 16384;
+00063 uint32 CSourceDSound::_XFadeSize = 64;
+00064 uint CSourceDSound::_DefaultChannels = 1;
+00065 uint CSourceDSound::_DefaultSampleRate = 22050;
+00066 uint CSourceDSound::_DefaultSampleSize = 16;
+00067 
+00068 
+00069 
+00070 #define NLSOUND_MIN(_a,_b)        (((_a) < (_b)) ? (_a) : (_b))
+00071 #define NLSOUND_DISTANCE(_from, _to, _period)   (((_to) > (_from)) ? (_to) - (_from) : (_period) + (_to) - (_from))
+00072 
+00073 
+00074 #if NLSOUND_PROFILE
+00075 
+00076 // Static variables used for profiling
+00077 double CSourceDSound::_LastSwapTime = 0.0;
+00078 double CSourceDSound::_TotalSwapTime = 0.0;
+00079 double CSourceDSound::_MaxSwapTime = 0.0;
+00080 double CSourceDSound::_MinSwapTime = 1000000.0;
+00081 uint32 CSourceDSound::_SwapCount = 0;
+00082 double CSourceDSound::_PosTime = 0.0;
+00083 double CSourceDSound::_LockTime = 0.0;
+00084 double CSourceDSound::_CopyTime = 0.0;
+00085 double CSourceDSound::_UnlockTime = 0.0;
+00086 uint32 CSourceDSound::_CopyCount = 0;
+00087 double CSourceDSound::_TotalUpdateTime = 0.0;
+00088 double CSourceDSound::_MaxUpdateTime = 0.0;
+00089 double CSourceDSound::_MinUpdateTime = 1000000.0;
+00090 uint32 CSourceDSound::_UpdateCount = 0;
+00091 uint32 CSourceDSound::_TotalUpdateSize = 0;
+00092 #endif
+00093 
+00094 
+00095 
+00096 // ******************************************************************
+00097 
+00098 CSourceDSound::CSourceDSound( uint sourcename ) : ISource(), _SourceName(sourcename)
+00099 {
+00100         _BufferSize = 0;
+00101         _SwapBuffer = 0;
+00102         _SecondaryBuffer = 0;
+00103         _SecondaryBufferState = NL_DSOUND_SILENCED;
+00104         _3DBuffer = 0;
+00105         _NextWritePos = 0;
+00106         _BytesWritten = 0;
+00107         _SilenceWritten = 0;
+00108         _Loop = false;
+00109         _EndPosition = 0;
+00110         _EndState = NL_DSOUND_TAIL1;
+00111         _UserState = NL_DSOUND_STOPPED;
+00112         _Freq = 1.0f;
+00113         _SampleRate = _DefaultSampleRate;
+00114         _IsUsed = false;
+00115         _Gain = 1.0f;
+00116         _Volume = 0;
+00117         _Alpha = 0.0;
+00118         InitializeCriticalSection(&_CriticalSection);
+00119 }
+00120 
+00121 
+00122 // ******************************************************************
+00123 
+00124 CSourceDSound::~CSourceDSound()
+00125 {
+00126         nldebug("Destroying DirectSound source");
+00127 
+00128         CSoundDriverDSound::instance()->removeSource(this);
+00129 
+00130         EnterCriticalSection(&_CriticalSection); 
+00131 
+00132         // Release the DirectSound buffer within the critical zone
+00133         // to avoid a call to update during deconstruction
+00134         release();
+00135 
+00136         LeaveCriticalSection(&_CriticalSection); 
+00137         DeleteCriticalSection(&_CriticalSection);
+00138 }
+00139 
+00140 
+00141 // ******************************************************************
+00142 
+00143 void CSourceDSound::release()
+00144 {
+00145         _Buffer = 0;
+00146 
+00147         if (_SecondaryBuffer != 0)
+00148         {
+00149                 _SecondaryBuffer->Stop();
+00150         }
+00151 
+00152         if (_3DBuffer != 0)
+00153         {
+00154                 _3DBuffer->Release();
+00155                 _3DBuffer = 0;
+00156         }
+00157 
+00158         if (_SecondaryBuffer != 0)
+00159         {
+00160                 _SecondaryBuffer->Release();
+00161                 _SecondaryBuffer = 0;
+00162         }
+00163 
+00164 }
+00165 
+00166 // ******************************************************************
+00167 
+00168 void CSourceDSound::init(LPDIRECTSOUND directSound)
+00169 {
+00170 
+00171         // Initialize the buffer format
+00172         WAVEFORMATEX format;
+00173 
+00174         format.cbSize = sizeof(WAVEFORMATEX);
+00175         format.nChannels = _DefaultChannels;
+00176         format.wBitsPerSample = _DefaultSampleSize;
+00177         format.nSamplesPerSec = _DefaultSampleRate;
+00178         format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
+00179         format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+00180         format.wFormatTag = WAVE_FORMAT_PCM;
+00181 
+00182 
+00183         // Initialize the buffer description 
+00184 
+00185         DSBUFFERDESC desc;
+00186 
+00187         CSoundDriverDSound* driver = CSoundDriverDSound::instance();
+00188 
+00189 
+00190         ZeroMemory(&desc, sizeof(DSBUFFERDESC));
+00191         desc.dwSize = sizeof(DSBUFFERDESC);
+00192         desc.lpwfxFormat = &format;
+00193         desc.dwBufferBytes = _SecondaryBufferSize;      
+00194         desc.dwReserved = 0; 
+00195 
+00196         if (driver->countHw3DBuffers() > 0)
+00197         {
+00198                 //nldebug("Source: Allocating 3D buffer in hardware");
+00199                 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCHARDWARE | DSBCAPS_GETCURRENTPOSITION2 
+00200                                                 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
+00201         } 
+00202         else
+00203         {
+00204                 //nldebug("Source: Allocating 3D buffer in software");
+00205                 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2 
+00206                                                 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
+00207                 desc.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
+00208                 //desc.guid3DAlgorithm = DS3DALG_HRTF_FULL;
+00209         }
+00210 
+00211 
+00212         // Allocate the secondary buffer
+00213  
+00214         if (FAILED(directSound->CreateSoundBuffer(&desc, &_SecondaryBuffer, NULL))) 
+00215         {
+00216                 nlwarning("Source: Failed to create a buffer with 3D capabilities.");
+00217 
+00218                 ZeroMemory(&desc, sizeof(DSBUFFERDESC));
+00219                 desc.dwSize = sizeof(DSBUFFERDESC);
+00220                 desc.lpwfxFormat = &format;
+00221                 desc.dwBufferBytes = _SecondaryBufferSize;      
+00222                 desc.dwReserved = 0; 
+00223 
+00224                 if (driver->countHw2DBuffers() > 0)
+00225                 {
+00226                         //nldebug("Source: Allocating 2D buffer in hardware");
+00227                         desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCHARDWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+00228                 } 
+00229                 else
+00230                 {
+00231                         //nldebug("Source: Allocating 2D buffer in software");
+00232                         desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+00233                 }
+00234 
+00235                 if (FAILED(directSound->CreateSoundBuffer(&desc, &_SecondaryBuffer, NULL))) 
+00236                 {
+00237                         throw ESoundDriver("Failed to allocate the DirectSound secondary buffer");
+00238                 }
+00239         }
+00240 
+00241 
+00242         // Fill the buffer with silence
+00243 
+00244         LPVOID ptr;
+00245         DWORD bytes;
+00246 
+00247         if (FAILED(_SecondaryBuffer->Lock(0, 0, &ptr, &bytes, NULL, NULL, DSBLOCK_ENTIREBUFFER)))
+00248         {
+00249                 throw ESoundDriver("Failed to lock the DirectSound secondary buffer");
+00250         }
+00251 
+00252         memset(ptr, 0, bytes);
+00253         
+00254         _SecondaryBuffer->Unlock(ptr, bytes, 0, 0);
+00255 
+00256         // Allocate the 3D interface, if necessary
+00257 
+00258         if (FAILED(_SecondaryBuffer->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID *) &_3DBuffer)))
+00259         {
+00260            throw ESoundDriver("Failed to allocate the DirectSound 3D buffer");
+00261         }
+00262 
+00263 
+00264         if (FAILED(_SecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING)))
+00265         {
+00266                 throw ESoundDriver("Play failed");
+00267         }
+00268 
+00269 }
+00270 
+00271 // ******************************************************************
+00272 
+00273 void CSourceDSound::reset()
+00274 {
+00275         setPitch(1.0f);
+00276         setLooping(false);
+00277         setGain(1.0f);
+00278 }
+00279 
+00280 
+00281 // ******************************************************************
+00282 
+00283 void CSourceDSound::setStaticBuffer( IBuffer *buffer )
+00284 {
+00285         EnterCriticalSection(&_CriticalSection); 
+00286 
+00287         // If the user calls setStaticBuffer with a null buffer,
+00288         // stop the currently playing buffer and set it to null.
+00289         // Otherwise, store the buffer in the swap buffer variable.
+00290         // A crossfade between the current buffer and the swap buffer
+00291         // will be done when the user calls play.
+00292         if (buffer == 0)
+00293         {
+00294                 stop();
+00295                 _Buffer = 0;
+00296                 _BufferSize = 0;
+00297                 _BytesWritten = 0;
+00298         }
+00299 
+00300         _SwapBuffer = _Buffer = buffer;
+00301 
+00302         LeaveCriticalSection(&_CriticalSection); 
+00303 }
+00304 
+00305 
+00306 
+00307 // ******************************************************************
+00308 
+00309 void CSourceDSound::setLooping( bool l )
+00310 {
+00311         _Loop = l;
+00312 }
+00313 
+00314 
+00315 // ******************************************************************
+00316 
+00317 bool CSourceDSound::getLooping() const
+00318 {
+00319         return _Loop;
+00320 }
+00321 
+00322 
+00323 // ******************************************************************
+00324 
+00325 void CSourceDSound::swap()
+00326 {
+00327         _Buffer = _SwapBuffer;
+00328         _BufferSize = _Buffer->getSize();
+00329         _BytesWritten = 0;
+00330         _SwapBuffer = 0;
+00331 }
+00332 
+00333 // ******************************************************************
+00334 
+00335 bool CSourceDSound::play()
+00336 {
+00337         EnterCriticalSection(&_CriticalSection); 
+00338 
+00339         if (_Buffer == 0 || ((CBufferDSound*) _Buffer)->getData() == 0)
+00340         {
+00341                 // the sample has been unloaded, can't play!
+00342 
+00343                 LeaveCriticalSection(&_CriticalSection); 
+00344                 return false;
+00345         }
+00346 
+00347 
+00348         DBGPOS(("[%p] PLAY: Enter, buffer state = %u", this, _SecondaryBufferState));
+00349         switch (_SecondaryBufferState)
+00350         {
+00351         case NL_DSOUND_FILLING:
+00352                 if (_SwapBuffer != 0)
+00353                 {
+00354                         // crossfade to the new sound 
+00355                         DBGPOS(("[%p] PLAY: XFading 1", this));
+00356                         crossFade();
+00357                 }
+00358                 break;
+00359 
+00360         case NL_DSOUND_SILENCING:
+00361                 if (_SwapBuffer != 0)
+00362                 {
+00363                         if ((_Buffer != 0) && (_UserState == NL_DSOUND_PLAYING))
+00364                         {
+00365                                 // crossfade to the new sound
+00366                                 DBGPOS(("[%p] PLAY: XFading 2", this));
+00367                                 crossFade();
+00368                         }
+00369                         else
+00370                         {
+00371                                 DBGPOS(("[%p] PLAY: Swap & fadein 1", this));
+00372                                 swap();
+00373                                 fadeIn();
+00374                         }
+00375                 }
+00376                 else
+00377                 {
+00378                         DBGPOS(("[%p] PLAY: Fadein", this));
+00379                         _BytesWritten = 0;
+00380                         // start the old sound again
+00381                         fadeIn();
+00382                 }
+00383 
+00384                 break;
+00385 
+00386 
+00387         case NL_DSOUND_SILENCED:
+00388                 if (_SwapBuffer != 0)
+00389                 {
+00390                         // fade in to the new sound
+00391                                 DBGPOS(("[%p] PLAY: Swap & fadein 2", this));
+00392                         swap();
+00393                         fadeIn();
+00394                 }
+00395                 else
+00396                 {
+00397                         DBGPOS(("[%p] PLAY: Fadein", this));
+00398                         _BytesWritten = 0;
+00399                         // start the old sound again
+00400                         fadeIn();
+00401                 }
+00402         }
+00403 
+00404         _UserState = NL_DSOUND_PLAYING;
+00405         DBGPOS(("[%p] PLAY: PLAYING", this));
+00406 
+00407         //nldebug ("NLSOUND: %p play", this);
+00408 
+00409         LeaveCriticalSection(&_CriticalSection); 
+00410 
+00411         return true;
+00412 }
+00413 
+00414 
+00415 // ******************************************************************
+00416 
+00417 void CSourceDSound::stop()
+00418 {
+00419         EnterCriticalSection(&_CriticalSection); 
+00420 
+00421         TSourceDSoundUserState old = _UserState;
+00422 
+00423         _UserState = NL_DSOUND_STOPPED;
+00424         DBGPOS(("[%p] STOP: STOPPED", this));
+00425 
+00426         //nldebug ("NLSOUND: %p stop", this);
+00427 
+00428         if (old == NL_DSOUND_PLAYING)
+00429         {
+00430                 fadeOut();
+00431         }
+00432 
+00433         _BytesWritten = 0;
+00434 
+00435         LeaveCriticalSection(&_CriticalSection); 
+00436 }
+00437 
+00438 // ******************************************************************
+00439 
+00440 void CSourceDSound::pause()
+00441 {
+00442         EnterCriticalSection(&_CriticalSection); 
+00443 
+00444         TSourceDSoundUserState old = _UserState;
+00445 
+00446         _UserState = NL_DSOUND_PAUSED;
+00447         DBGPOS(("[%p] PAUZ: PAUSED", this));
+00448 
+00449         //nldebug ("NLOUND: pause %p", this);
+00450 
+00451         if (old == NL_DSOUND_PLAYING)
+00452         {
+00453                 fadeOut();
+00454         }
+00455 
+00456         LeaveCriticalSection(&_CriticalSection); 
+00457 }
+00458 
+00459 // ******************************************************************
+00460 
+00461 bool CSourceDSound::isPlaying() const
+00462 {
+00463         return (_UserState == NL_DSOUND_PLAYING);
+00464 }
+00465 
+00466 
+00467 // ******************************************************************
+00468 
+00469 bool CSourceDSound::isPaused() const
+00470 {
+00471         return (_UserState == NL_DSOUND_PAUSED);
+00472 }
+00473 
+00474 
+00475 // ******************************************************************
+00476 
+00477 bool CSourceDSound::isStopped() const
+00478 {
+00479         return (_UserState == NL_DSOUND_STOPPED);
+00480 }
+00481 
+00482 
+00483 // ******************************************************************
+00484 
+00485 bool CSourceDSound::needsUpdate()
+00486 {
+00487         DWORD playPos, writePos;
+00488         uint32 space;
+00489         
+00490         if (_SecondaryBuffer == 0)
+00491         {
+00492                 return true;
+00493         }
+00494 
+00495         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+00496 
+00497                 
+00498         if (playPos == _NextWritePos)
+00499         {
+00500                 return false;
+00501         }
+00502         else if (playPos > _NextWritePos) 
+00503         {
+00504                 space = playPos - _NextWritePos;
+00505         }
+00506         else
+00507         {
+00508                 space = _SecondaryBufferSize + playPos - _NextWritePos;
+00509         }
+00510         
+00511         // Don't bother if the number of samples is smaller than the copy size.
+00512         return (space > _UpdateCopySize);
+00513 }
+00514 
+00515 
+00516 
+00517 // ******************************************************************
+00518 
+00519 void CSourceDSound::update()
+00520 {
+00521         update2();
+00522 }
+00523 
+00524 // ******************************************************************
+00525 
+00526 bool CSourceDSound::update2()
+00527 {
+00528         bool res = false;
+00529 
+00530 
+00531 
+00532         INITTIME(start);
+00533 
+00534         //
+00535         // Enter critical region
+00536         //
+00537         EnterCriticalSection(&_CriticalSection);
+00538 
+00539 
+00540         switch (_SecondaryBufferState)
+00541         {
+00542 
+00543 
+00544         case NL_DSOUND_SILENCED:
+00545                 {
+00546                         // Just pretend were writing silence by advancing the next 
+00547                         // write position.
+00548                         _NextWritePos += _UpdateCopySize;
+00549                         if (_NextWritePos >= _SecondaryBufferSize)
+00550                         {
+00551                                 _NextWritePos  -= _SecondaryBufferSize;
+00552                         }
+00553                 }
+00554                 break;
+00555 
+00556 
+00557         case NL_DSOUND_FILLING:
+00558                 res = fill();   
+00559                 break;
+00560 
+00561 
+00562         case NL_DSOUND_SILENCING:
+00563                 res = silence();        
+00564                 break;
+00565 
+00566         }
+00567 
+00568 
+00569         //
+00570         // Leave critical region
+00571         //
+00572         LeaveCriticalSection(&_CriticalSection); 
+00573 
+00574 
+00575 #if NLSOUND_PROFILE
+00576         double dt = CTime::ticksToSecond(CTime::getPerformanceTime() - start);;
+00577         _TotalUpdateTime += dt;
+00578         _MaxUpdateTime = (dt > _MaxUpdateTime) ? dt : _MaxUpdateTime;
+00579         _MinUpdateTime = (dt < _MinUpdateTime) ? dt : _MinUpdateTime;
+00580         _UpdateCount++;
+00581 #endif
+00582 
+00583         return res;
+00584 }
+00585 
+00586 
+00587 
+00588 // ******************************************************************
+00589 
+00590 void CSourceDSound::setPos( const NLMISC::CVector& pos, bool deferred )
+00591 {
+00592         _Pos = pos;
+00593         // Coordinate system: conversion from NeL to OpenAL/GL:
+00594         if (_3DBuffer != NULL)
+00595         {
+00596                 if (_3DBuffer->SetPosition(pos.x, pos.z, pos.y, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
+00597                 {
+00598                         nlwarning ("SetPosition failed");
+00599                 }
+00600                 else
+00601                 {
+00602                         //nlwarning ("%p set source NEL(p:%.2f/%.2f/%.2f) DS(p:%.2f/%.2f/%.2f)", this, pos.x, pos.y, pos.z, pos.x, pos.z, pos.y);
+00603                 }
+00604         }
+00605 }
+00606 
+00607 
+00608 // ******************************************************************
+00609 
+00610 const NLMISC::CVector &CSourceDSound::getPos() const
+00611 {
+00612         return _Pos;
+00613         // Coordinate system: conversion from NeL to OpenAL/GL:
+00614 /*      if (_3DBuffer != NULL)
+00615         {
+00616                 D3DVECTOR v;
+00617                 HRESULT hr = _3DBuffer->GetPosition(&v);
+00618 
+00619                 if (hr != DS_OK)
+00620                 {
+00621                         nlwarning ("GetPosition failed");
+00622                         pos.set(0, 0, 0);       
+00623                 }
+00624                 else
+00625                 {
+00626                         pos.set(v.x, v.z, v.y);
+00627                 }
+00628         }
+00629         else
+00630         {
+00631                 pos.set(0, 0, 0);       
+00632         }
+00633 */
+00634 }
+00635 
+00636 
+00637 // ******************************************************************
+00638 
+00639 void CSourceDSound::setVelocity( const NLMISC::CVector& vel, bool deferred )
+00640 {
+00641         if (_3DBuffer != NULL)
+00642         {
+00643                 if (_3DBuffer->SetVelocity(vel.x, vel.z, vel.y, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
+00644                 {
+00645                         nlwarning ("SetVelocity failed");
+00646                 }
+00647         }
+00648 }
+00649 
+00650 
+00651 // ******************************************************************
+00652 
+00653 void CSourceDSound::getVelocity( NLMISC::CVector& vel ) const
+00654 {
+00655         if (_3DBuffer != NULL)
+00656         {
+00657                 D3DVECTOR v;
+00658 
+00659                 if (_3DBuffer->GetVelocity(&v) != DS_OK)
+00660                 {
+00661                         nlwarning ("GetVelocity failed");
+00662                         vel.set(0, 0, 0);       
+00663                 }
+00664                 else
+00665                 {
+00666                         vel.set(v.x, v.z, v.y);
+00667                 }
+00668         }
+00669         else
+00670         {
+00671                 vel.set(0, 0, 0);       
+00672         }
+00673 }
+00674 
+00675 
+00676 // ******************************************************************
+00677 
+00678 void CSourceDSound::setDirection( const NLMISC::CVector& dir )
+00679 {
+00680         if (_3DBuffer != 0)
+00681         {
+00682                 if (_3DBuffer->SetConeOrientation(dir.x, dir.z, dir.y, DS3D_DEFERRED) != DS_OK)
+00683                 {
+00684                         nlwarning ("SetConeOrientation failed (x=%.2f, y=%.2f, z=%.2f)", dir.x, dir.y, dir.z);
+00685                 }
+00686                 else
+00687                 {
+00688                         //nlwarning ("NLSOUND: %p set source direction NEL(p:%.2f/%.2f/%.2f) DS(p:%.2f/%.2f/%.2f)", this, dir.x, dir.y, dir.z, dir.x, dir.z, dir.y);
+00689                 }
+00690         }
+00691 }
+00692 
+00693 
+00694 // ******************************************************************
+00695 
+00696 void CSourceDSound::getDirection( NLMISC::CVector& dir ) const
+00697 {
+00698         if (_3DBuffer != NULL)
+00699         {
+00700                 D3DVECTOR v;
+00701 
+00702                 if (_3DBuffer->GetConeOrientation(&v) != DS_OK)
+00703                 {
+00704                         nlwarning("GetConeOrientation failed");
+00705                         dir.set(0, 0, 1);       
+00706                 }
+00707                 else
+00708                 {
+00709                         dir.set(v.x, v.z, v.y);
+00710                 }
+00711         }
+00712         else
+00713         {
+00714                 dir.set(0, 0, 1);       
+00715         }
+00716 }
+00717 
+00718 
+00719 // ******************************************************************
+00720 
+00721 void CSourceDSound::setGain( float gain )
+00722 {
+00723         clamp(gain, 0.00001f, 1.0f);
+00724         _Gain = gain;
+00725 
+00726         /* convert from linear amplitude to hundredths of decibels */
+00727         _Volume = (uint32)(100.0 * 20.0 * log10(gain));
+00728         clamp(_Volume, DSBVOLUME_MIN, DSBVOLUME_MAX);
+00729 
+00730         //nlwarning ("set gain %f vol %d", gain, _Volume);
+00731 
+00732         /*
+00733         if ((_SecondaryBuffer != 0) && (_SecondaryBuffer->SetVolume(_Volume) != DS_OK))
+00734         {
+00735                 nlwarning("SetVolume failed");
+00736         }
+00737         */
+00738 }
+00739 
+00740 
+00741 /*
+00742  * Get the gain
+00743  */
+00744 float CSourceDSound::getGain() const
+00745 {
+00746         return _Gain;
+00747 }
+00748 
+00749 
+00750 // ******************************************************************
+00751 
+00752 void CSourceDSound::setPitch( float coeff )
+00753 {
+00754 //      _Freq = coeff;
+00755 
+00756         if ((_Buffer != 0) && (_SecondaryBuffer != 0))
+00757         {
+00758                 TSampleFormat format;
+00759                 uint freq;
+00760 
+00761                 _Buffer->getFormat(format, freq);
+00762 
+00763                 _SampleRate = (uint32) (coeff * (float) freq);
+00764 
+00765                 //nlwarning("Freq=%d", newfreq);
+00766 
+00767                 if (_SecondaryBuffer->SetFrequency(_SampleRate) != DS_OK)
+00768                 {
+00769 //                      nlwarning("SetFrequency failed (buffer freq=%d, NeL freq=%.5f, DSound freq=%d)", freq, coeff, newfreq);
+00770                         nlwarning("SetFrequency");
+00771                 }
+00772         }
+00773 }
+00774 
+00775 
+00776 // ******************************************************************
+00777 
+00778 float CSourceDSound::getPitch() const
+00779 {
+00780         if ((_Buffer != 0) && (_SecondaryBuffer != 0))
+00781         {
+00782                 TSampleFormat format;
+00783                 uint freq0;
+00784                 DWORD freq;
+00785 
+00786                 _Buffer->getFormat(format, freq0);
+00787 
+00788                 if (_SecondaryBuffer->GetFrequency(&freq) != DS_OK)
+00789                 {
+00790                         nlwarning("GetFrequency failed");
+00791                         return 1.0;
+00792                 }
+00793 
+00794                 return ((float) freq / (float) freq0);
+00795         }
+00796 
+00797         return 1.0;
+00798 }
+00799 
+00800 
+00801 // ******************************************************************
+00802 
+00803 void CSourceDSound::setSourceRelativeMode( bool mode )
+00804 {
+00805         if (_3DBuffer != 0)
+00806         {
+00807                 HRESULT hr;
+00808 
+00809                 if (mode)
+00810                 {
+00811                         hr = _3DBuffer->SetMode(DS3DMODE_HEADRELATIVE, DS3D_IMMEDIATE);
+00812                 }
+00813                 else
+00814                 {
+00815                         hr = _3DBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE);
+00816                 }
+00817 
+00818                 if (hr != DS_OK)
+00819                 {
+00820                         nlwarning("SetMode failed");
+00821                 }
+00822         }
+00823         else
+00824         {
+00825                 nlwarning("Requested setSourceRelativeMode on a non-3D source");
+00826         }
+00827 }
+00828 
+00829 
+00830 // ******************************************************************
+00831 
+00832 bool CSourceDSound::getSourceRelativeMode() const
+00833 {
+00834         if (_3DBuffer != 0)
+00835         {
+00836                 DWORD mode;
+00837 
+00838                 if (_3DBuffer->GetMode(&mode) != DS_OK)
+00839                 {
+00840                         nlwarning("GetMode failed");
+00841                         return false;
+00842                 }
+00843 
+00844                 return (mode == DS3DMODE_HEADRELATIVE);
+00845         }
+00846         else
+00847         {
+00848                 nlwarning("Requested setSourceRelativeMode on a non-3D source");
+00849                 return false;
+00850         }
+00851 }
+00852 
+00853 
+00854 // ******************************************************************
+00855 
+00856 void CSourceDSound::setMinMaxDistances( float mindist, float maxdist, bool deferred )
+00857 {
+00858         if (_3DBuffer != 0)
+00859         {
+00860                 if (_3DBuffer->SetMinDistance(mindist, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
+00861                 {
+00862                         nlwarning("SetMinDistance (%f) failed", mindist);
+00863                 }
+00864                 if (_3DBuffer->SetMaxDistance(maxdist, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
+00865                 {
+00866                         nlwarning("SetMaxDistance (%f) failed", maxdist);
+00867                 }
+00868         }
+00869         else
+00870         {
+00871                 nlwarning("Requested setMinMaxDistances on a non-3D source");
+00872         }
+00873 }
+00874 
+00875 
+00876 // ******************************************************************
+00877 
+00878 void CSourceDSound::getMinMaxDistances( float& mindist, float& maxdist ) const
+00879 {
+00880         if (_3DBuffer != 0)
+00881         {
+00882                 D3DVALUE min, max;
+00883 
+00884                 if ((_3DBuffer->GetMinDistance(&min) != DS_OK)
+00885                         || (_3DBuffer->GetMaxDistance(&max) != DS_OK))
+00886                 {
+00887                         mindist = 0.0f;
+00888                         maxdist = 0.0f;
+00889                         nlwarning("GetMinDistance or GetMaxDistance failed");
+00890                 }
+00891                 else
+00892                 {
+00893                         mindist = min;
+00894                         maxdist = max;
+00895                 }
+00896         }
+00897         else
+00898         {
+00899                 mindist = 0.0f;
+00900                 maxdist = 0.0f;
+00901                 nlwarning("Requested getMinMaxDistances on a non-3D source");
+00902         }
+00903 }
+00904 
+00905 // ******************************************************************
+00906 
+00907 void CSourceDSound::updateVolume( const NLMISC::CVector& listener )
+00908 {
+00909         CVector pos = getPos();
+00910         pos -= listener;
+00911 
+00912         float sqrdist = pos.sqrnorm();
+00913         float min, max;
+00914 
+00915         getMinMaxDistances(min, max);
+00916 
+00917         if (sqrdist < min * min) 
+00918         {
+00919                 _SecondaryBuffer->SetVolume(_Volume);
+00920                 //nlwarning("VOLUME = %ddB, rolloff = %0.2f", _Volume/100, CListenerDSound::instance()->getRolloffFactor());
+00921         }
+00922         else if (sqrdist > max * max)
+00923         {
+00924                 _SecondaryBuffer->SetVolume(DSBVOLUME_MIN);
+00925                 //nlwarning("VOLUME = %ddB, rolloff = %0.2f", DSBVOLUME_MIN/100, CListenerDSound::instance()->getRolloffFactor());
+00926         }
+00927         else
+00928         {
+00929                 sint32 db = _Volume;
+00930 
+00931                 double dist = (double) sqrt(sqrdist);
+00932 
+00933                 // linearly descending volume on a dB scale
+00934                 double db1 = DSBVOLUME_MIN * (dist - min) / (max - min);
+00935 
+00936                 if (_Alpha == 0.0) {
+00937                         db += (sint32) db1;
+00938 
+00939                 } else if (_Alpha > 0.0) {
+00940                         double amp2 = 0.0001 + 0.9999 * (max - dist) / (max - min); // linear amp between 0.00001 and 1.0
+00941                         double db2 = 2000.0 * log10(amp2); // covert to 1/100th decibels
+00942                         db += (sint32) ((1.0 - _Alpha) * db1 + _Alpha * db2);
+00943 
+00944                 } else if (_Alpha < 0.0) {
+00945                         double amp3 = min / dist; // linear amplitude is 1/distance
+00946                         double db3 = 2000.0 * log10(amp3); // covert to 1/100th decibels
+00947                         db += (sint32) ((1.0 + _Alpha) * db1 - _Alpha * db3);
+00948                 }
+00949 
+00950                 clamp(db, DSBVOLUME_MIN, DSBVOLUME_MAX);
+00951 
+00952                 _SecondaryBuffer->SetVolume(db);
+00953 
+00954 /*              LONG tmp;
+00955                 _SecondaryBuffer->GetVolume(&tmp);
+00956 */
+00957                 
+00958                 //nlwarning("VOLUME = %d dB, rolloff = %0.2f", db/100, CListenerDSound::instance()->getRolloffFactor());
+00959         }
+00960 
+00961 }
+00962 
+00963 // ******************************************************************
+00964 
+00965 void CSourceDSound::setCone( float innerAngle, float outerAngle, float outerGain )
+00966 {
+00967         if (_3DBuffer != 0)
+00968         {
+00969                 // Set the cone angles
+00970 
+00971                 // Convert from radians to degrees
+00972                 DWORD inner = (DWORD)(180.0 * innerAngle / Pi);
+00973                 DWORD outer = (DWORD)(180.0 * outerAngle / Pi);
+00974 
+00975 
+00976                 // Sanity check: wrap the angles in the [0,360] interval
+00977                 if (outer < inner)
+00978                 {
+00979                         outer = inner;
+00980                 }
+00981 
+00982                 while (inner < DS3D_MINCONEANGLE) 
+00983                 {
+00984                         inner += 360;
+00985                 }
+00986 
+00987                 while (inner > DS3D_MAXCONEANGLE)
+00988                 {
+00989                         inner -= 360;
+00990                 }
+00991 
+00992                 while (outer < DS3D_MINCONEANGLE) 
+00993                 {
+00994                         outer += 360;
+00995                 }
+00996 
+00997                 while (outer > DS3D_MAXCONEANGLE)
+00998                 {
+00999                         outer -= 360;
+01000                 }
+01001 
+01002                 if (_3DBuffer->SetConeAngles(inner, outer, DS3D_DEFERRED) != DS_OK)
+01003                 {
+01004                         nlwarning("SetConeAngles failed");                      
+01005                 }
+01006 
+01007                 // Set the outside volume
+01008                 if (outerGain < 0.00001f)
+01009                 {
+01010                         outerGain = 0.00001f;
+01011                 }
+01012 
+01013                 // convert from linear amplitude to hundredths of decibels 
+01014                 LONG volume = (LONG)(100.0 * 20.0 * log10(outerGain));
+01015 
+01016                 if (volume < DSBVOLUME_MIN) 
+01017                 {
+01018                         volume = DSBVOLUME_MIN;
+01019                 }
+01020                 else if (volume > DSBVOLUME_MAX) 
+01021                 {
+01022                         volume = DSBVOLUME_MAX;
+01023                 }
+01024 
+01025                 if (_3DBuffer->SetConeOutsideVolume(volume, DS3D_DEFERRED) != DS_OK)
+01026                 {
+01027                         nlwarning("SetConeOutsideVolume failed");               
+01028                 }
+01029 
+01030         }
+01031         else
+01032         {
+01033                 nlwarning("Requested setCone on a non-3D source");
+01034         }
+01035 }
+01036 
+01037 // ******************************************************************
+01038 
+01039 void CSourceDSound::getCone( float& innerAngle, float& outerAngle, float& outerGain ) const
+01040 {
+01041         if (_3DBuffer != 0)
+01042         {
+01043                 DWORD inner, outer;
+01044                 LONG volume;
+01045 
+01046                 if (_3DBuffer->GetConeAngles(&inner, &outer) != DS_OK)
+01047                 {
+01048                         nlwarning("GetConeAngles failed");                      
+01049                         innerAngle = outerAngle = (float)(2.0 * Pi);
+01050                 }
+01051                 else
+01052                 {
+01053                         innerAngle = (float)(Pi * inner / 180.0);
+01054                         outerAngle = (float)(Pi * outer / 180.0);
+01055                 }
+01056 
+01057                 if (_3DBuffer->GetConeOutsideVolume(&volume) != DS_OK)
+01058                 {
+01059                         nlwarning("GetConeOutsideVolume failed");               
+01060                         outerGain = 0.0f;
+01061                 }
+01062                 else
+01063                 {
+01064                         outerGain = (float) pow(10, (double) volume / 20.0 / 100.0);
+01065                 }
+01066         }
+01067         else
+01068         {
+01069                 nlwarning("Requested getCone on a non-3D source");
+01070         }
+01071 }
+01072 
+01073 // ******************************************************************
+01074 
+01075 void CSourceDSound::setEAXProperty( uint prop, void *value, uint valuesize )
+01076 {
+01077 #ifdef EAX_AVAILABLE
+01078         if ( EAXSetProp != NULL )
+01079         {
+01080                 EAXSetProp( &DSPROPSETID_EAX_SourceProperties, prop, _SourceName, value, valuesize );
+01081         }
+01082 #endif
+01083 }
+01084 
+01085 
+01086 // ******************************************************************
+01087 
+01088 IBuffer *CSourceDSound::getBuffer()
+01089 {       
+01090         return _Buffer;
+01091 }
+01092 
+01093 
+01094 // ******************************************************************
+01095 
+01096 bool CSourceDSound::lock(uint32 writePos, uint32 size, uint8* &ptr1, DWORD &bytes1, uint8* &ptr2, DWORD &bytes2)
+01097 {
+01098         HRESULT hr = _SecondaryBuffer->Lock(writePos, size, (LPVOID*) &ptr1, &bytes1, (LPVOID*) &ptr2, &bytes2, 0);
+01099 
+01100         if (hr == DSERR_BUFFERLOST)
+01101         {
+01102                 // If the buffer got lost somehow, try to restore it.
+01103                 if (FAILED(_SecondaryBuffer->Restore()))
+01104                 {
+01105                         nlwarning("Lock failed (1)");
+01106                         return false;
+01107                 }
+01108                 if (FAILED(_SecondaryBuffer->Lock(_NextWritePos, _UpdateCopySize, (LPVOID*) &ptr1, &bytes1, (LPVOID*) &ptr2, &bytes2, 0)))
+01109                 {
+01110                         nlwarning("Lock failed (2)");
+01111                         return false;
+01112                 }
+01113         } 
+01114         else if (hr != DS_OK)
+01115         {
+01116                 nlwarning("Lock failed (3)");
+01117                 return false;
+01118         }
+01119 
+01120         return true;
+01121 }
+01122 
+01123 // ******************************************************************
+01124 
+01125 bool CSourceDSound::unlock(uint8* ptr1, DWORD bytes1, uint8* ptr2, DWORD bytes2)
+01126 {
+01127         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+01128         return true;
+01129 }
+01130 
+01131 
+01132 
+01133 /***************************************************************************
+01134  
+01135 
+01136   Buffer operations
+01137 
+01138   There are five buffer operation: fill, silence, fadeOut, crossFade
+01139   and fadeIn. fill and silence are called by the update function. The
+01140   others are called by the user state functions (play, stop, pause).
+01141 
+01142 
+01143                         NW         P   W
+01144    +--------+------+---+-----------------------+
+01145    |........|      |xxx|.......................|
+01146    +--------+------+---+-----------------------+
+01147 
+01148   The source maintains the next write position (_NextWritePos, NW in figure
+01149   above). That is the position at which new samples or silemce is written.
+01150   DirectSound maintaines a play cursor and a write cursor (P and W in figure).
+01151   The data between P and W is scheduled for playing and cannot be touched.
+01152   The data between W and NW are unplayed sample data that the source copied
+01153   into the DirectSound buffer.
+01154 
+01155   The update functions (fill, silence) refresh the buffer with new samples
+01156   or silence. That insert the sample data at the next write position NW. This 
+01157   write position is maintained as closely behind the DirectSound play cursor 
+01158   as possible to keep the buffer filled with data.
+01159 
+01160   The user functions (the fades) modify the sample data that is right after
+01161   the write cursor W maintained by DirectSound. The data has to be written 
+01162   after W to hear the changes as soon as possible. When a fade is done, the
+01163   date already written in the buffer has to be overwritten. The function
+01164   getFadeOutSize() helps to found out how many samples are writen between
+01165   W and NW and to what section of the original audio data they correspond.
+01166 
+01167   All the buffer functions below have the same pattern:
+01168 
+01169         - get current play and write cursors (P and W)
+01170         - lock the buffer
+01171         - copy samples
+01172         - unlock buffer
+01173         - update state variables
+01174 
+01175   The differences between the functions are due to different operation
+01176   (fades), position and size of the buffer to lock, handling of silence
+01177   and looping.
+01178 
+01179   Enjoy!
+01180 
+01181   PH
+01182 
+01183 
+01184 ************************************************************************/
+01185 
+01186 bool CSourceDSound::fill()
+01187 {
+01188         bool res = false;
+01189         uint8 *ptr1, *ptr2;
+01190         DWORD bytes1, bytes2;
+01191         DWORD playPos, writePos;
+01192         uint32 space;
+01193 
+01194 
+01195         if (_Buffer == NULL)
+01196         {
+01197                 _SecondaryBufferState = NL_DSOUND_SILENCING;
+01198                 _UserState = NL_DSOUND_STOPPED;
+01199                 return false;
+01200         }
+01201 
+01202         if (_SecondaryBuffer == 0)
+01203         {
+01204                 return false;
+01205         }
+01206 
+01207 
+01208         INITTIME(startPos);
+01209 
+01210 
+01211         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+01212 
+01213         if (playPos == _NextWritePos)
+01214         {
+01215                 return false;
+01216         }
+01217         else if (playPos > _NextWritePos) 
+01218         {
+01219                 space = playPos - _NextWritePos;
+01220         }
+01221         else
+01222         {
+01223                 space = _SecondaryBufferSize + playPos - _NextWritePos;
+01224         }
+01225 
+01226         // Don't bother if the number of samples that can be written is too small.
+01227         if (space < _UpdateCopySize)
+01228         {
+01229                 return false;
+01230         }
+01231 
+01232 
+01233         uint8* data = ((CBufferDSound*) _Buffer)->getData();
+01234         uint32 available = (_BytesWritten < _BufferSize) ? _BufferSize - _BytesWritten : 0;
+01235 
+01236 
+01237         // The number of samples bytes that will be copied. If bytes is 0
+01238         // than write silence to the buffer.
+01239         uint32 bytes = NLSOUND_MIN(_UpdateCopySize, available);
+01240         uint32 clear = _UpdateCopySize - available;
+01241 
+01242 
+01243         // Lock the buffer
+01244 
+01245         INITTIME(startLock);
+01246 
+01247 
+01248         if (!lock(_NextWritePos, _UpdateCopySize, ptr1, bytes1, ptr2, bytes2))
+01249         {
+01250                 return false;
+01251         }
+01252 
+01253 
+01254         INITTIME(startCopy);
+01255 
+01256         // Start copying the samples
+01257 
+01258         if (bytes1 <= bytes) {
+01259 
+01260                 CFastMem::memcpy(ptr1, data + _BytesWritten, bytes1);
+01261                 _BytesWritten += bytes1;
+01262                 bytes -= bytes1;
+01263 
+01264                 if (ptr2)
+01265                 {
+01266                         if (bytes > 0)
+01267                         {
+01268                                 CFastMem::memcpy(ptr2, data + _BytesWritten, bytes);                                    
+01269                                 _BytesWritten += bytes;
+01270                         }
+01271 
+01272                         if (bytes < bytes2)
+01273                         {
+01274                                 if (_Loop)
+01275                                 {
+01276                                         DBGPOS(("[%p] FILL: LOOP", this));
+01277 
+01278                                         CFastMem::memcpy(ptr2 + bytes, data, bytes2 - bytes); 
+01279                                         _BytesWritten = bytes2 - bytes;
+01280                                 }
+01281                                 else
+01282                                 {
+01283                                         memset(ptr2 + bytes, 0, bytes2 - bytes); 
+01284                                         _SilenceWritten = bytes2 - bytes;
+01285                                 }
+01286                         }
+01287                 }
+01288         }
+01289         else
+01290         {
+01291                 if (bytes > 0)
+01292                 {
+01293                         CFastMem::memcpy(ptr1, data + _BytesWritten, bytes);
+01294                         _BytesWritten += bytes;
+01295                 }
+01296 
+01297                 if (_Loop)
+01298                 {
+01299                         DBGPOS(("[%p] FILL: LOOP", this));
+01300 
+01301                         CFastMem::memcpy(ptr1 + bytes, data, bytes1 - bytes);                                    
+01302                         _BytesWritten = bytes1 - bytes;
+01303 
+01304                         if (ptr2)
+01305                         {
+01306                                 CFastMem::memcpy(ptr2, data + _BytesWritten, bytes2);                                    
+01307                                 _BytesWritten += bytes2;
+01308                         }
+01309 
+01310                 } 
+01311                 else
+01312                 {
+01313                         memset(ptr1 + bytes, 0, bytes1 - bytes);                                        
+01314                         _SilenceWritten = bytes1 - bytes;
+01315 
+01316                         if (ptr2)
+01317                         {
+01318                                 memset(ptr2, 0, bytes2);                                        
+01319                                 _SilenceWritten += bytes2;
+01320                         }
+01321                 }
+01322 
+01323         }
+01324 
+01325 
+01326 
+01327 
+01328         INITTIME(startUnlock);
+01329 
+01330         // Unlock the buffer
+01331         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+01332 
+01333 
+01334         // Update the state variables
+01335 
+01336         // Check if we've reached the end of the file
+01337         if (_BytesWritten == _BufferSize) 
+01338         {
+01339                 if (_Loop)
+01340                 {
+01341                         // If we're looping, start all over again
+01342                         DBGPOS(("[%p] FILL: LOOP", this));
+01343                         _BytesWritten = 0;
+01344                 }
+01345                 else
+01346                 {
+01347                         _SecondaryBufferState = NL_DSOUND_SILENCING;
+01348 
+01349                         // Keep track of where tha last sample was written and the position
+01350                         // of the play cursor relative to the end position. if the _EndState
+01351                         // is 0, the play cursor is after the end position, 1 otherwise.
+01352                         _EndPosition = writePos + bytes;
+01353                         if (_EndPosition >= _SecondaryBufferSize)
+01354                         {
+01355                                 _EndPosition -= _SecondaryBufferSize;
+01356                         }
+01357 
+01358                         _EndState = (playPos > _EndPosition)? NL_DSOUND_TAIL1 : NL_DSOUND_TAIL2;
+01359 
+01360                         DBGPOS(("[%p] FILL: SILENCING", this));
+01361                         DBGPOS(("[%p] FILL: ENDSTATE=%d, E=%d, P=%d", this, (int) _EndState, _EndPosition, playPos));
+01362                 }
+01363         }
+01364 
+01365 
+01366         // Update the write pointer
+01367         _NextWritePos += bytes1 + bytes2;
+01368         if (_NextWritePos >= _SecondaryBufferSize)
+01369         {
+01370                 _NextWritePos  -= _SecondaryBufferSize;
+01371         }
+01372  
+01373         DBGPOS(("[%p] FILL: P=%d, W=%d, NW=%d, SZ=%d, BW=%d, S=%d, B=%d", this, playPos, writePos, _NextWritePos, _BufferSize, _BytesWritten, _SilenceWritten, bytes1 + bytes2));
+01374 
+01375 
+01376 #if NLSOUND_PROFILE
+01377         _TotalUpdateSize += bytes1 + bytes2;
+01378         _PosTime += CTime::ticksToSecond(startLock - startPos);
+01379         _LockTime += CTime::ticksToSecond(startCopy - startLock);
+01380         _CopyTime += CTime::ticksToSecond(startUnlock - startCopy);
+01381         _UnlockTime += CTime::ticksToSecond(CTime::getPerformanceTime() - startUnlock);
+01382         _CopyCount++;
+01383 #endif
+01384 
+01385 
+01386         return true;
+01387 }
+01388 
+01389 
+01390 
+01391 
+01392 // ******************************************************************
+01393 
+01394 bool CSourceDSound::silence()
+01395 {
+01396         uint8 *ptr1, *ptr2;
+01397         DWORD bytes1, bytes2;
+01398         DWORD playPos, writePos;
+01399         uint32 space;
+01400 
+01401         if (_SecondaryBuffer == 0)
+01402         {
+01403                 return false;
+01404         }
+01405                 
+01406         INITTIME(startPos);
+01407 
+01408         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+01409 
+01410         if (playPos == _NextWritePos)
+01411         {
+01412                 return false;
+01413         }
+01414         else if (playPos > _NextWritePos) 
+01415         {
+01416                 space = playPos - _NextWritePos;
+01417         }
+01418         else
+01419         {
+01420                 space = _SecondaryBufferSize + playPos - _NextWritePos;
+01421         }
+01422 
+01423         // Don't bother if the number of samples that can be written is too small.
+01424         if (space < _UpdateCopySize)
+01425         {
+01426                 return false;
+01427         }
+01428 
+01429                 // Lock the buffer
+01430 
+01431         INITTIME(startLock);
+01432 
+01433         if (!lock(_NextWritePos, _UpdateCopySize, ptr1, bytes1, ptr2, bytes2))
+01434         {
+01435                 return false;
+01436         }
+01437 
+01438 
+01439         INITTIME(startCopy);
+01440    
+01441         // Silence the buffer
+01442         memset(ptr1, 0, bytes1);
+01443         memset(ptr2, 0, bytes2);
+01444 
+01445                 // Unlock the buffer
+01446 
+01447         INITTIME(startUnlock);
+01448 
+01449         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+01450 
+01451 
+01452         // Update the next write position
+01453         _NextWritePos += bytes1 + bytes2;
+01454         if (_NextWritePos >= _SecondaryBufferSize)
+01455         {
+01456                 _NextWritePos  -= _SecondaryBufferSize;
+01457         }
+01458 
+01459 
+01460         // Check if all the samples in the buffer are played
+01461         if ((playPos > _EndPosition) && (_EndState == NL_DSOUND_TAIL2)) 
+01462         {
+01463                 // The buffer played passed the last sample. Flag the source as stopped.
+01464                 _EndState = NL_DSOUND_ENDED;
+01465                 DBGPOS(("[%p] SLNC: ENDED", this));
+01466 
+01467                 // If the buffer was playing, mark it as stopped
+01468                 if (_UserState == NL_DSOUND_PLAYING)
+01469                 {
+01470                         _UserState = NL_DSOUND_STOPPED;
+01471                         DBGPOS(("[%p] SLNC: STOPPED", this));
+01472                 }
+01473         }
+01474         else if ((playPos < _EndPosition) && (_EndState == NL_DSOUND_TAIL1))
+01475         {
+01476                 // The play cursor wrapped around the buffer and is now before the end position
+01477                 _EndState = NL_DSOUND_TAIL2;
+01478                 DBGPOS(("[%p] FILL: ENDSTATE=%d, E=%d, P=%d", this, (int) _EndState, _EndPosition, playPos));
+01479         }
+01480 
+01481 
+01482         // Update the amount of silence written
+01483         _SilenceWritten += bytes1 + bytes2;
+01484         if (_SilenceWritten >= _SecondaryBufferSize)
+01485         {
+01486                 // The buffer is now completely filled with silence
+01487                 _SecondaryBufferState = NL_DSOUND_SILENCED;
+01488                 DBGPOS(("[%p] SLNC: SILENCED", this));
+01489 
+01490                 // If the buffer was playing, mark it as stopped
+01491                 if (_UserState == NL_DSOUND_PLAYING)
+01492                 {
+01493                         _UserState = NL_DSOUND_STOPPED;
+01494                         DBGPOS(("[%p] SLNC: STOPPED*", this));
+01495                 }
+01496         }
+01497 
+01498         DBGPOS(("[%p] SLNC: P=%d, W=%d, NW=%d, SZ=%d, BW=%d, S=%d, B=%d", this, playPos, writePos, _NextWritePos, _BufferSize, _BytesWritten, _SilenceWritten, bytes1 + bytes2));
+01499 
+01500 
+01501 #if NLSOUND_PROFILE
+01502         _TotalUpdateSize += bytes1 + bytes2;
+01503         _PosTime += CTime::ticksToSecond(startLock - startPos);
+01504         _LockTime += CTime::ticksToSecond(startCopy - startLock);
+01505         _CopyTime += CTime::ticksToSecond(startUnlock - startCopy);
+01506         _UnlockTime += CTime::ticksToSecond(CTime::getPerformanceTime() - startUnlock);
+01507         _CopyCount++;
+01508 #endif
+01509 
+01510         return true;
+01511 }
+01512 
+01513 
+01514 // ******************************************************************
+01515 
+01524  void CSourceDSound::getFadeOutSize(uint32 writePos, uint32 &xfadeSize, sint16* &in1, uint32 &writtenTooMuch)
+01525 {
+01526         // The number of samples over which we will do the crossfade
+01527         xfadeSize = _XFadeSize;
+01528 
+01529 
+01530         // The tricky part of this method is to figger out how many samples of the old
+01531         // buffer were written after the write cursor and figger our with what position 
+01532         // in the old buffer the write cursor corresponds. We have to consider the following
+01533         // cases:
+01534         //
+01535         // - the old buffer just looped, 
+01536         // - the old buffer is finished, but stil has samples in the DirectSound buffer
+01537         // - the default case, i.e. the old buffer is playing somewhere in the middle.
+01538         //
+01539 
+01540         // How many bytes did we write after the write position?
+01541 
+01542         writtenTooMuch = NLSOUND_DISTANCE(writePos, _NextWritePos, _SecondaryBufferSize);
+01543 
+01544         DBGPOS(("[%p] FADE: TOO=%d", this, writtenTooMuch));
+01545 
+01546 
+01547         uint8* data = ((CBufferDSound*) _Buffer)->getData();
+01548 
+01549         // If the sound is finished and all the samples are written in the
+01550         // buffer, it's possible that there are still samples after the write
+01551         // position. If this is the case, we have to do a fade out. If there is
+01552         // only silence, we only need to copy without fade.
+01553 
+01554         if (_SilenceWritten > 0)
+01555         {
+01556                 
+01557                 if (writtenTooMuch > _SilenceWritten)
+01558                 {
+01559                         writtenTooMuch -= _SilenceWritten;
+01560                         in1 = (sint16*) (data + _BufferSize - writtenTooMuch) ;
+01561 
+01562                         if (writtenTooMuch < 2 * xfadeSize)
+01563                         {
+01564                                 xfadeSize = writtenTooMuch / 2;
+01565                         }
+01566                 }
+01567                 else
+01568                 {
+01569                         xfadeSize = 0;                                                    
+01570                 }
+01571 
+01572                 DBGPOS(("[%p] FADE: END, TOO=%d, S=%d, F=%d", this, writtenTooMuch, _SilenceWritten, xfadeSize));
+01573         }
+01574         
+01575         // If the sound looped, it's possible that the number of samples
+01576         // written is small. In that case, the write cursor is still inside
+01577         // the previous loop. All we have to do is fade out the last part
+01578         // of the previous loop. 
+01579 
+01580         else if (writtenTooMuch >= _BytesWritten)
+01581         {
+01582 
+01583                 writtenTooMuch -= _BytesWritten;
+01584 
+01585                 in1 = (sint16*) (data + _BufferSize - writtenTooMuch) ;
+01586 
+01587                 if (writtenTooMuch < 2 * xfadeSize)
+01588                 {
+01589                         xfadeSize = writtenTooMuch / 2;
+01590                 }
+01591 
+01592                 DBGPOS(("[%p] FADE: LOOPED, TOO=%d, F=%d", this, writtenTooMuch, xfadeSize));
+01593 
+01594         }
+01595 
+01596         // This is the default case. Simply fade from the previous to the next buffer.
+01597         // The variable writtenTooMuch tells us how much of the previous sound has
+01598         // been written after the current write cursor. We just have to check there
+01599         // are enough samples available for the fade.
+01600 
+01601         else
+01602         {
+01603                 in1 = (sint16*) (data + (sint32) _BytesWritten - writtenTooMuch);
+01604 
+01605                 if (xfadeSize > _BufferSize - _BytesWritten)
+01606                 {
+01607                         xfadeSize = _BufferSize - _BytesWritten;
+01608                 }
+01609 
+01610                 DBGPOS(("[%p] FADE: STD, TOO=%d, F=%d", this, writtenTooMuch, xfadeSize));
+01611         }
+01612 }
+01613 
+01614 
+01615 
+01616 // ******************************************************************
+01617 
+01618 void CSourceDSound::crossFade()
+01619 {
+01620         uint8 *ptr1, *ptr2;
+01621         DWORD bytes1, bytes2;
+01622         DWORD playPos, writePos;
+01623         uint32 i;
+01624 
+01625 
+01626 
+01627         if (_Buffer == NULL)
+01628         {
+01629                 return;
+01630         }
+01631 
+01632         if (_SecondaryBuffer == 0)
+01633         {
+01634                 return;
+01635         }
+01636 
+01637 
+01638         INITTIME(start); 
+01639         
+01640 
+01641         EnterCriticalSection(&_CriticalSection); 
+01642 
+01643 
+01644 
+01645         // The source is currently playing an other buffer. We will do a hot
+01646         // swap between the old and the new buffer. DirectSound maintains two
+01647         // cursors into the buffer: the play cursor and the write cursor.
+01648         // The write cursor indicates where we can start writing the new samples.
+01649         // To avoid clicks, we have to do a cross fade between the old buffer and
+01650         // the new buffer.
+01651         
+01652         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+01653 
+01654 
+01655         // The number of bytes we will write to the DirectSound buffer
+01656         uint32 bytes = _SwapCopySize;
+01657         if (bytes > _SwapBuffer->getSize())
+01658         {
+01659                 bytes = _SwapBuffer->getSize();
+01660         }
+01661 
+01662 
+01663         // Lock the DirectSound buffer
+01664 
+01665         if (FAILED(_SecondaryBuffer->Lock(writePos, bytes, (LPVOID*) &ptr1, &bytes1, (LPVOID*) &ptr2, &bytes2, 0)))
+01666         {
+01667                 LeaveCriticalSection(&_CriticalSection);
+01668                 throw ESoundDriver("Failed to lock the DirectSound secondary buffer");
+01669         }
+01670 
+01671         
+01672         sint16* in1;
+01673         uint8* data1 = ((CBufferDSound*) _Buffer)->getData();
+01674         uint8* data2 = ((CBufferDSound*) _SwapBuffer)->getData();
+01675         sint16* in2 = (sint16*) data2;
+01676         sint16* out = (sint16*) ptr1;
+01677 
+01678         // The number of samples over which we will do the crossfade
+01679         uint32 xfadeSize;
+01680         uint32 xfadeByteSize;
+01681         uint32 writtenTooMuch;
+01682 
+01683         getFadeOutSize(writePos, xfadeSize, in1, writtenTooMuch);
+01684         xfadeByteSize = 2 * xfadeSize;
+01685 
+01686 #define MIX 1
+01687 
+01688 
+01689 #if MIX
+01690         float incr, amp1, amp2;
+01691 
+01692         if (xfadeSize == 0)
+01693         {
+01694                 amp1 = 0.0f;
+01695                 amp2 = 1.0f;
+01696                 incr = 0.0f;
+01697         }
+01698         else
+01699         {
+01700                 amp1 = 1.0f;
+01701                 amp2 = 0.0f;
+01702                 incr = 1.0f / xfadeSize;
+01703         }
+01704 
+01705 #else
+01706         float incr, amp1;
+01707 
+01708         if (xfadeSize == 0)
+01709         {
+01710                 amp1 = 0.0f;
+01711                 incr = 0.0f;
+01712         }
+01713         else
+01714         {
+01715                 amp1 = 1.0f;
+01716                 incr = 1.0f / xfadeSize;
+01717         }
+01718 
+01719 #endif
+01720 
+01721 
+01722         // Start copying the samples
+01723         
+01724 
+01725         // In the first case, the cross fade is completely contained in the first buffer
+01726         // pointed to by ptr1.
+01727         if (xfadeByteSize < bytes1)
+01728         {
+01729 
+01730                 // Do cross fade
+01731 
+01732                 for (i = 0; i < xfadeSize; i++) 
+01733                 {
+01734 #if MIX
+01735                         out[i] = (sint16) (amp1 * in1[i] + amp2 * in2[i]);
+01736                         amp1 -= incr;
+01737                         amp2 += incr;
+01738 #else
+01739                         out[i] = (sint16) (amp1 * in1[i]);
+01740                         amp1 -= incr;
+01741 #endif
+01742                 }
+01743 
+01744                 // Copy remaining samples
+01745 
+01746 #if MIX
+01747                 CFastMem::memcpy(ptr1 + xfadeByteSize, data2 + xfadeByteSize, bytes1 - xfadeByteSize);
+01748                 _BytesWritten = bytes1;
+01749 #else
+01750                 CFastMem::memcpy(ptr1 + xfadeByteSize, data2, bytes1 - xfadeByteSize);
+01751                 _BytesWritten = bytes1 - xfadeByteSize;
+01752 #endif
+01753 
+01754                 if (ptr2)
+01755                 {
+01756                         CFastMem::memcpy(ptr2, data2 + _BytesWritten, bytes2);
+01757                         _BytesWritten += bytes2;
+01758                 }
+01759 
+01760         }
+01761 
+01762         // In the second case, the cross fade stretches over the first and the second buffers.
+01763         else
+01764         {
+01765 
+01766                 uint32 fade1 = bytes1 / 2;
+01767                 uint32 fade2 = xfadeSize - fade1;
+01768 
+01769                 // Do cross fade
+01770 
+01771                 // Part 1, start at ptr1
+01772                 for (i = 0; i < fade1; i++) 
+01773                 {
+01774 #if MIX
+01775                         out[i] = (sint16) (amp1 * in1[i] + amp2 * in2[i]);
+01776                         amp1 -= incr;
+01777                         amp2 += incr;
+01778 #else
+01779                         out[i] = (sint16) (amp1 * in1[i]);
+01780                         amp1 -= incr;
+01781 #endif
+01782                 }
+01783 #if MIX
+01784                 _BytesWritten = bytes1;
+01785 #else
+01786                 _BytesWritten = 0;
+01787 #endif
+01788 
+01789 
+01790                 if (ptr2)
+01791                 {
+01792                         out = (sint16*) ptr2;
+01793 
+01794                         // Part 2, ontinue at ptr2
+01795                         for (uint32 k = 0; i < xfadeSize; i++, k++) 
+01796                         {
+01797 #if MIX
+01798                                 out[k] = (sint16) (amp1 * in1[i] + amp2 * in2[i]);
+01799                                 amp1 -= incr;
+01800                                 amp2 += incr;
+01801 #else
+01802                                 out[k] = (sint16) (amp1 * in1[i]);
+01803                                 amp1 -= incr;
+01804 #endif
+01805                         }
+01806 
+01807                         // Copy remaining samples
+01808 #if MIX
+01809                         CFastMem::memcpy(ptr2 + 2 * k, data2 + _BytesWritten + 2 * k, bytes2 - 2 * k);
+01810                         _BytesWritten += bytes2;
+01811 #else
+01812                         CFastMem::memcpy(ptr2 + 2 * k, data2, bytes2 - 2 * k);
+01813                         _BytesWritten = bytes2 - 2 * k;
+01814 #endif
+01815                 }
+01816         }
+01817 
+01818 
+01819         // Unlock the DirectSound buffer
+01820         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+01821 
+01822         
+01823         // Update the state variables
+01824 
+01825         _SilenceWritten = 0;
+01826 
+01827         _NextWritePos = (writePos + bytes1 + bytes2);
+01828         if (_NextWritePos >= _SecondaryBufferSize)
+01829         {
+01830                 _NextWritePos -= _SecondaryBufferSize;
+01831         }
+01832 
+01833 
+01834 
+01835         _SecondaryBufferState = NL_DSOUND_FILLING;
+01836 
+01837 
+01838         // Swap the two buffers
+01839         _BufferSize = _SwapBuffer->getSize();
+01840         _Buffer = _SwapBuffer;
+01841         _SwapBuffer = 0;
+01842 
+01843         setPitch(_Freq);
+01844 
+01845         // Check if we've reached the end of the file
+01846         if (_BytesWritten == _BufferSize) 
+01847         {
+01848                 if (_Loop)
+01849                 {
+01850                         _BytesWritten = 0;
+01851                 }
+01852                 else
+01853                 {
+01854                         _SecondaryBufferState = NL_DSOUND_SILENCING;
+01855                 }
+01856         }
+01857 
+01858 
+01859         DBGPOS(("[%p] XFADE", this));
+01860         DBGPOS(("[%p] P=%d, W=%d, NW=%d, SZ=%d, BW=%d, B=%d", this, playPos, writePos, _NextWritePos, _BufferSize, _BytesWritten, bytes1 + bytes2));
+01861 
+01862         
+01863 
+01864         LeaveCriticalSection(&_CriticalSection);
+01865 
+01866 
+01867 #if NLSOUND_PROFILE
+01868         _LastSwapTime = CTime::ticksToSecond(CTime::getPerformanceTime() - start);
+01869         _TotalSwapTime += _LastSwapTime;
+01870         _MaxSwapTime = (_LastSwapTime > _MaxSwapTime) ? _LastSwapTime : _MaxSwapTime;
+01871         _MinSwapTime = (_LastSwapTime < _MinSwapTime) ? _LastSwapTime : _MinSwapTime;
+01872         _SwapCount++;
+01873 #endif
+01874 
+01875 }
+01876 
+01877 
+01878 
+01879 // ******************************************************************
+01880 
+01881 void CSourceDSound::fadeOut()
+01882 {
+01883         uint8 *ptr1, *ptr2;
+01884         DWORD bytes1, bytes2;
+01885         DWORD playPos, writePos;
+01886         uint32 i;
+01887 
+01888 
+01889         if (_Buffer == NULL)
+01890         {
+01891                 _SecondaryBufferState = NL_DSOUND_SILENCING;
+01892                 _UserState = NL_DSOUND_STOPPED;
+01893                 return;
+01894         }
+01895 
+01896         if (_SecondaryBuffer == 0)
+01897         {
+01898                 return;
+01899         }
+01900 
+01901         INITTIME(start);
+01902         
+01903 
+01904         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+01905 
+01906 
+01907         // Lock the DirectSound buffer
+01908 
+01909         if (FAILED(_SecondaryBuffer->Lock(writePos, _SwapCopySize, (LPVOID*) &ptr1, &bytes1, (LPVOID*) &ptr2, &bytes2, 0)))
+01910         {
+01911                 throw ESoundDriver("Failed to lock the DirectSound secondary buffer");
+01912         }
+01913 
+01914         
+01915 
+01916         // in1 points to the position in the old buffer where the fade out starts
+01917         sint16* in1;
+01918         sint16* out = (sint16*) ptr1;
+01919 
+01920         // The number of samples over which we will do the crossfade
+01921         uint32 xfadeSize;
+01922         uint32 xfadeByteSize;
+01923         uint32 writtenTooMuch;
+01924 
+01925         getFadeOutSize(writePos, xfadeSize, in1, writtenTooMuch);
+01926         xfadeByteSize = 2 * xfadeSize;
+01927 
+01928         float amp1, incr;
+01929 
+01930         if (xfadeSize == 0)
+01931         {
+01932                 amp1 = 0.0f;
+01933                 incr = 0.0f;
+01934         }
+01935         else
+01936         {
+01937                 amp1 = 1.0f;
+01938                 incr = 1.0f / xfadeSize;
+01939         }
+01940 
+01941 
+01942         if (writtenTooMuch > _BytesWritten)
+01943         {
+01944                 // The buffer looped. Count backwards from the end of the file.
+01945                 _BytesWritten = _BufferSize - writtenTooMuch;
+01946         }
+01947         else
+01948         {
+01949                 _BytesWritten -= writtenTooMuch;
+01950         }
+01951 
+01952 
+01953         // Start copying the samples
+01954         
+01955 
+01956         // In the first case, the fade out is completely contained in the first buffer
+01957         // pointed to by ptr1.
+01958         if (xfadeByteSize < bytes1)
+01959         {
+01960 
+01961                 // Do cross fade
+01962 
+01963                 for (i = 0; i < xfadeSize; i++) 
+01964                 {
+01965                         out[i] = (sint16) (amp1 * in1[i]);
+01966                         amp1 -= incr;
+01967                 }
+01968 
+01969                 // Copy remaining samples
+01970 
+01971                 memset(ptr1 + xfadeByteSize, 0, bytes1 - xfadeByteSize);
+01972                 _SilenceWritten = bytes1 - xfadeByteSize;
+01973 
+01974                 if (ptr2)
+01975                 {
+01976                         memset(ptr2, 0, bytes2);
+01977                         _SilenceWritten += bytes2;
+01978                 }
+01979 
+01980         }
+01981 
+01982         // In the second case, the fade out stretches over the first and the second buffers.
+01983         else
+01984         {
+01985 
+01986                 uint32 fade1 = bytes1 / 2;
+01987                 uint32 fade2 = xfadeSize - fade1;
+01988 
+01989                 // Do cross fade
+01990 
+01991                 // Part 1, start at ptr1
+01992                 for (i = 0; i < fade1; i++) 
+01993                 {
+01994                         out[i] = (sint16) (amp1 * in1[i]);
+01995                         amp1 -= incr;
+01996                 }
+01997 
+01998 
+01999                 if (ptr2)
+02000                 {
+02001                         out = (sint16*) ptr2;
+02002 
+02003                         // Part 2, continue at ptr2
+02004                         for (uint32 k = 0; i < xfadeSize; i++, k++) 
+02005                         {
+02006                                 out[k] = (sint16) (amp1 * in1[i]);
+02007                                 amp1 -= incr;
+02008                         }
+02009 
+02010                         // Clear remaining samples
+02011                         memset(ptr2 + 2 * k, 0, bytes2 - 2 * k);
+02012                         _SilenceWritten = bytes2 - 2 * k;
+02013                 }
+02014 
+02015         }
+02016 
+02017 
+02018         _BytesWritten += xfadeByteSize;
+02019 
+02020 
+02021         // Unlock the DirectSound buffer
+02022         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+02023 
+02024         
+02025         // Update the next write position
+02026         _NextWritePos = (writePos + bytes1 + bytes2);
+02027         if (_NextWritePos >= _SecondaryBufferSize)
+02028         {
+02029                 _NextWritePos -= _SecondaryBufferSize;
+02030         }
+02031 
+02032 
+02033         _SecondaryBufferState = NL_DSOUND_SILENCING;
+02034         DBGPOS(("[%p] FDOU: SILENCING", this));
+02035 
+02036         // Keep track of where tha last sample was written and the position
+02037         // of the play cursor relative to the end position. if the _EndState
+02038         // is 0, the play cursor is after the end position, 1 otherwise.
+02039         _EndPosition = writePos + xfadeSize;
+02040         if (_EndPosition >= _SecondaryBufferSize)
+02041         {
+02042                 _EndPosition -= _SecondaryBufferSize;
+02043         }
+02044 
+02045         _EndState = (playPos > _EndPosition)? NL_DSOUND_TAIL1 : NL_DSOUND_TAIL2;
+02046         DBGPOS(("[%p] FDOU: ENDSTATE=%d, E=%d, P=%d", this, (int) _EndState, _EndPosition, playPos));
+02047 
+02048 
+02049         DBGPOS(("[%p] FDOU: P=%d, W=%d, NW=%d, SZ=%d, BW=%d, S=%d, B=%d", this, playPos, writePos, _NextWritePos, _BufferSize, _BytesWritten, _SilenceWritten, bytes1 + bytes2));
+02050 
+02051 
+02052 
+02053 #if NLSOUND_PROFILE
+02054         _LastSwapTime = CTime::ticksToSecond(CTime::getPerformanceTime() - start);
+02055         _TotalSwapTime += _LastSwapTime;
+02056         _MaxSwapTime = (_LastSwapTime > _MaxSwapTime) ? _LastSwapTime : _MaxSwapTime;
+02057         _MinSwapTime = (_LastSwapTime < _MinSwapTime) ? _LastSwapTime : _MinSwapTime;
+02058         _SwapCount++;
+02059 #endif
+02060 
+02061 }
+02062 
+02063 // ******************************************************************
+02064 
+02065 void CSourceDSound::fadeIn()
+02066 {
+02067         bool res = false;
+02068         uint8 *ptr1, *ptr2;
+02069         DWORD bytes1, bytes2;
+02070         DWORD playPos, writePos;
+02071 
+02072 
+02073         if (_Buffer == NULL)
+02074         {
+02075                 _SecondaryBufferState = NL_DSOUND_SILENCING;
+02076                 _UserState = NL_DSOUND_STOPPED;
+02077                 return;
+02078         }
+02079 
+02080         if (_SecondaryBuffer == 0)
+02081         {
+02082                 return;
+02083         }
+02084 
+02085         INITTIME(startPos);
+02086 
+02087         // Set the correct pitch for this sound
+02088         setPitch(_Freq);
+02089 
+02090         // Set the correct volume
+02091         // FIXME: a bit of a hack
+02092         const CVector &pos = CListenerDSound::instance()->getPos();
+02093         updateVolume(pos);
+02094 
+02095 
+02096         _SecondaryBuffer->GetCurrentPosition(&playPos, &writePos);
+02097 
+02098         uint8* data = ((CBufferDSound*) _Buffer)->getData();
+02099         uint32 available = (_BytesWritten < _BufferSize) ? _BufferSize - _BytesWritten : 0;
+02100         uint32 bytes = NLSOUND_MIN(_SwapCopySize, available);
+02101 //      uint32 clear = _SwapCopySize - available;
+02102 
+02103 
+02104         _SilenceWritten = 0;
+02105 
+02106         // Lock the buffer
+02107 
+02108         INITTIME(startLock);
+02109 
+02110 
+02111         if (!lock(writePos, _SwapCopySize, ptr1, bytes1, ptr2, bytes2))
+02112         {
+02113                 return;
+02114         }
+02115 
+02116 
+02117         INITTIME(startCopy);
+02118 
+02119         // Start copying the samples
+02120 
+02121         if (bytes1 <= bytes) {
+02122 
+02123                 CFastMem::memcpy(ptr1, data + _BytesWritten, bytes1);
+02124                 _BytesWritten += bytes1;
+02125                 bytes -= bytes1;
+02126 
+02127                 if (ptr2)
+02128                 {
+02129                         if (bytes > 0)
+02130                         {
+02131                                 CFastMem::memcpy(ptr2, data + _BytesWritten, bytes);                                    
+02132                                 _BytesWritten += bytes;
+02133                         }
+02134 
+02135                         if (bytes < bytes2)
+02136                         {
+02137                                 if (_Loop)
+02138                                 {
+02139                                         DBGPOS(("[%p] FDIN: LOOP", this));
+02140 
+02141                                         CFastMem::memcpy(ptr2 + bytes, data, bytes2 - bytes); 
+02142                                         _BytesWritten = bytes2 - bytes;
+02143                                 }
+02144                                 else
+02145                                 {
+02146                                         memset(ptr2 + bytes, 0, bytes2 - bytes); 
+02147                                         _SilenceWritten = bytes2 - bytes;
+02148                                 }
+02149                         }
+02150                 }
+02151         }
+02152         else
+02153         {
+02154                 if (bytes > 0)
+02155                 {
+02156                         CFastMem::memcpy(ptr1, data + _BytesWritten, bytes);
+02157                         _BytesWritten += bytes;
+02158                 }
+02159 
+02160                 if (_Loop)
+02161                 {
+02162                         DBGPOS(("[%p] FDIN: LOOP", this));
+02163 
+02164                         CFastMem::memcpy(ptr1 + bytes, data, bytes1 - bytes);                                    
+02165                         _BytesWritten = bytes1 - bytes;
+02166 
+02167                         if (ptr2)
+02168                         {
+02169                                 CFastMem::memcpy(ptr2, data + _BytesWritten, bytes2);                                    
+02170                                 _BytesWritten += bytes2;
+02171                         }
+02172                 } 
+02173                 else
+02174                 {
+02175                         memset(ptr1 + bytes, 0, bytes1 - bytes);                                        
+02176                         _SilenceWritten = bytes1 - bytes;
+02177 
+02178                         if (ptr2)
+02179                         {
+02180                                 memset(ptr2, 0, bytes2);                                        
+02181                                 _SilenceWritten += bytes2;
+02182                         }
+02183                 }
+02184         }
+02185 
+02186 
+02187         INITTIME(startUnlock);
+02188 
+02189         // Unlock the buffer
+02190         _SecondaryBuffer->Unlock(ptr1, bytes1, ptr2, bytes2);
+02191 
+02192 
+02193         // Update the state variables
+02194 
+02195         _SecondaryBufferState = NL_DSOUND_FILLING;
+02196         DBGPOS(("[%p] FDIN: FILLING", this));
+02197 
+02198 
+02199         // Check if we've reached the end of the file
+02200         if (_BytesWritten == _BufferSize) 
+02201         {
+02202                 if (_Loop)
+02203                 {
+02204                         // If we're looping, start all over again
+02205                         DBGPOS(("[%p] FDIN: LOOP", this));
+02206                         _BytesWritten = 0;
+02207                 }
+02208                 else
+02209                 {
+02210                         _SecondaryBufferState = NL_DSOUND_SILENCING;
+02211 
+02212                         // Keep track of where tha last sample was written and the position
+02213                         // of the play cursor relative to the end position. if the _EndState
+02214                         // is NL_DSOUND_TAIL1, the play cursor is after the end position, 
+02215                         // NL_DSOUND_TAIL2 otherwise.
+02216                         _EndPosition = writePos + bytes;
+02217                         if (_EndPosition >= _SecondaryBufferSize)
+02218                         {
+02219                                 _EndPosition -= _SecondaryBufferSize;
+02220                         }
+02221 
+02222                         _EndState = (playPos > _EndPosition)? NL_DSOUND_TAIL1 : NL_DSOUND_TAIL2;
+02223 
+02224                         DBGPOS(("[%p] FDIN: SILENCING", this));
+02225                         DBGPOS(("[%p] FDIN: ENDSTATE=%d, E=%d, P=%d", this, (int) _EndState, _EndPosition, playPos));
+02226                 }
+02227         }
+02228 
+02229 
+02230         // Update the write pointer
+02231         _NextWritePos = writePos + bytes1 + bytes2;
+02232         if (_NextWritePos >= _SecondaryBufferSize)
+02233         {
+02234                 _NextWritePos  -= _SecondaryBufferSize;
+02235         }
+02236  
+02237         DBGPOS(("[%p] FDIN: P=%d, W=%d, NW=%d, SZ=%d, BW=%d, S=%d, B=%d", this, playPos, writePos, _NextWritePos, _BufferSize, _BytesWritten, _SilenceWritten, bytes1 + bytes2));
+02238 
+02239 
+02240 #if NLSOUND_PROFILE
+02241         _TotalUpdateSize += bytes1 + bytes2;
+02242         _PosTime += CTime::ticksToSecond(startLock - startPos);
+02243         _LockTime += CTime::ticksToSecond(startCopy - startLock);
+02244         _CopyTime += CTime::ticksToSecond(startUnlock - startCopy);
+02245         _UnlockTime += CTime::ticksToSecond(CTime::getPerformanceTime() - startUnlock);
+02246         _CopyCount++;
+02247 #endif
+02248 
+02249 
+02250 }
+02251 
+02252 
+02253 
+02254 } // NLSOUND
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1