mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
230 lines
6.9 KiB
C++
230 lines
6.9 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "sfx/dsound/sfxDSVoice.h"
|
|
#include "sfx/dsound/sfxDSDevice.h"
|
|
#include "core/util/safeRelease.h"
|
|
|
|
|
|
SFXDSVoice* SFXDSVoice::create( SFXDSDevice *device, SFXDSBuffer *buffer )
|
|
{
|
|
AssertFatal( buffer, "SFXDSVoice::create() - Got null buffer!" );
|
|
|
|
IDirectSoundBuffer8 *dsBuffer8 = NULL;
|
|
if ( !buffer->createVoice( &dsBuffer8 ) || !dsBuffer8 )
|
|
return NULL;
|
|
|
|
// Now try to grab a 3D interface... if we don't
|
|
// get one its probably because its not a 3d sound.
|
|
IDirectSound3DBuffer8* dsBuffer3d8 = NULL;
|
|
dsBuffer8->QueryInterface( IID_IDirectSound3DBuffer8, (LPVOID*)&dsBuffer3d8 );
|
|
|
|
// Create the voice and return!
|
|
SFXDSVoice* voice = new SFXDSVoice( device,
|
|
buffer,
|
|
dsBuffer8,
|
|
dsBuffer3d8 );
|
|
|
|
// Now set the voice to a default state.
|
|
// The buffer from which we have duplicated may have been assigned different
|
|
// properties and we don't want to inherit these.
|
|
|
|
voice->setVolume( 1.0 );
|
|
voice->setPitch( 1.0 );
|
|
|
|
return voice;
|
|
}
|
|
|
|
SFXDSVoice::SFXDSVoice( SFXDSDevice *device,
|
|
SFXDSBuffer *buffer,
|
|
IDirectSoundBuffer8 *dsBuffer,
|
|
IDirectSound3DBuffer8 *dsBuffer3d )
|
|
: Parent( buffer ),
|
|
mDevice( device ),
|
|
mDSBuffer( dsBuffer ),
|
|
mDSBuffer3D( dsBuffer3d ),
|
|
mIsLooping( false )
|
|
{
|
|
AssertFatal( mDevice, "SFXDSVoice::SFXDSVoice() - SFXDSDevice is null!" );
|
|
AssertFatal( mBuffer, "SFXDSVoice::SFXDSVoice() - SFXDSBuffer is null!" );
|
|
AssertFatal( mDSBuffer, "SFXDSVoice::SFXDSVoice() - Dsound buffer is null!" );
|
|
}
|
|
|
|
SFXDSVoice::~SFXDSVoice()
|
|
{
|
|
SAFE_RELEASE( mDSBuffer3D );
|
|
|
|
SFXDSBuffer* dsBuffer = _getBuffer();
|
|
if( dsBuffer )
|
|
dsBuffer->releaseVoice( &mDSBuffer );
|
|
|
|
mBuffer = NULL;
|
|
}
|
|
|
|
SFXStatus SFXDSVoice::_status() const
|
|
{
|
|
DWORD status = 0;
|
|
mDSBuffer->GetStatus( &status );
|
|
|
|
if ( status & DSBSTATUS_PLAYING )
|
|
return SFXStatusPlaying;
|
|
else
|
|
return SFXStatusStopped;
|
|
}
|
|
|
|
void SFXDSVoice::_play()
|
|
{
|
|
DSAssert( mDSBuffer->Play( 0, 0, mIsLooping ? DSBPLAY_LOOPING : 0 ),
|
|
"SFXDSVoice::_play() - Playback failed!" );
|
|
}
|
|
|
|
void SFXDSVoice::_stop()
|
|
{
|
|
DSAssert( mDSBuffer->Stop(), "SFXDSVoice::pause - stop failed!" );
|
|
mDSBuffer->SetCurrentPosition( 0 );
|
|
}
|
|
|
|
void SFXDSVoice::_pause()
|
|
{
|
|
DSAssert( mDSBuffer->Stop(), "SFXDSVoice::pause - stop failed!" );
|
|
}
|
|
|
|
void SFXDSVoice::_seek( U32 sample )
|
|
{
|
|
U32 pos = mBuffer->getFormat().getBytesPerSample() * sample;
|
|
mDSBuffer->SetCurrentPosition( pos );
|
|
}
|
|
|
|
U32 SFXDSVoice::_tell() const
|
|
{
|
|
DWORD position = 0;
|
|
mDSBuffer->GetCurrentPosition( &position, NULL );
|
|
U32 samplePos = _getBuffer()->getSamplePos( position );
|
|
return samplePos;
|
|
}
|
|
|
|
void SFXDSVoice::setMinMaxDistance( F32 min, F32 max )
|
|
{
|
|
if ( !mDSBuffer3D )
|
|
return;
|
|
|
|
mDSBuffer3D->SetMinDistance( min, DS3D_DEFERRED );
|
|
mDSBuffer3D->SetMaxDistance( max, DS3D_DEFERRED );
|
|
}
|
|
|
|
void SFXDSVoice::play( bool looping )
|
|
{
|
|
// If this is a 3d sound then we need
|
|
// to commit any deferred settings before
|
|
// we start playback else we can get some
|
|
// glitches.
|
|
|
|
if ( mDSBuffer3D )
|
|
mDevice->_commitDeferred();
|
|
|
|
// If this is a streaming buffer,
|
|
// force looping.
|
|
|
|
const bool isStreaming = mBuffer->isStreaming();
|
|
if( isStreaming )
|
|
looping = true;
|
|
mIsLooping = looping;
|
|
|
|
Parent::play( looping );
|
|
}
|
|
|
|
void SFXDSVoice::setVelocity( const VectorF& velocity )
|
|
{
|
|
if ( !mDSBuffer3D )
|
|
return;
|
|
|
|
DSAssert( mDSBuffer3D->SetVelocity( velocity.x, velocity.z, velocity.y, DS3D_DEFERRED ),
|
|
"SFXDSVoice::setVelocity - couldn't update buffer!" );
|
|
}
|
|
|
|
void SFXDSVoice::setTransform( const MatrixF& transform )
|
|
{
|
|
if ( !mDSBuffer3D )
|
|
return;
|
|
|
|
Point3F pos, dir;
|
|
transform.getColumn( 3, &pos );
|
|
transform.getColumn( 1, &dir );
|
|
DSAssert( mDSBuffer3D->SetPosition( pos.x, pos.z, pos.y, DS3D_DEFERRED ),
|
|
"SFXDSVoice::setTransform - couldn't set position of the buffer." );
|
|
|
|
DSAssert( mDSBuffer3D->SetConeOrientation( dir.x, dir.z, dir.y, DS3D_DEFERRED ),
|
|
"SFXDSVoice::setTransform - couldn't set cone orientation of the buffer." );
|
|
}
|
|
|
|
/// Helper for converting floating point linear volume
|
|
/// to a logrithmic integer volume for dsound.
|
|
LONG SFXDSVoice::_linearToLogVolume( F32 linVolume )
|
|
{
|
|
LONG logVolume;
|
|
|
|
if ( linVolume <= 0.0f )
|
|
logVolume = DSBVOLUME_MIN;
|
|
else
|
|
{
|
|
logVolume = -2000.0 * mLog( 1.0f / linVolume );
|
|
logVolume = mClamp( logVolume, DSBVOLUME_MIN, DSBVOLUME_MAX );
|
|
}
|
|
|
|
return logVolume;
|
|
}
|
|
|
|
void SFXDSVoice::setVolume( F32 volume )
|
|
{
|
|
LONG logVolume = _linearToLogVolume( volume );
|
|
|
|
HRESULT hr = mDSBuffer->SetVolume( logVolume );
|
|
DSAssert( hr, "SFXDSVoice::setVolume - couldn't set volume!" );
|
|
}
|
|
|
|
void SFXDSVoice::setPitch( F32 pitch )
|
|
{
|
|
F32 sampleRate = _getBuffer()->getFormat().getSamplesPerSecond();
|
|
F32 frequency = mFloor( mClampF( sampleRate * pitch, DSBFREQUENCY_MIN, DSBFREQUENCY_MAX ) );
|
|
|
|
DSAssert( mDSBuffer->SetFrequency( ( U32 )frequency ),
|
|
"SFXDSVoice::setPitch - couldn't set playback frequency.");
|
|
}
|
|
|
|
void SFXDSVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume )
|
|
{
|
|
if ( !mDSBuffer3D )
|
|
return;
|
|
|
|
DSAssert( mDSBuffer3D->SetConeAngles( innerAngle,
|
|
outerAngle,
|
|
DS3D_DEFERRED ),
|
|
"SFXDSVoice::setCone - couldn't set cone angles!" );
|
|
|
|
|
|
LONG logVolume = _linearToLogVolume( outerVolume );
|
|
|
|
DSAssert( mDSBuffer3D->SetConeOutsideVolume( logVolume,
|
|
DS3D_DEFERRED ),
|
|
"SFXDSVoice::setCone - couldn't set cone outside volume!" );
|
|
}
|