123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- //
- // ds3dvirtualbuffer.cpp
- //
- // Classes representing virtual DirectSound3D buffers that may or may not have
- // a real DirectSoundBuffer associated with them at any given moment.
- //
- #include "pch.h"
- #include "soundbase.h"
- #include "ds3dutil.h"
- #include "ds3dbuffer.h"
- #include "ds3dvirtualbuffer.h"
- namespace SoundEngine {
- /////////////////////////////////////////////////////////////////////////////
- //
- // DS3DBufferPositionTracker
- //
- /////////////////////////////////////////////////////////////////////////////
- // Create a position tracker for a sound which plays until it reaches the
- // end (for non-looping sounds) or has stop called upon it.
- BufferPositionTracker::BufferPositionTracker(ISoundPCMData* pdata, bool bLooping) :
- m_dwBytesPerSec(pdata->GetBytesPerSec()),
- m_dwLength(pdata->GetSize()),
- m_dwPositionMask(~(pdata->GetBytesPerSample() - 1)),
- m_dwPosition(0),
- m_bLooping(bLooping),
- m_bEnding(false),
- m_bASR(false)
- {
- };
- // Creates a position tracker for an ASR buffer.
- BufferPositionTracker::BufferPositionTracker(ISoundPCMData* pdata,
- DWORD dwLoopStart, DWORD dwLoopLength) :
- m_dwBytesPerSec(pdata->GetBytesPerSec()),
- m_dwLength(pdata->GetSize()),
- m_dwPositionMask(~(pdata->GetBytesPerSample() - 1)),
- m_dwPosition(0),
- m_bASR(true),
- m_bEnding(false),
- m_dwLoopStart(dwLoopStart),
- m_dwLoopLength(dwLoopLength)
- {
- // make sure the loop is contained in the buffer
- ZAssert(m_dwLoopStart + m_dwLoopLength <= m_dwLength);
- };
- // the sound has been given a stop.
- void BufferPositionTracker::Stop(bool bForceNow)
- {
- if (!m_bASR || bForceNow)
- {
- // stop it now.
- m_dwPosition = m_dwLoopLength;
- }
- m_bEnding = true;
- };
- // the given number of miliseconds have elapsed
- void BufferPositionTracker::AddTime(DWORD dwElapsedTime)
- {
- DWORD dwElapsedBytes =
- (DWORD)(dwElapsedTime * (__int64)m_dwBytesPerSec / 1000);
- if (!m_bASR)
- {
- m_dwPosition += dwElapsedBytes;
-
- // if we've passed the end...
- if (m_dwPosition > m_dwLength)
- {
- // loop for a looping sound
- if (m_bLooping && !m_bEnding)
- {
- m_dwPosition %= m_dwLength;
- }
- else
- {
- // stop the position at the end of the sound.
- m_dwPosition = m_dwLength;
- }
- }
- }
- else // m_bASR
- {
- if (m_bEnding)
- {
- bool bWasInAttack = m_dwPosition < m_dwLoopStart;
- m_dwPosition += dwElapsedBytes;
- // if we were in the attack portion, make sure we jump
- // directly to the release portion of the wave.
- if (bWasInAttack && (m_dwPosition > m_dwLoopStart))
- {
- m_dwPosition += m_dwLoopLength;
- }
- // stop the position at the end of the sound.
- if (m_dwPosition > m_dwLength)
- {
- m_dwPosition = m_dwLength;
- }
- }
- else
- {
- m_dwPosition += dwElapsedBytes;
- // loop if appropriate
- if (m_dwPosition >= m_dwLoopStart + m_dwLoopLength)
- {
- m_dwPosition =
- ((m_dwPosition - m_dwLoopStart) % m_dwLoopLength)
- + m_dwLoopStart;
- }
- }
- }
- };
- // Resets the position to the given one, presumably retrieved from a
- // playing buffer.
- void BufferPositionTracker::SetPosition(DWORD dwPosition)
- {
- m_dwPosition = min(dwPosition, m_dwLength);
- };
- /////////////////////////////////////////////////////////////////////////////
- //
- // DSVirtualSoundBuffer
- //
- /////////////////////////////////////////////////////////////////////////////
- // prepare a sound buffer with the given quality and 3D support using the
- // direct sound object pointed to by pDirectSound.
- HRESULT DSVirtualSoundBuffer::PrepareBuffer(IDirectSound* pDirectSound,
- ISoundEngine::Quality quality, bool bAllowHardware, bool bSupport3D)
- {
- HRESULT hr;
- if (m_pds3dbuffer == NULL)
- {
- if (m_bufferPositionTracker.IsASR())
- {
- DS3DASRSoundBuffer* pds3dASRBuffer = new DS3DASRSoundBuffer();
- // initialize the buffer.
- hr = pds3dASRBuffer->Init(pDirectSound, m_pdata,
- m_bufferPositionTracker.GetLoopOffset(),
- m_bufferPositionTracker.GetLoopLength(),
- bSupport3D, quality, bAllowHardware);
- if (ZFailed(hr)) return hr;
- m_pds3dbuffer = pds3dASRBuffer;
- }
- // stream sounds that are larger than 1 MB or so.
- else if (m_pdata->GetSize() > 1000000)
- {
- DS3DStreamingSoundBuffer* pds3DStreamingBuffer = new DS3DStreamingSoundBuffer();
- // initialize the buffer.
- hr = pds3DStreamingBuffer->Init(pDirectSound, m_pdata,
- m_bufferPositionTracker.IsLooping(), bSupport3D, quality, bAllowHardware);
- if (ZFailed(hr)) return hr;
- m_pds3dbuffer = pds3DStreamingBuffer;
- }
- else
- {
- DS3DStaticSoundBuffer* pds3DStaticBuffer = new DS3DStaticSoundBuffer();
- // initialize the buffer.
- hr = pds3DStaticBuffer->Init(pDirectSound, m_pdata,
- m_bufferPositionTracker.IsLooping(), bSupport3D, quality, bAllowHardware);
- if (FAILED(hr)) return hr;
- m_pds3dbuffer = pds3DStaticBuffer;
- }
- }
- m_quality = quality;
- m_bAllowHardware = bAllowHardware;
- // update the buffers's volume and pitch as needed.
- hr = m_pds3dbuffer->UpdateState(m_fGain, m_fPitch, false);
- if (ZFailed(hr)) return hr;
- return S_OK;
- }
- // Creates a virtual sound buffer for a normal sound, possibly looping
- DSVirtualSoundBuffer::DSVirtualSoundBuffer(ISoundPCMData* pdata, bool bLooping) :
- m_bufferPositionTracker(pdata, bLooping),
- m_pdata(pdata),
- m_bStarted(false),
- m_bStopped(false),
- m_bRetryStop(false),
- m_bBufferPlaying(false),
- m_bAudible(false),
- m_fAge(0),
- m_fPriority(1.0f),
- m_fGain(0.0f),
- m_fPitch(1.0f),
- m_fDynamicPriority(0.0f)
- {
- };
- // Creates a virtual sound buffer for an ASR sound
- DSVirtualSoundBuffer::DSVirtualSoundBuffer(ISoundPCMData* pdata, DWORD dwLoopOffset, DWORD dwLoopLength) :
- m_bufferPositionTracker(pdata, dwLoopOffset, dwLoopLength),
- m_pdata(pdata),
- m_bStarted(false),
- m_bStopped(false),
- m_bRetryStop(false),
- m_bBufferPlaying(false),
- m_bAudible(false),
- m_fAge(0),
- m_fPriority(1.0f),
- m_fGain(0.0f),
- m_fPitch(1.0f),
- m_fDynamicPriority(0.0f)
- {
- };
- // Recalculates the sounds position, loudness, whether it's playing, etc..
- HRESULT DSVirtualSoundBuffer::Update(DWORD dwTimeElapsed,
- const Vector& vectListenerPosition, float fRolloffFactor)
- {
- HRESULT hr;
- bool bWasStopped = m_bStopped;
- // if we tried to stop the sound and failed, try again now
- if (m_bRetryStop && m_bBufferPlaying)
- m_pds3dbuffer->Stop(true);
-
- // Start the sound and calculate the end time, if we have not done so
- // yet.
- if (!m_bStarted)
- {
- m_bStarted = true;
- }
- else
- {
- // update the play position
- m_bufferPositionTracker.AddTime((DWORD)(dwTimeElapsed * m_fPitch));
- m_fAge += dwTimeElapsed/1000.0f;
- }
- // if the buffer is playing, try to figure out its state.
- if (m_bBufferPlaying)
- {
- bool bPlaying, bBufferLost;
- hr = m_pds3dbuffer->GetStatus(bPlaying, bBufferLost);
- if (ZFailed(hr)) return hr;
- if (bBufferLost)
- {
- // we are obviously no longer playing
- m_bBufferPlaying = false;
- }
- else
- {
- // otherwise, the buffer knows if we are still playing
- m_bStopped = !bPlaying;
- }
- }
- // if we don't have a buffer playing, try to calculate if this sound
- // would still be playing if it were audible.
- if (!m_bBufferPlaying)
- {
- m_bStopped = m_bufferPositionTracker.IsStopped();
- }
- else
- {
- // update the playing sound's volume and pitch, as needed.
- hr = m_pds3dbuffer->UpdateState(m_fGain, m_fPitch);
- if (ZFailed(hr)) return hr;
- }
- // if this has just stopped
- if (m_bStopped && !bWasStopped)
- {
- // free the sound buffer to conserve resources
- m_pds3dbuffer = NULL;
- m_bBufferPlaying = FALSE;
- // if there is an event source for the sound finishing, trigger it.
- if (m_peventsourceFinished != NULL)
- {
- m_peventsourceFinished->Trigger();
- }
- }
- // set this sound to be audible if it is playing and has an attenuation
- // of less than 90dB.
- m_bAudible = !m_bStopped && (m_fGain > c_fMinAudible);
- // set the dynamic priority to be the aproximate volume plus the static
- // priority, with a 0.1 dB priority boost for physically playing sounds
- // and up to a 0.2 dB boost for sounds less than 2 seconds old. This
- // should help insure that, all other things being equal, a playing
- // sound will continue playing and a younger sound will replace an
- // identical older sound.
- //
- // Repeating weapon sounds is an example of where this behavior is most
- // important.
- m_fDynamicPriority = m_fGain + m_fPriority
- + (m_bBufferPlaying ? 0.1f : 0)
- + max(0.0f, 1.0f * (2 - m_fAge));
- return S_OK;
- };
- // Creates and starts a real dsound buffer for this sound
- HRESULT DSVirtualSoundBuffer::StartBuffer(IDirectSound* pDirectSound,
- ISoundEngine::Quality quality, bool bAllowHardware)
- {
- HRESULT hr;
- // if we have a buffer playing, we have nothing more to do
- if (m_bBufferPlaying)
- {
- ZAssert(false); // I want to know about this
- return S_FALSE;
- }
- // Create a sound buffer with the given quality (or reuse the one we
- // have, if appropriate).
- hr = PrepareBuffer(pDirectSound, quality, bAllowHardware, false);
- if (FAILED(hr)) return hr;
- // start the sound.
- hr = m_pds3dbuffer->Start(m_bufferPositionTracker.GetPosition(),
- m_bufferPositionTracker.IsStopping());
- if (FAILED(hr)) return hr;
- m_bBufferPlaying = true;
- return S_OK;
- };
- // forcibly stops the given buffer.
- HRESULT DSVirtualSoundBuffer::StopBuffer()
- {
- HRESULT hr;
- // if we don't have a buffer playing, we have nothing to do
- if (!m_bBufferPlaying)
- {
- ZAssert(false); // I want to know about this
- return S_FALSE;
- }
-
- // try to stop the sound...
- hr = m_pds3dbuffer->Stop(true);
- if (ZFailed(hr)) return hr;
- // syncronize our buffer tracker with the final position of the buffer.
- DWORD dwPosition;
- hr = m_pds3dbuffer->GetPosition(dwPosition);
- if (ZFailed(hr)) return hr;
- if (dwPosition != 0) // 0 could be a wraparound for a static buffer
- m_bufferPositionTracker.SetPosition(dwPosition);
- m_bBufferPlaying = false;
- return S_OK;
- }
- // Sets the gain, from 0 to -100 dB
- HRESULT DSVirtualSoundBuffer::SetGain(float fGain)
- {
- if (fGain > 0)
- {
- ZAssert(false);
- return E_INVALIDARG;
- }
- m_fGain = max(fGain, -100.0f);
- return S_OK;
- };
- // Sets the pitch shift, where 1.0 is normal, 0.5 is half of normal speed,
- // and 2.0 is twice normal speed.
- HRESULT DSVirtualSoundBuffer::SetPitch(float fPitch)
- {
- fPitch = max(fPitch, DSBFREQUENCY_MIN / m_pdata->GetSampleRate());
- fPitch = min(fPitch, DSBFREQUENCY_MAX / m_pdata->GetSampleRate());
- m_fPitch = fPitch;
- return S_OK;
- };
- // sets the priority - used as a addition to volume when choosing which
- // sounds are most important to play.
- HRESULT DSVirtualSoundBuffer::SetPriority(float fPriority)
- {
- m_fPriority = fPriority;
- return S_OK;
- };
- // Stops the sound. If bForceNow is true the sound will stop ASAP,
- // possibly popping. If it is false some sounds may play a trail-off
- // sound or fade away.
- HRESULT DSVirtualSoundBuffer::Stop(bool bForceNow)
- {
- HRESULT hr;
- if (m_bBufferPlaying)
- {
- // REVIEW: fade out at higher quality settings?
- hr = m_pds3dbuffer->Stop(bForceNow);
- if (ZFailed(hr))
- {
- m_bRetryStop = true;
- return hr;
- }
- }
- m_bufferPositionTracker.Stop(bForceNow);
- return S_OK;
- };
- // returns S_OK if the sound is currently playing, S_FALSE otherwise.
- HRESULT DSVirtualSoundBuffer::IsPlaying()
- {
- return m_bStopped ? S_FALSE : S_OK;
- };
- // Gets an event which fires when the sound finishes playing (for any
- // reason)
- IEventSource* DSVirtualSoundBuffer::GetFinishEventSource()
- {
- // if we don't have an event source, create one.
- if (m_peventsourceFinished == NULL)
- {
- m_peventsourceFinished = new EventSourceImpl();
- }
- return m_peventsourceFinished;
- };
- // Gets an interface for tweaking the sound, if supported, NULL otherwise.
- TRef<ISoundTweakable> DSVirtualSoundBuffer::GetISoundTweakable()
- {
- return this;
- };
- // Gets an interface for tweaking the sound, if supported, NULL otherwise.
- TRef<ISoundTweakable3D> DSVirtualSoundBuffer::GetISoundTweakable3D()
- {
- return NULL;
- };
- #ifdef _DEBUG
- // return a human-readable description of the object, prepending
- // strIndent to the beginning of each line.
- ZString DSVirtualSoundBuffer::DebugDump(const ZString& strIndent)
- {
- return strIndent + "DSVirtualSoundBuffer: Priority " + ZString(m_fDynamicPriority)
- + ", Age " + ZString(m_fAge)
- + ", gain " + ZString(m_fGain)
- + ", pitch " + ZString(m_fPitch) + "\n"
- + SoundDebugDump(m_pdata, strIndent + " ")
- + ((m_pds3dbuffer) ? SoundDebugDump(m_pds3dbuffer, strIndent + " ") : "");
- }
- #endif
- /////////////////////////////////////////////////////////////////////////////
- //
- // DS3DVirtualSoundBuffer
- //
- /////////////////////////////////////////////////////////////////////////////
- // constructs a simple 3D capable sound
- DS3DVirtualSoundBuffer::DS3DVirtualSoundBuffer(ISoundPCMData* pdata, bool bLooping,
- TRef<ISoundPositionSource> psource) :
- DSVirtualSoundBuffer(pdata, bLooping),
- m_pposSource(psource),
- m_b3D(false),
- m_bListenerRelative(false),
- m_bPlayingIn3D(true),
- m_fMinimumDistance(20.0f),
- m_fInnerAngle(360),
- m_fOuterAngle(360),
- m_fOutsideGain(0.0f),
- m_vectPosition(0,0,0),
- m_vectVelocity(0,0,0),
- m_vectOrientation(0,0,1)
- {
- };
- // constructs an ASR 3D capable sound
- DS3DVirtualSoundBuffer::DS3DVirtualSoundBuffer(ISoundPCMData* pdata, DWORD dwLoopOffset,
- DWORD dwLoopLength, TRef<ISoundPositionSource> psource) :
- DSVirtualSoundBuffer(pdata, dwLoopOffset, dwLoopLength),
- m_pposSource(psource),
- m_b3D(false),
- m_bListenerRelative(false),
- m_bPlayingIn3D(true),
- m_fMinimumDistance(20.0f),
- m_fInnerAngle(360),
- m_fOuterAngle(360),
- m_fOutsideGain(0.0f),
- m_vectPosition(0,0,0),
- m_vectVelocity(0,0,0),
- m_vectOrientation(0,0,1)
- {
- };
- // prepare a sound buffer with the given quality and 3D support using the
- // direct sound object pointed to by pDirectSound.
- HRESULT DS3DVirtualSoundBuffer::PrepareBuffer(IDirectSound* pDirectSound,
- ISoundEngine::Quality quality, bool bAllowHardware, bool bSupport3D)
- {
- HRESULT hr;
- // If the old and new quality are not the same, we need a new buffer
- // because the 3D quality is set on a per-buffer basis.
- if (quality != m_quality || m_bAllowHardware != bAllowHardware)
- m_pds3dbuffer = NULL;
- // do all of the 2D buffer creation stuff.
- hr = DSVirtualSoundBuffer::PrepareBuffer(pDirectSound, quality, bAllowHardware, true);
- if (FAILED(hr)) return hr;
- // update the playing sound's 3D state, as needed.
- hr = m_pds3dbuffer->UpdateState3D(
- m_vectPosition, m_vectVelocity, m_vectOrientation,
- m_fMinimumDistance,
- m_fInnerAngle, m_fOuterAngle, m_fOutsideGain,
- m_bPlayingIn3D,
- m_bListenerRelative,
- false
- );
- if (ZFailed(hr)) return hr;
- return S_OK;
- };
- // Recalculates the sounds position, loudness, whether it's playing, etc..
- HRESULT DS3DVirtualSoundBuffer::Update(DWORD dwTimeElapsed,
- const Vector& vectListenerPosition, float fRolloffFactor)
- {
- HRESULT hr;
- // if the source no longer exists, stop the sound.
- hr = m_pposSource->IsPlaying();
- if (ZFailed(hr)) return hr;
- bool bSourceIsValid = hr == S_OK;
- if (!bSourceIsValid)
- {
- Stop(true);
- }
- // most of what DSVirtualSoundBuffer does is perfectly fine
- hr = DSVirtualSoundBuffer::Update(dwTimeElapsed, vectListenerPosition,
- fRolloffFactor);
- if (ZFailed(hr)) return hr;
- if (bSourceIsValid)
- {
- // get the position of the source.
- hr = m_pposSource->GetPosition(m_vectPosition);
- if (ZFailed(hr)) return hr;
- // find out whether the position is listener relative
- hr = m_pposSource->IsListenerRelative();
- if (ZFailed(hr)) return hr;
- m_bListenerRelative = hr == S_OK;
- // optimization: don't do 3D processing if the source position is
- // identical to the listener's position.
- m_bPlayingIn3D = m_b3D
- && m_vectPosition
- != (m_bListenerRelative ? Vector(0,0,0) : vectListenerPosition);
- if (m_bPlayingIn3D)
- {
- // get the velocity of the source
- hr = m_pposSource->GetVelocity(m_vectVelocity);
- if (ZFailed(hr)) return hr;
- // get the position of the listener relative to this source
- Vector vectRelListener = m_bListenerRelative
- ? -m_vectPosition : (vectListenerPosition - m_vectPosition);
- // get the distance to the listener
- float fDistanceSquared = vectRelListener.LengthSquared();
-
- // calculate some useful constants
- float fMinimumDistanceSquared = m_fMinimumDistance * m_fMinimumDistance;
- float fMaximumDistanceSquared = fMinimumDistanceSquared
- * c_fMinToMaxDistanceRatio * c_fMinToMaxDistanceRatio;
-
- // if we are outside of the maximum distance for this sound
- if (fDistanceSquared > fMaximumDistanceSquared || !m_bAudible)
- {
- // this sound is silent
- m_bAudible = false;
- m_fDynamicPriority += -100;
- }
- else
- {
- // calculate how much softer the sound is (in dB) based on distance
- float fDistanceGain = min(0.0f, (float)(
- fRolloffFactor * -10 * log(fDistanceSquared/fMinimumDistanceSquared)
- ));
- // if this has a sound cone
- float fConeGain = 0;
- if (m_fOutsideGain != 0.0f && m_fInnerAngle != 360
- && !m_bListenerRelative) // TODO: HACK: we don't have the info
- // to do the right thing for listener
- // relative sounds yet.
- {
- const float fRadiansToDegrees = 57.2957795f;
- // get the orientation of the source
- hr = m_pposSource->GetOrientation(m_vectOrientation);
- if (ZFailed(hr)) return hr;
- ZAssertIsUnitVector(m_vectOrientation);
- // calculate the angle between the source and the listener
- // (using the identity v1 * v2 = |v1||v2|cos(angle) )
- float fPhi = (float)acos(m_vectOrientation * vectRelListener
- / sqrt(fDistanceSquared)) * fRadiansToDegrees;
- // adjust the cone attenuation to reflect this.
- if (fPhi > m_fInnerAngle)
- {
- if (fPhi < m_fOuterAngle)
- {
- // do a linear fade between the outside and inside
- // gains.
- fConeGain = m_fOutsideGain
- * (fPhi - m_fInnerAngle)
- / (m_fOuterAngle - m_fInnerAngle);
- }
- else
- {
- fConeGain = m_fOutsideGain;
- }
- }
- }
- float fTotalGain = m_fGain + fDistanceGain + fConeGain;
- // update the audibility
- m_bAudible = fTotalGain > c_fMinAudible;
- // add in the distance and cone attenuations to the priority
- m_fDynamicPriority += fDistanceGain + fConeGain;
- }
- }
- };
-
- // if we have a buffer...
- if (m_bBufferPlaying)
- {
- // update the playing sound's 3D state, as needed.
- hr = m_pds3dbuffer->UpdateState3D(
- m_vectPosition, m_vectVelocity, m_vectOrientation,
- m_fMinimumDistance,
- m_fInnerAngle, m_fOuterAngle, m_fOutsideGain,
- m_bPlayingIn3D,
- m_bListenerRelative
- );
- if (ZFailed(hr)) return hr;
- }
- return S_OK;
- }
- // toggles 3D Positioning on and off for the given sound.
- HRESULT DS3DVirtualSoundBuffer::Set3D(bool b3D)
- {
- m_b3D = b3D;
- return S_OK;
- };
- // Sets the distance at which the sound will be at max volume. This
- // effects how quickly the sound drops off with distance.
- HRESULT DS3DVirtualSoundBuffer::SetMinimumDistance(float fMinimumDistance)
- {
- // Any distance greater than 0 is OK.
- if (fMinimumDistance <= 0)
- {
- ZAssert(false);
- return E_INVALIDARG;
- }
- m_fMinimumDistance = fMinimumDistance;
-
- return S_OK;
- };
- // Sets a sound cone of size fInnerAngle (in degrees) where the volume is at
- // normal levels, outside of which it fades down by fOutsideGain
- // (range of 0 to -100 db) at fOuterAngle (degrees) and beyond.
- HRESULT DS3DVirtualSoundBuffer::SetCone(float fInnerAngle, float fOuterAngle, float fOutsideGain)
- {
- // check the parameters
- if ((fInnerAngle < 0 || fInnerAngle > 360)
- || (fOuterAngle < 0 || fOuterAngle > 360)
- || (fOuterAngle < fInnerAngle)
- || (fOutsideGain < -100 || fOutsideGain > 0)
- )
- {
- ZAssert(false);
- return E_INVALIDARG;
- };
- m_fInnerAngle = fInnerAngle;
- m_fOuterAngle = fOuterAngle;
- m_fOutsideGain = fOutsideGain;
- return S_OK;
- };
- // Sets the gain, from 0 to -100 dB
- HRESULT DS3DVirtualSoundBuffer::SetGain(float fGain)
- {
- return DSVirtualSoundBuffer::SetGain(fGain);
- };
- // Sets the pitch shift, where 1.0 is normal, 0.5 is half of normal speed,
- // and 2.0 is twice normal speed.
- HRESULT DS3DVirtualSoundBuffer::SetPitch(float fPitch)
- {
- return DSVirtualSoundBuffer::SetPitch(fPitch);
- };
- // sets the priority - used as a addition to volume when choosing which
- // sounds are most important to play.
- HRESULT DS3DVirtualSoundBuffer::SetPriority(float fPriority)
- {
- return DSVirtualSoundBuffer::SetPriority(fPriority);
- };
- // Gets an interface for tweaking the sound, if supported, NULL otherwise.
- TRef<ISoundTweakable> DS3DVirtualSoundBuffer::GetISoundTweakable()
- {
- return DSVirtualSoundBuffer::GetISoundTweakable();
- };
- // Gets an interface for tweaking the sound, if supported, NULL otherwise.
- TRef<ISoundTweakable3D> DS3DVirtualSoundBuffer::GetISoundTweakable3D()
- {
- return this;
- };
- };
|