00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stddsound.h"
00026 #include "nel/misc/hierarchical_timer.h"
00027 #include "source_dsound.h"
00028 #include "sound_driver_dsound.h"
00029 #include "buffer_dsound.h"
00030 #include "listener_dsound.h"
00031 #include "../sound_driver.h"
00032
00033 #include <algorithm>
00034
00035
00036 using namespace NLMISC;
00037 using namespace std;
00038
00039
00040 namespace NLSOUND {
00041
00042
00043 #if NLSOUND_PROFILE
00044
00045 #define INITTIME(_var) TTicks _var = CTime::getPerformanceTime()
00046
00047 #define DEBUG_POSITIONS 1
00048
00049 #if DEBUG_POSITIONS
00050 #define DBGPOS(_a) nldebug ## _a
00051 #else
00052 #define DBGPOS(_a)
00053 #endif
00054
00055 #else
00056 #define INITTIME(_var)
00057 #define DBGPOS(_a)
00058 #endif
00059
00060
00061
00062 const uint32 CSourceDSound::_SecondaryBufferSize = 0x10000;
00063 const uint32 CSourceDSound::_SizeMask = 0xffff;
00064 const uint32 CSourceDSound::_SwapCopySize = 0x8000;
00065 const uint32 CSourceDSound::_UpdateCopySize = 0x4000;
00066 const uint32 CSourceDSound::_XFadeSize = 64;
00067 const uint CSourceDSound::_DefaultChannels = 1;
00068 const uint CSourceDSound::_DefaultSampleRate = 22050;
00069 const uint CSourceDSound::_DefaultSampleSize = 16;
00070
00071
00072
00073 #define NLSOUND_MIN(_a,_b) (((_a) < (_b)) ? (_a) : (_b))
00074 #define NLSOUND_DISTANCE(_from, _to, _period) (((_to) > (_from)) ? (_to) - (_from) : (_period) + (_to) - (_from))
00075
00076
00077 #if NLSOUND_PROFILE
00078
00079
00080 double CSourceDSound::_LastSwapTime = 0.0;
00081 double CSourceDSound::_TotalSwapTime = 0.0;
00082 double CSourceDSound::_MaxSwapTime = 0.0;
00083 double CSourceDSound::_MinSwapTime = 1000000.0;
00084 uint32 CSourceDSound::_SwapCount = 0;
00085 double CSourceDSound::_PosTime = 0.0;
00086 double CSourceDSound::_LockTime = 0.0;
00087 double CSourceDSound::_CopyTime = 0.0;
00088 double CSourceDSound::_UnlockTime = 0.0;
00089 uint32 CSourceDSound::_CopyCount = 0;
00090 double CSourceDSound::_TotalUpdateTime = 0.0;
00091 double CSourceDSound::_MaxUpdateTime = 0.0;
00092 double CSourceDSound::_MinUpdateTime = 1000000.0;
00093 uint32 CSourceDSound::_UpdateCount = 0;
00094 uint32 CSourceDSound::_TotalUpdateSize = 0;
00095 #endif
00096
00097
00098 uint32 getWritePosAndSpace(uint32 &nextWritePos, uint32 playPos, uint32 writePos, uint32 bufferSize);
00099
00100
00101
00102
00103 CSourceDSound::CSourceDSound( uint sourcename )
00104 : ISource(),
00105 _SourceName(sourcename)
00106 {
00107 #if EAX_AVAILABLE == 1
00108 _EAXSource = 0;
00109 #endif
00110 _Sample = 0;
00111 _SampleSize = 0;
00112 _SampleOffset = 0;
00113 _Format = Mono8;
00114 _SampleFreq = _DefaultSampleRate;
00115 _FillOffset = 0;
00116 _State = source_stoped;
00117 _PlayOffset = 0;
00118 _LastPlayPos = 0;
00119 _PosRelative= false;
00120
00121
00122
00123 _SecondaryBuffer = 0;
00124
00125 _3DBuffer = 0;
00126
00127
00128
00129 _Loop = false;
00130
00131
00132
00133 _Freq = 1.0f;
00134 _SampleRate = _DefaultSampleRate;
00135
00136 _Gain = 1.0f;
00137 _Volume = 0;
00138 _Alpha = 0.0;
00139 InitializeCriticalSection(&_CriticalSection);
00140 }
00141
00142
00143
00144
00145 CSourceDSound::~CSourceDSound()
00146 {
00147 nldebug("Destroying DirectSound source");
00148
00149 CSoundDriverDSound::instance()->removeSource(this);
00150
00151 EnterCriticalSection(&_CriticalSection);
00152
00153
00154
00155 release();
00156
00157 LeaveCriticalSection(&_CriticalSection);
00158 DeleteCriticalSection(&_CriticalSection);
00159 }
00160
00161
00162
00163
00164 void CSourceDSound::release()
00165 {
00166
00167
00168 #if EAX_AVAILABLE == 1
00169 if (_EAXSource != 0)
00170 {
00171 _EAXSource->Release();
00172 _EAXSource = 0;
00173 }
00174 #endif
00175
00176 if (_SecondaryBuffer != 0)
00177 {
00178 _SecondaryBuffer->Stop();
00179 }
00180
00181 if (_3DBuffer != 0)
00182 {
00183 _3DBuffer->Release();
00184 _3DBuffer = 0;
00185 }
00186
00187 if (_SecondaryBuffer != 0)
00188 {
00189 _SecondaryBuffer->Release();
00190 _SecondaryBuffer = 0;
00191 }
00192
00193 }
00194
00195
00196 uint32 CSourceDSound::getTime()
00197 {
00198 if (_Sample == 0)
00199 return 0;
00200
00201 TSampleFormat format;
00202 uint freq;
00203
00204 _Sample->getFormat(format, freq);
00205
00206 return uint32(1000.0f * (_PlayOffset+1) / (float)freq);
00207 }
00208
00209
00210
00211 void CSourceDSound::init(LPDIRECTSOUND directSound, bool useEax)
00212 {
00213
00214
00215 WAVEFORMATEX format;
00216
00217 format.cbSize = sizeof(WAVEFORMATEX);
00218 format.nChannels = _DefaultChannels;
00219 format.wBitsPerSample = _DefaultSampleSize;
00220 format.nSamplesPerSec = _DefaultSampleRate;
00221 format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
00222 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
00223 format.wFormatTag = WAVE_FORMAT_PCM;
00224
00225
00226
00227
00228 DSBUFFERDESC desc;
00229
00230 CSoundDriverDSound* driver = CSoundDriverDSound::instance();
00231
00232
00233 ZeroMemory(&desc, sizeof(DSBUFFERDESC));
00234 desc.dwSize = sizeof(DSBUFFERDESC);
00235 desc.lpwfxFormat = &format;
00236 desc.dwBufferBytes = _SecondaryBufferSize;
00237 desc.dwReserved = 0;
00238
00239 if (driver->countHw3DBuffers() > 0)
00240 {
00241
00242 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCHARDWARE | DSBCAPS_GETCURRENTPOSITION2
00243 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
00244 }
00245 else
00246 {
00247 nldebug("Failed to create a 3D Hardware DirectX secondary buffer. Try 3D software one");
00248
00249 if (useEax)
00250 {
00251 throw ESoundDriver("No 3d hardware sound buffer, but EAX support requested");
00252 }
00253
00254 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2
00255 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
00256 desc.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
00257
00258 }
00259
00260
00261
00262
00263 if (FAILED(directSound->CreateSoundBuffer(&desc, &_SecondaryBuffer, NULL)))
00264 {
00265 if (useEax)
00266 {
00267 throw ESoundDriver("Failed to create a 3d hardware sound buffer, but EAX support requested");
00268 }
00269 nlwarning("Source: Failed to create a buffer with 3D capabilities.");
00270
00271 ZeroMemory(&desc, sizeof(DSBUFFERDESC));
00272 desc.dwSize = sizeof(DSBUFFERDESC);
00273 desc.lpwfxFormat = &format;
00274 desc.dwBufferBytes = _SecondaryBufferSize;
00275 desc.dwReserved = 0;
00276
00277 if (driver->countHw2DBuffers() > 0)
00278 {
00279
00280 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCHARDWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
00281 }
00282 else
00283 {
00284
00285 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
00286 }
00287
00288 if (FAILED(directSound->CreateSoundBuffer(&desc, &_SecondaryBuffer, NULL)))
00289 {
00290 throw ESoundDriver("Failed to allocate the DirectSound secondary buffer");
00291 }
00292 }
00293
00294
00295 nldebug("Created DirectX secondary buffer @ %p", _SecondaryBuffer);
00296
00297
00298 LPVOID ptr;
00299 DWORD bytes;
00300
00301 if (FAILED(_SecondaryBuffer->Lock(0, 0, &ptr, &bytes, NULL, NULL, DSBLOCK_ENTIREBUFFER)))
00302 {
00303 throw ESoundDriver("Failed to lock the DirectSound secondary buffer");
00304 }
00305
00306 memset(ptr, 0, bytes);
00307
00308 _SecondaryBuffer->Unlock(ptr, bytes, 0, 0);
00309
00310
00311
00312 if (FAILED(_SecondaryBuffer->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID *) &_3DBuffer)))
00313 {
00314 throw ESoundDriver("Failed to allocate the DirectSound 3D buffer");
00315 }
00316
00317
00318 if (FAILED(_SecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING)))
00319 {
00320 throw ESoundDriver("Play failed");
00321 }
00322
00323 }
00324
00325
00326
00327 void CSourceDSound::reset()
00328 {
00329 setPitch(1.0f);
00330 setLooping(false);
00331 setGain(1.0f);
00332 }
00333
00335 void CSourceDSound::setStreaming(bool streaming)
00336 {
00337 if (streaming) throw ESoundDriverNoBufferStreaming();
00338 }
00339
00340
00341
00342 void CSourceDSound::setStaticBuffer( IBuffer *buffer )
00343 {
00344 EnterCriticalSection(&_CriticalSection);
00345
00346 if (_State == source_playing)
00347 {
00348 _State = source_swap_pending;
00349 _Sample = 0;
00350 _NextSample = buffer;
00351 _SampleOffset = 0;
00352 _PlayOffset = 0;
00353 }
00354 else
00355 {
00356 _Sample = buffer;
00357 _NextSample = 0;
00358 _SampleOffset = 0;
00359 _PlayOffset = 0;
00360 _ADPCMState.PreviousSample = 0;
00361 _ADPCMState.StepIndex = 0;
00362 if (buffer)
00363 {
00364
00365 buffer->getFormat(_Format, _SampleFreq);
00366 switch(_Format)
00367 {
00368 case Mono8:
00369 _SampleSize = buffer->getSize();
00370 break;
00371 case Mono16:
00372 _SampleSize = buffer->getSize() / 2;
00373 break;
00374 case Mono16ADPCM:
00375 _SampleSize = buffer->getSize() * 2;
00376 break;
00377 case Stereo8:
00378 _SampleSize = buffer->getSize() / 2;
00379 break;
00380 case Stereo16:
00381 _SampleSize = buffer->getSize() / 4;
00382 break;
00383 }
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 LeaveCriticalSection(&_CriticalSection);
00407 }
00408
00409 IBuffer *CSourceDSound::getStaticBuffer()
00410 {
00411 if (_State == source_swap_pending)
00412 return _NextSample;
00413 else
00414 return _Sample;
00415
00416 }
00417
00420 void CSourceDSound::submitStreamingBuffer(IBuffer * )
00421 {
00422 throw ESoundDriverNoBufferStreaming();
00423 }
00424
00426 uint CSourceDSound::countStreamingBuffers() const
00427 {
00428 throw ESoundDriverNoBufferStreaming();
00429 }
00430
00431 void CSourceDSound::getCursors(TCursors &cursors)
00432 {
00433 _SecondaryBuffer->GetCurrentPosition((DWORD*)&cursors.PlayCursor, (DWORD*)&cursors.WriteCursor);
00434
00435
00436
00437
00438
00439
00440
00441 cursors.WriteSize = std::min(_UpdateCopySize, (cursors.PlayCursor - cursors.WriteCursor) & _SizeMask);
00442 }
00443
00444 void CSourceDSound::fillData(sint16 *dst, uint nbSample)
00445 {
00446 nlassert((nbSample & 0xfffffffe) == nbSample);
00447 if (_Sample != 0)
00448 {
00449 const void *data = ((CBufferDSound*) _Sample)->getData();
00450 const sint8 *data8;
00451 const uint8 *dataAdpcm;
00452 const sint16 *data16;
00453 uint i;
00454
00455
00456
00457
00458 switch(_Format)
00459 {
00460 case Mono8:
00461 data8 = (sint8*) data;
00462 data8 += _SampleOffset;
00463
00464 for (i=0; i<nbSample; ++i)
00465 {
00466 dst[i] = sint16(data8[i])*256;
00467 }
00468 _SampleOffset += nbSample;
00469 break;
00470 case Mono16ADPCM:
00471 dataAdpcm = (uint8*) data;
00472 dataAdpcm += _SampleOffset/2;
00473
00474
00475 IBuffer::decodeADPCM(dataAdpcm, dst, nbSample, _ADPCMState);
00476 _SampleOffset += nbSample;
00477 break;
00478 case Mono16:
00479 data16 = (sint16*)data;
00480 data16 += _SampleOffset;
00481
00482
00483 CFastMem::memcpy(dst, data16, nbSample*2);
00484 _SampleOffset += nbSample;
00485 break;
00486 case Stereo8:
00487 data8 = (sint8*) data;
00488 data8 += _SampleOffset*2;
00489 for (i=0; i<nbSample; ++i)
00490 {
00491 dst[i] = (sint16(data8[i*2])*128) + (sint16(data8[i*2+1])*128);
00492 }
00493 _SampleOffset += nbSample*2;
00494 break;
00495 case Stereo16:
00496 data16 = (sint16*) data;
00497 data16 += _SampleOffset*2;
00498 for (i=0; i<nbSample; ++i)
00499 {
00500 dst[i] = (data16[i*2]>>1) + (data16[i*2+1]>>1);
00501 }
00502 _SampleOffset += nbSample*2;
00503 break;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 nlassert(_SampleOffset <= _SampleSize);
00515 }
00516 else
00517 {
00518 nldebug("Filling : NO DATA from %p to %p (%p sample, %p bytes)", dst, dst+nbSample, nbSample, nbSample*2);
00519
00520
00521 while (nbSample)
00522 {
00523 *dst++ = 0;
00524 --nbSample;
00525 }
00526 }
00527 }
00528
00529 void CSourceDSound::fillData(const TLockedBufferInfo &lbi, int nbSample)
00530 {
00531 nlassert((nbSample & 0x1) == 0);
00532
00533
00534 uint size = std::min(uint32(nbSample), lbi.Size1>>1);
00535 fillData(lbi.Ptr1, size);
00536 nbSample -= size;
00537
00538 if (nbSample)
00539 {
00540
00541
00542 size = min(uint32(nbSample), lbi.Size2>>1);
00543 fillData(lbi.Ptr2, size);
00544 nbSample -= size;
00545 }
00546 nlassert(nbSample == 0);
00547 }
00548
00549 void CSourceDSound::fillSilence(const TLockedBufferInfo &lbi, int nbSample)
00550 {
00551 uint size = min(uint32(nbSample), lbi.Size1>>1);
00552 uint tmp = size;
00553 sint16 *ptr = lbi.Ptr1;
00554
00555
00556 for (; size != 0; --size)
00557 *ptr++ = 0;
00558 nbSample -= tmp;
00559
00560 if (nbSample)
00561 {
00562 size = std::min(uint32(nbSample), lbi.Size2>>1);
00563 tmp = size;
00564 ptr = lbi.Ptr2;
00565
00566 for (; size != 0; --size)
00567 *ptr++ = 0;
00568 nbSample -= tmp;
00569 }
00570 nlassert(nbSample == 0);
00571
00572 }
00573
00574 void CSourceDSound::xfade(const TLockedBufferInfo &lbi, sint16 *src)
00575 {
00576
00577
00578 nlassert((_XFadeSize & 0x1) == 0);
00579 uint fade = _XFadeSize;
00580 sint16 *ptr = lbi.Ptr1;
00581 uint count = lbi.Size1 /2;
00582 sint alpha, invAlpha;
00583
00584 while (fade && count)
00585 {
00586 alpha = (fade<<16) / _XFadeSize;
00587 invAlpha = 0x10000 - alpha;
00588 *ptr = (sint(*ptr)*alpha + sint(*src) * invAlpha) >> 16;
00589 ++src;
00590 ++ptr;
00591 --count;
00592 --fade;
00593 }
00594
00595 ptr = lbi.Ptr2;
00596 count = lbi.Size2 /2;
00597
00598 while (fade && count)
00599 {
00600 alpha = (fade<<16) / _XFadeSize;
00601 invAlpha = 0x10000 - alpha;
00602 *ptr = (sint(*ptr)*alpha + sint(*src) * invAlpha) >> 16;
00603 ++src;
00604 ++ptr;
00605 --count;
00606 --fade;
00607 }
00608 }
00609
00610 void CSourceDSound::fadeOut(const TLockedBufferInfo &lbi)
00611 {
00612 nlassert((_XFadeSize & 0x1) == 0);
00613 uint fade = _XFadeSize;
00614 sint16 *ptr = lbi.Ptr1;
00615 uint count = lbi.Size1/2;
00616 sint alpha;
00617
00618 while (fade && count)
00619 {
00620 alpha = (fade<<16) / _XFadeSize;
00621 *ptr = (*ptr*alpha) >> 16;
00622 ++ptr;
00623 --count;
00624 --fade;
00625 }
00626
00627 ptr = lbi.Ptr2;
00628 count = lbi.Size2/2;
00629
00630 while (fade && count)
00631 {
00632 alpha = (fade<<16) / _XFadeSize;
00633 *ptr = (*ptr*alpha) >> 16;
00634 ++ptr;
00635 --count;
00636 --fade;
00637 }
00638 }
00639 void CSourceDSound::fadeIn(const TLockedBufferInfo &lbi)
00640 {
00641
00642
00643 nlassert((_XFadeSize & 0x1) == 0);
00644 uint fade = _XFadeSize;
00645 sint16 *ptr = lbi.Ptr1;
00646 uint count = lbi.Size1 /2;
00647 sint alpha, invAlpha;
00648
00649 while (fade && count)
00650 {
00651 alpha = (fade<<16) / _XFadeSize;
00652 invAlpha = 0x10000 - alpha;
00653 *ptr = (*ptr*invAlpha) >> 16;
00654 ++ptr;
00655 --count;
00656 --fade;
00657 }
00658
00659 ptr = lbi.Ptr2;
00660 count = lbi.Size2 /2;
00661
00662 while (fade && count)
00663 {
00664 alpha = (fade<<16) / _XFadeSize;
00665 invAlpha = 0x10000 - alpha;
00666 *ptr = (*ptr*invAlpha) >> 16;
00667 ++ptr;
00668 --count;
00669 --fade;
00670 }
00671 }
00672
00673
00674 void CSourceDSound::advanceFill(TLockedBufferInfo &lbi, uint nbSample)
00675 {
00676 uint32 size = nbSample * 2;
00677 if (lbi.Size1 < size)
00678 {
00679 size -= lbi.Size1;
00680 lbi.Size1 = lbi.Size2;
00681 lbi.Size2 = 0;
00682 lbi.Ptr1 = lbi.Ptr2;
00683 lbi.Ptr2 = 0;
00684 }
00685
00686 nlassert(lbi.Size1 >= size);
00687 lbi.Size1 -= size;
00688 lbi.Ptr1 += size/2;
00689
00690 _FillOffset += nbSample*2;
00691 nlassert(_FillOffset == (_FillOffset & 0xfffffffC));
00692 _FillOffset &= _SizeMask;
00693
00694
00695 nlassert(_FillOffset < _SecondaryBufferSize);
00696 }
00697
00698
00699
00700 bool CSourceDSound::play()
00701 {
00702
00703 EnterCriticalSection(&_CriticalSection);
00704
00705 _SilenceWriten = 0;
00706
00707
00708 TCursors cursors;
00709 getCursors(cursors);
00710
00711
00712 _FillOffset = cursors.WriteCursor;
00713 _FillOffset = (_FillOffset+3) & 0xfffffffC;
00714 cursors.WriteCursor = _FillOffset;
00715
00716 TLockedBufferInfo lbi;
00717 if (lock(_FillOffset, cursors.WriteSize, lbi))
00718 {
00719 TLockedBufferInfo unlockInfo(lbi);
00720
00721 if (_State == source_swap_pending)
00722 {
00723
00724 _Sample = _NextSample;
00725 _NextSample = 0;
00726 if (_Sample != 0)
00727 {
00728 _Sample->getFormat(_Format, _SampleFreq);
00729 switch(_Format)
00730 {
00731 case Mono8:
00732 _SampleSize = _Sample->getSize();
00733 break;
00734 case Mono16:
00735 _SampleSize = _Sample->getSize() / 2;
00736 break;
00737 case Mono16ADPCM:
00738 _SampleSize = _Sample->getSize() * 2;
00739 break;
00740 case Stereo8:
00741 _SampleSize = _Sample->getSize() / 2;
00742 break;
00743 case Stereo16:
00744 _SampleSize = _Sample->getSize() / 4;
00745 break;
00746 }
00747 _State = source_playing;
00748 }
00749 else
00750 {
00751 _SampleSize = 0;
00752 _State = source_silencing;
00753 }
00754 }
00755 _LastPlayPos = cursors.PlayCursor;
00756 _SampleOffset = 0;
00757 _PlayOffset = 0;
00758 _ADPCMState.PreviousSample = 0;
00759 _ADPCMState.StepIndex = 0;
00760
00761 uint dataToFill = std::min(uint(cursors.WriteSize / 2), _SampleSize - _SampleOffset);
00762 dataToFill &= 0xfffffffe;
00763
00764 if (_State == source_playing || _State == source_silencing)
00765 {
00766
00767 sint16 fadeBuffer[_XFadeSize];
00768 fillData(fadeBuffer, _XFadeSize);
00769 xfade(lbi, fadeBuffer);
00770 advanceFill(lbi, _XFadeSize);
00771 cursors.WriteSize -= _XFadeSize*2;
00772 dataToFill -= _XFadeSize;
00773 }
00774 else
00775 {
00776
00777 fillData(lbi, _XFadeSize);
00778 fadeIn(lbi);
00779 advanceFill(lbi, _XFadeSize);
00780 cursors.WriteSize -= _XFadeSize*2;
00781 dataToFill -= _XFadeSize;
00782 }
00783 fillData(lbi, dataToFill);
00784 cursors.WriteSize -= dataToFill * 2;
00785 advanceFill(lbi, dataToFill);
00786 _State = source_playing;
00787 if (_Loop)
00788 {
00789 while (cursors.WriteSize >= 4)
00790 {
00791 if (_SampleOffset == _SampleSize)
00792 {
00793
00794 _SampleOffset = 0;
00795 _ADPCMState.PreviousSample = 0;
00796 _ADPCMState.StepIndex = 0;
00797 }
00798 nlassert(_SampleOffset < _SampleSize);
00799 dataToFill = std::min(uint(cursors.WriteSize / 2), _SampleSize - _SampleOffset);
00800 dataToFill &= 0xfffffffe;
00801 fillData(lbi, dataToFill);
00802 advanceFill(lbi, dataToFill);
00803 cursors.WriteSize -= dataToFill*2;
00804 }
00805 }
00806 else
00807 {
00808 if (_SampleOffset == _SampleSize)
00809 {
00810
00811
00812 fillSilence(lbi, cursors.WriteSize/2);
00813 advanceFill(lbi, cursors.WriteSize/2);
00814 _SilenceWriten = cursors.WriteSize;
00815 cursors.WriteSize = 0;
00816 }
00817
00818
00819 }
00820
00821
00822 unlock(unlockInfo);
00823 }
00824 else
00825 {
00826 nlwarning("Couldn't lock the sound buffer for %u bytes", cursors.WriteSize);
00827 }
00828
00829
00830 CListenerDSound* listener = CListenerDSound::instance();
00831
00832 updateVolume(listener->getPos());
00833
00834 LeaveCriticalSection(&_CriticalSection);
00835
00836 return true;
00837 }
00838
00839 void CSourceDSound::stop()
00840 {
00841
00842 EnterCriticalSection(&_CriticalSection);
00843
00844 if (_State != source_stoped && _State != source_silencing)
00845 {
00846
00847 TCursors cursors;
00848 getCursors(cursors);
00849
00850 _FillOffset = cursors.WriteCursor;
00851 _FillOffset = (_FillOffset+3) & 0xfffffffC;
00852
00853 TLockedBufferInfo lbi;
00854 if (lock(_FillOffset, cursors.WriteSize, lbi))
00855 {
00856 TLockedBufferInfo unlockInfo(lbi);
00857
00858 fadeOut(lbi);
00859 advanceFill(lbi, _XFadeSize);
00860 cursors.WriteSize -= _XFadeSize*2;
00861 fillSilence(lbi, cursors.WriteSize/2);
00862 advanceFill(lbi, cursors.WriteSize/2);
00863 _SilenceWriten = cursors.WriteSize;
00864
00865 _State = source_silencing;
00866
00867 unlock(unlockInfo);
00868 }
00869 }
00870
00871 LeaveCriticalSection(&_CriticalSection);
00872 }
00873
00874
00875
00876
00877
00878 void CSourceDSound::setLooping( bool l )
00879 {
00880 _Loop = l;
00881 }
00882
00883
00884
00885
00886 bool CSourceDSound::getLooping() const
00887 {
00888 return _Loop;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 void CSourceDSound::pause()
01010 {
01011
01012 nlassert(false);
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 }
01030
01031
01032
01033 bool CSourceDSound::isPlaying() const
01034 {
01035
01036 return _State == source_playing || _State == source_swap_pending;
01037 }
01038
01039
01040
01041
01042 bool CSourceDSound::isPaused() const
01043 {
01044
01045 nlassert(false);
01046 return false;
01047
01048 }
01049
01050
01051
01052
01053 bool CSourceDSound::isStopped() const
01054 {
01055 return _State == source_silencing || _State == source_stoped;
01056
01057 }
01058
01059
01060
01061
01062 bool CSourceDSound::needsUpdate()
01063 {
01064 return _State == source_silencing || _State == source_playing || _State == source_swap_pending;
01065 }
01066
01067
01068
01069
01070
01071 bool CSourceDSound::update()
01072 {
01073 H_AUTO(NLSOUND_SourceDSoundUpdate)
01074 bool updateDone = false;
01075
01076 EnterCriticalSection(&_CriticalSection);
01077
01078
01079 TCursors cursors;
01080 getCursors(cursors);
01081 uint32 writeSize;
01082
01083
01084 uint32 fillSize = (cursors.PlayCursor - _FillOffset) & _SizeMask;
01085
01086 uint32 margin = (cursors.WriteCursor - cursors.PlayCursor) & _SizeMask;
01087
01088 uint32 samplePlayed = ((cursors.PlayCursor - _LastPlayPos) & _SizeMask) / 2;
01089 _LastPlayPos = cursors.PlayCursor;
01090
01091
01092
01093 if (fillSize + margin > _SecondaryBufferSize)
01094 {
01095
01096 nlwarning("FillOffset is between play and write cursor (P = %p F = %p W = %p!", cursors.PlayCursor, _FillOffset, cursors.WriteCursor);
01097 _FillOffset = cursors.WriteCursor;
01098 _FillOffset = (_FillOffset+3) & 0xfffffffC;
01099 _SilenceWriten = 0;
01100 nlassert(_FillOffset < _SecondaryBufferSize);
01101 }
01102
01103
01104 uint32 advance = (_FillOffset - cursors.WriteCursor) & _SizeMask;
01105
01106
01107
01108
01109 if (advance > _UpdateCopySize)
01110 {
01111
01112 cursors.WriteSize = 0;
01113 }
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138 cursors.WriteCursor = _FillOffset;
01139 writeSize = cursors.WriteSize;
01140
01141
01142 if (_State == source_playing)
01143 _PlayOffset += samplePlayed;
01144
01145 if (writeSize >= _UpdateCopySize)
01146 {
01147
01148 writeSize = _UpdateCopySize;
01149 updateDone = true;
01150 TLockedBufferInfo lbi;
01151 if (lock(_FillOffset, writeSize, lbi))
01152 {
01153 TLockedBufferInfo unlockInfo(lbi);
01154 if (_State == source_playing)
01155 {
01156 nlassert(_SampleOffset <= _SampleSize);
01157 uint32 updateSize = min(_SampleSize - _SampleOffset, uint(writeSize/2));
01158 updateSize &= 0xfffffffe;
01159 fillData(lbi, updateSize);
01160 advanceFill(lbi, updateSize);
01161 writeSize -= updateSize*2;
01162
01163 if (_Loop)
01164 {
01165 while (_PlayOffset >= _SampleSize)
01166 _PlayOffset -= _SampleSize;
01167
01168
01169 while (writeSize >= 4)
01170 {
01171 if (_SampleOffset == _SampleSize)
01172 {
01173
01174 _SampleOffset = 0;
01175 _ADPCMState.PreviousSample = 0;
01176 _ADPCMState.StepIndex = 0;
01177 }
01178
01179 updateSize = min(_SampleSize - _SampleOffset, uint(writeSize/2));
01180 updateSize &= 0xfffffffe;
01181 fillData(lbi, updateSize);
01182 advanceFill(lbi, updateSize);
01183 writeSize -= updateSize*2;
01184 }
01185 }
01186 else
01187 {
01188 if (_SampleOffset == _SampleSize)
01189 {
01190 fillSilence(lbi, writeSize/2);
01191 advanceFill(lbi, writeSize/2);
01192 _SilenceWriten += writeSize;
01193 }
01194 if (_PlayOffset >= _SampleSize)
01195 {
01196
01197 _PlayOffset = _SampleSize;
01198 _State = source_silencing;
01199 }
01200 }
01201
01202 }
01203 else if (_State == source_swap_pending)
01204 {
01205
01206
01207 fadeOut(lbi);
01208 advanceFill(lbi, _XFadeSize);
01209 writeSize -= _XFadeSize*2;
01210 fillSilence(lbi, writeSize/2);
01211 advanceFill(lbi, writeSize/2);
01212 _SilenceWriten = writeSize;
01213 _State = source_silencing;
01214 }
01215 else if (_State == source_silencing)
01216 {
01217
01218 uint32 updateSize = min(writeSize, _SecondaryBufferSize - _SilenceWriten);
01219 updateSize &= 0xfffffffC;
01220 fillSilence(lbi, updateSize/2);
01221 advanceFill(lbi, updateSize/2);
01222 _SilenceWriten += updateSize;
01223
01224 if (_SilenceWriten == _SecondaryBufferSize)
01225 _State = source_stoped;
01226 }
01227 else
01228 {
01229 nlwarning("Update not needed !");
01230 }
01231
01232 unlock(unlockInfo);
01233 }
01234 }
01235
01236 LeaveCriticalSection(&_CriticalSection);
01237
01238 return updateDone;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 void CSourceDSound::setPos( const NLMISC::CVector& pos, bool deferred )
01326 {
01327 _Pos = pos;
01328
01329 if (_3DBuffer != NULL)
01330 {
01331 if (_3DBuffer->SetPosition(pos.x, pos.z, pos.y, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
01332 {
01333 nlwarning ("SetPosition failed");
01334 }
01335 else
01336 {
01337
01338 }
01339 }
01340 }
01341
01342
01343
01344
01345 const NLMISC::CVector &CSourceDSound::getPos() const
01346 {
01347 return _Pos;
01348 }
01349
01350
01351
01352
01353 void CSourceDSound::setVelocity( const NLMISC::CVector& vel, bool deferred )
01354 {
01355 if (_3DBuffer != NULL)
01356 {
01357 if (_3DBuffer->SetVelocity(vel.x, vel.z, vel.y, deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
01358 {
01359 nlwarning ("SetVelocity failed");
01360 }
01361 }
01362 }
01363
01364
01365
01366
01367 void CSourceDSound::getVelocity( NLMISC::CVector& vel ) const
01368 {
01369 if (_3DBuffer != NULL)
01370 {
01371 D3DVECTOR v;
01372
01373 if (_3DBuffer->GetVelocity(&v) != DS_OK)
01374 {
01375 nlwarning ("GetVelocity failed");
01376 vel.set(0, 0, 0);
01377 }
01378 else
01379 {
01380 vel.set(v.x, v.z, v.y);
01381 }
01382 }
01383 else
01384 {
01385 vel.set(0, 0, 0);
01386 }
01387 }
01388
01389
01390
01391
01392 void CSourceDSound::setDirection( const NLMISC::CVector& dir )
01393 {
01394 if (_3DBuffer != 0)
01395 {
01396 if (_3DBuffer->SetConeOrientation(dir.x, dir.z, dir.y, DS3D_DEFERRED) != DS_OK)
01397 {
01398 nlwarning ("SetConeOrientation failed (x=%.2f, y=%.2f, z=%.2f)", dir.x, dir.y, dir.z);
01399 }
01400 else
01401 {
01402
01403 }
01404 }
01405 }
01406
01407
01408
01409
01410 void CSourceDSound::getDirection( NLMISC::CVector& dir ) const
01411 {
01412 if (_3DBuffer != NULL)
01413 {
01414 D3DVECTOR v;
01415
01416 if (_3DBuffer->GetConeOrientation(&v) != DS_OK)
01417 {
01418 nlwarning("GetConeOrientation failed");
01419 dir.set(0, 0, 1);
01420 }
01421 else
01422 {
01423 dir.set(v.x, v.z, v.y);
01424 }
01425 }
01426 else
01427 {
01428 dir.set(0, 0, 1);
01429 }
01430 }
01431
01432
01433
01434
01435 void CSourceDSound::setGain( float gain )
01436 {
01437 clamp(gain, 0.00001f, 1.0f);
01438 _Gain = gain;
01439
01440
01441 _Volume = (uint32)(100.0 * 20.0 * log10(gain));
01442 clamp(_Volume, DSBVOLUME_MIN, DSBVOLUME_MAX);
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 }
01453
01454
01455
01456
01457
01458 float CSourceDSound::getGain() const
01459 {
01460 return _Gain;
01461 }
01462
01463
01464
01465
01466 void CSourceDSound::setPitch( float coeff )
01467 {
01468
01469
01470 if ((_Sample != 0) && (_SecondaryBuffer != 0))
01471 {
01472 TSampleFormat format;
01473 uint freq;
01474
01475 _Sample->getFormat(format, freq);
01476
01477 _SampleRate = (uint32) (coeff * (float) freq);
01478
01479
01480
01481 if (_SecondaryBuffer->SetFrequency(_SampleRate) != DS_OK)
01482 {
01483
01484 nlwarning("SetFrequency");
01485 }
01486 }
01487 }
01488
01489
01490
01491
01492 float CSourceDSound::getPitch() const
01493 {
01494 if ((_Sample != 0) && (_SecondaryBuffer != 0))
01495 {
01496 TSampleFormat format;
01497 uint freq0;
01498 DWORD freq;
01499
01500 _Sample->getFormat(format, freq0);
01501
01502 if (_SecondaryBuffer->GetFrequency(&freq) != DS_OK)
01503 {
01504 nlwarning("GetFrequency failed");
01505 return 1.0;
01506 }
01507
01508 return ((float) freq / (float) freq0);
01509 }
01510
01511 return 1.0;
01512 }
01513
01514
01515
01516
01517 void CSourceDSound::setSourceRelativeMode( bool mode )
01518 {
01519 if (_3DBuffer != 0)
01520 {
01521 HRESULT hr;
01522
01523 if (mode)
01524 {
01525 hr = _3DBuffer->SetMode(DS3DMODE_HEADRELATIVE, DS3D_IMMEDIATE);
01526 }
01527 else
01528 {
01529 hr = _3DBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE);
01530 }
01531
01532
01533 if (hr == DS_OK)
01534 _PosRelative= mode;
01535 else
01536 nlwarning("SetMode failed");
01537 }
01538 else
01539 {
01540 nlwarning("Requested setSourceRelativeMode on a non-3D source");
01541 }
01542 }
01543
01544
01545
01546
01547 bool CSourceDSound::getSourceRelativeMode() const
01548 {
01549 return _PosRelative;
01550 }
01551
01552
01553
01554 void CSourceDSound::setMinMaxDistances( float mindist, float maxdist, bool deferred )
01555 {
01556 if (_3DBuffer != 0)
01557 {
01558 if (_3DBuffer->SetMinDistance(std::max(DS3D_DEFAULTMINDISTANCE, mindist), deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
01559 {
01560 nlwarning("SetMinDistance (%f) failed", mindist);
01561 }
01562 if (_3DBuffer->SetMaxDistance(std::min(DS3D_DEFAULTMAXDISTANCE, maxdist), deferred ? DS3D_DEFERRED : DS3D_IMMEDIATE) != DS_OK)
01563 {
01564 nlwarning("SetMaxDistance (%f) failed", maxdist);
01565 }
01566 }
01567 else
01568 {
01569 nlwarning("Requested setMinMaxDistances on a non-3D source");
01570 }
01571 }
01572
01573
01574
01575
01576 void CSourceDSound::getMinMaxDistances( float& mindist, float& maxdist ) const
01577 {
01578 if (_3DBuffer != 0)
01579 {
01580 D3DVALUE min, max;
01581
01582 if ((_3DBuffer->GetMinDistance(&min) != DS_OK)
01583 || (_3DBuffer->GetMaxDistance(&max) != DS_OK))
01584 {
01585 mindist = 0.0f;
01586 maxdist = 0.0f;
01587 nlwarning("GetMinDistance or GetMaxDistance failed");
01588 }
01589 else
01590 {
01591 mindist = min;
01592 maxdist = max;
01593 }
01594 }
01595 else
01596 {
01597 mindist = 0.0f;
01598 maxdist = 0.0f;
01599 nlwarning("Requested getMinMaxDistances on a non-3D source");
01600 }
01601 }
01602
01603
01604 void CSourceDSound::updateVolume( const NLMISC::CVector& listener )
01605 {
01606 if (!CSoundDriverDSound::instance()->getOption(ISoundDriver::OptionManualRolloff))
01607 {
01608
01609 _SecondaryBuffer->SetVolume(_Volume);
01610 }
01611 else
01612 {
01613 CVector pos = getPos();
01614
01615 if(!_PosRelative)
01616 pos -= listener;
01617 float sqrdist = pos.sqrnorm();
01618
01619 float mindist, maxdist;
01620 getMinMaxDistances(mindist, maxdist);
01621
01622
01623 sint32 volumeDB = ISource::computeManualRollOff(_Volume, DSBVOLUME_MIN, DSBVOLUME_MAX, _Alpha, sqrdist, mindist, maxdist);
01624
01625
01626 _SecondaryBuffer->SetVolume(volumeDB);
01627 }
01628 }
01629
01630
01631
01632 void CSourceDSound::setCone( float innerAngle, float outerAngle, float outerGain )
01633 {
01634 if (_3DBuffer != 0)
01635 {
01636
01637
01638
01639 DWORD inner = (DWORD)(180.0 * innerAngle / Pi);
01640 DWORD outer = (DWORD)(180.0 * outerAngle / Pi);
01641
01642
01643
01644 if (outer < inner)
01645 {
01646 outer = inner;
01647 }
01648
01649 while (inner < DS3D_MINCONEANGLE)
01650 {
01651 inner += 360;
01652 }
01653
01654 while (inner > DS3D_MAXCONEANGLE)
01655 {
01656 inner -= 360;
01657 }
01658
01659 while (outer < DS3D_MINCONEANGLE)
01660 {
01661 outer += 360;
01662 }
01663
01664 while (outer > DS3D_MAXCONEANGLE)
01665 {
01666 outer -= 360;
01667 }
01668
01669 if (_3DBuffer->SetConeAngles(inner, outer, DS3D_DEFERRED) != DS_OK)
01670 {
01671 nlwarning("SetConeAngles failed");
01672 }
01673
01674
01675 if (outerGain < 0.00001f)
01676 {
01677 outerGain = 0.00001f;
01678 }
01679
01680
01681 LONG volume = (LONG)(100.0 * 20.0 * log10(outerGain));
01682
01683 if (volume < DSBVOLUME_MIN)
01684 {
01685 volume = DSBVOLUME_MIN;
01686 }
01687 else if (volume > DSBVOLUME_MAX)
01688 {
01689 volume = DSBVOLUME_MAX;
01690 }
01691
01692 if (_3DBuffer->SetConeOutsideVolume(volume, DS3D_DEFERRED) != DS_OK)
01693 {
01694 nlwarning("SetConeOutsideVolume failed");
01695 }
01696
01697 }
01698 else
01699 {
01700 nlwarning("Requested setCone on a non-3D source");
01701 }
01702 }
01703
01704
01705
01706 void CSourceDSound::getCone( float& innerAngle, float& outerAngle, float& outerGain ) const
01707 {
01708 if (_3DBuffer != 0)
01709 {
01710 DWORD inner, outer;
01711 LONG volume;
01712
01713 if (_3DBuffer->GetConeAngles(&inner, &outer) != DS_OK)
01714 {
01715 nlwarning("GetConeAngles failed");
01716 innerAngle = outerAngle = (float)(2.0 * Pi);
01717 }
01718 else
01719 {
01720 innerAngle = (float)(Pi * inner / 180.0);
01721 outerAngle = (float)(Pi * outer / 180.0);
01722 }
01723
01724 if (_3DBuffer->GetConeOutsideVolume(&volume) != DS_OK)
01725 {
01726 nlwarning("GetConeOutsideVolume failed");
01727 outerGain = 0.0f;
01728 }
01729 else
01730 {
01731 outerGain = (float) pow((double)10, (double) volume / 20.0 / 100.0);
01732 }
01733 }
01734 else
01735 {
01736 nlwarning("Requested getCone on a non-3D source");
01737 }
01738 }
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01756
01757
01758
01759
01760
01774 void CSourceDSound::setAlpha(double a)
01775 {
01776 _Alpha = a;
01777 }
01778
01780 void CSourceDSound::setDirect(bool )
01781 {
01782
01783 }
01784
01786 bool CSourceDSound::getDirect() const
01787 {
01788 return true;
01789 }
01790
01792 void CSourceDSound::setDirectGain(float )
01793 {
01794
01795 }
01796
01798 float CSourceDSound::getDirectGain() const
01799 {
01800 return NLSOUND_DEFAULT_DIRECT_GAIN;
01801 }
01802
01804 void CSourceDSound::enableDirectFilter(bool )
01805 {
01806
01807 }
01808
01810 bool CSourceDSound::isDirectFilterEnabled() const
01811 {
01812 return false;
01813 }
01814
01816 void CSourceDSound::setDirectFilter(TFilter , float , float , float )
01817 {
01818
01819 }
01820
01822 void CSourceDSound::getDirectFilter(TFilter &filterType, float &lowFrequency, float &highFrequency, float &passGain) const
01823 {
01824 filterType = FilterLowPass;
01825 lowFrequency = NLSOUND_DEFAULT_FILTER_PASS_LF;
01826 highFrequency = NLSOUND_DEFAULT_FILTER_PASS_HF;
01827 passGain = NLSOUND_DEFAULT_FILTER_PASS_GAIN;
01828 }
01829
01831 void CSourceDSound::setDirectFilterPassGain(float )
01832 {
01833
01834 }
01835
01837 float CSourceDSound::getDirectFilterPassGain() const
01838 {
01839 return 0.0f;
01840 }
01841
01843 void CSourceDSound::setEffect(IReverbEffect * )
01844 {
01845
01846 }
01847
01849 IEffect *CSourceDSound::getEffect() const
01850 {
01851 return NULL;
01852 }
01853
01855 void CSourceDSound::setEffectGain(float )
01856 {
01857
01858 }
01859
01861 float CSourceDSound::getEffectGain() const
01862 {
01863 return NLSOUND_DEFAULT_EFFECT_GAIN;
01864 }
01865
01867 void CSourceDSound::enableEffectFilter(bool )
01868 {
01869
01870 }
01871
01873 bool CSourceDSound::isEffectFilterEnabled() const
01874 {
01875 return false;
01876 }
01877
01879 void CSourceDSound::setEffectFilter(TFilter , float , float , float )
01880 {
01881
01882 }
01883
01885 void CSourceDSound::getEffectFilter(TFilter &filterType, float &lowFrequency, float &highFrequency, float &passGain) const
01886 {
01887 filterType = FilterLowPass;
01888 lowFrequency = NLSOUND_DEFAULT_FILTER_PASS_LF;
01889 highFrequency = NLSOUND_DEFAULT_FILTER_PASS_HF;
01890 passGain = NLSOUND_DEFAULT_FILTER_PASS_GAIN;
01891 }
01892
01894 void CSourceDSound::setEffectFilterPassGain(float )
01895 {
01896
01897 }
01898
01900 float CSourceDSound::getEffectFilterPassGain() const
01901 {
01902 return 0.0f;
01903 }
01904
01905
01906
01907 IBuffer *CSourceDSound::getBuffer()
01908 {
01909 return _Sample;
01910 }
01911
01912
01913
01914
01915 bool CSourceDSound::lock(uint32 offset, uint32 size, TLockedBufferInfo &lbi)
01916 {
01917 HRESULT hr = _SecondaryBuffer->Lock(offset, size, (LPVOID*) &lbi.Ptr1, (DWORD*) &lbi.Size1, (LPVOID*) &lbi.Ptr2, (DWORD*) &lbi.Size2, 0);
01918
01919 if (hr == DSERR_BUFFERLOST)
01920 {
01921
01922 if (FAILED(_SecondaryBuffer->Restore()))
01923 {
01924 nlwarning("Lock failed (1)");
01925 return false;
01926 }
01927 if (FAILED(_SecondaryBuffer->Lock(offset, size, (LPVOID*) &lbi.Ptr1, (DWORD*)&lbi.Size1, (LPVOID*) &lbi.Ptr2, (DWORD*)&lbi.Size2, 0)))
01928 {
01929 nlwarning("Lock failed (2)");
01930 return false;
01931 }
01932 }
01933 else if (hr != DS_OK)
01934 {
01935 nlwarning("Lock failed (3)");
01936 return false;
01937 }
01938
01939 return true;
01940 }
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972 bool CSourceDSound::unlock(const TLockedBufferInfo &lbi)
01973 {
01974 _SecondaryBuffer->Unlock(lbi.Ptr1, lbi.Size1, lbi.Ptr2, lbi.Size2);
01975 return true;
01976 }
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208 }