123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- //-----------------------------------------------------------------------------
- // 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 "platform/platform.h"
- #include "sfx/openal/sfxALVoice.h"
- #include "sfx/openal/sfxALBuffer.h"
- #include "sfx/openal/sfxALDevice.h"
- #ifdef TORQUE_DEBUG
- # define AL_SANITY_CHECK() \
- AssertFatal( mOpenAL.alIsSource( mSourceName ), "AL Source Sanity Check Failed!" );
- #else
- # define AL_SANITY_CHECK()
- #endif
- //#define DEBUG_SPEW
- SFXALVoice* SFXALVoice::create( SFXALDevice* device, SFXALBuffer *buffer )
- {
- AssertFatal( buffer, "SFXALVoice::create() - Got null buffer!" );
-
- ALuint sourceName;
- device->mOpenAL.alGenSources( 1, &sourceName );
- AssertFatal( device->mOpenAL.alIsSource( sourceName ), "AL Source Sanity Check Failed!" );
- // Is this 3d?
- // Okay, this looks odd, but bear with me for a moment. AL_SOURCE_RELATIVE does NOT indicate
- // whether or not the volume of the sound should change depending on the position of the listener.
- // OpenAL assumes that the volume will ALWAYS depend on the position of the listener. What AL_SOURCE_RELATIVE
- // does do is dictate if the position of THIS SOURCE is relative to the listener. If AL_SOURCE_RELATIVE is AL_TRUE
- // and the source's position is 0, 0, 0, then the source is directly on top of the listener at all times, which is what
- // we want for non-3d sounds.
- device->mOpenAL.alSourcei( sourceName, AL_SOURCE_RELATIVE, ( buffer->mIs3d ? AL_FALSE : AL_TRUE ) );
-
- if( buffer->mIs3d )
- device->mOpenAL.alSourcef( sourceName, AL_ROLLOFF_FACTOR, device->mRolloffFactor );
- SFXALVoice *voice = new SFXALVoice( device->mOpenAL,
- buffer,
- sourceName );
- return voice;
- }
- SFXALVoice::SFXALVoice( const OPENALFNTABLE &oalft,
- SFXALBuffer *buffer,
- ALuint sourceName )
- : Parent( buffer ),
- mSourceName( sourceName ),
- mResumeAtSampleOffset( -1.0f ),
- mSampleOffset( 0 ),
- mOpenAL( oalft )
- {
- AL_SANITY_CHECK();
- }
- SFXALVoice::~SFXALVoice()
- {
- mOpenAL.alDeleteSources( 1, &mSourceName );
- }
- void SFXALVoice::_lateBindStaticBufferIfNecessary()
- {
- if( !mBuffer->isStreaming() )
- {
- ALint bufferId;
- mOpenAL.alGetSourcei( mSourceName, AL_BUFFER, &bufferId );
- if( !bufferId )
- mOpenAL.alSourcei( mSourceName, AL_BUFFER, _getBuffer()->mALBuffer );
- }
- }
- SFXStatus SFXALVoice::_status() const
- {
- AL_SANITY_CHECK();
- ALint state;
- mOpenAL.alGetSourcei( mSourceName, AL_SOURCE_STATE, &state );
- switch( state )
- {
- case AL_PLAYING: return SFXStatusPlaying;
- case AL_PAUSED: return SFXStatusPaused;
- default: return SFXStatusStopped;
- }
- }
- void SFXALVoice::_play()
- {
- AL_SANITY_CHECK();
- _lateBindStaticBufferIfNecessary();
- #ifdef DEBUG_SPEW
- Platform::outputDebugString( "[SFXALVoice] Starting playback" );
- #endif
- #if defined(AL_ALEXT_PROTOTYPES)
- //send every voice that plays to the alauxiliary slot that has the reverb
- mOpenAL.alSource3i(mSourceName, AL_AUXILIARY_SEND_FILTER, 1, 0, AL_FILTER_NULL);
- #endif
- mOpenAL.alSourcePlay( mSourceName );
-
- //WORKAROUND: Adjust play cursor for buggy OAL when resuming playback. Do this after alSourcePlay
- // as it is the play function that will cause the cursor to jump.
-
- if( mResumeAtSampleOffset != -1.0f )
- {
- mOpenAL.alSourcef( mSourceName, AL_SAMPLE_OFFSET, mResumeAtSampleOffset );
- mResumeAtSampleOffset = -1.0f;
- }
- }
- void SFXALVoice::_pause()
- {
- AL_SANITY_CHECK();
- #ifdef DEBUG_SPEW
- Platform::outputDebugString( "[SFXALVoice] Pausing playback" );
- #endif
- mOpenAL.alSourcePause( mSourceName );
-
- //WORKAROUND: Another workaround for buggy OAL. Resuming playback of a paused source will cause the
- // play cursor to jump. Save the cursor so we can manually move it into position in _play(). Sigh.
-
- mOpenAL.alGetSourcef( mSourceName, AL_SAMPLE_OFFSET, &mResumeAtSampleOffset );
- }
- void SFXALVoice::_stop()
- {
- AL_SANITY_CHECK();
-
- #ifdef DEBUG_SPEW
- Platform::outputDebugString( "[SFXALVoice] Stopping playback" );
- #endif
- mOpenAL.alSourceStop( mSourceName );
- mSampleOffset = 0;
-
- mResumeAtSampleOffset = -1.0f;
- }
- void SFXALVoice::_seek( U32 sample )
- {
- AL_SANITY_CHECK();
-
- _lateBindStaticBufferIfNecessary();
- mOpenAL.alSourcei( mSourceName, AL_SAMPLE_OFFSET, sample );
- mResumeAtSampleOffset = -1.0f;
- }
- U32 SFXALVoice::_tell() const
- {
- // Flush processed buffers as AL_SAMPLE_OFFSET will snap back to zero as soon
- // as the queue is processed in whole.
- if( mBuffer->isStreaming() )
- mBuffer->write( NULL, 0 );
- ALint pos;
- mOpenAL.alGetSourcei( mSourceName, AL_SAMPLE_OFFSET, &pos );
- return ( pos + mSampleOffset );
- }
- void SFXALVoice::setMinMaxDistance( F32 min, F32 max )
- {
- AL_SANITY_CHECK();
- mOpenAL.alSourcef( mSourceName, AL_REFERENCE_DISTANCE, min );
- mOpenAL.alSourcef( mSourceName, AL_MAX_DISTANCE, max );
- }
- void SFXALVoice::play( bool looping )
- {
- AL_SANITY_CHECK();
- mOpenAL.alSourceStop( mSourceName );
- if( !mBuffer->isStreaming() )
- mOpenAL.alSourcei( mSourceName, AL_LOOPING, ( looping ? AL_TRUE : AL_FALSE ) );
- Parent::play( looping );
- }
- void SFXALVoice::setVelocity( const VectorF& velocity )
- {
- AL_SANITY_CHECK();
- // Torque and OpenAL are both right handed
- // systems, so no coordinate flipping is needed.
- mOpenAL.alSourcefv( mSourceName, AL_VELOCITY, velocity );
- }
- void SFXALVoice::setTransform( const MatrixF& transform )
- {
- AL_SANITY_CHECK();
- // Torque and OpenAL are both right handed
- // systems, so no coordinate flipping is needed.
- Point3F pos, dir;
- transform.getColumn( 3, &pos );
- transform.getColumn( 1, &dir );
- mOpenAL.alSourcefv( mSourceName, AL_POSITION, pos );
- mOpenAL.alSourcefv( mSourceName, AL_DIRECTION, dir );
- }
- void SFXALVoice::setVolume( F32 volume )
- {
- AL_SANITY_CHECK();
- mOpenAL.alSourcef( mSourceName, AL_GAIN, volume );
- }
- void SFXALVoice::setPitch( F32 pitch )
- {
- AL_SANITY_CHECK();
- mOpenAL.alSourcef( mSourceName, AL_PITCH, pitch );
- }
- void SFXALVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume )
- {
- AL_SANITY_CHECK();
- mOpenAL.alSourcef( mSourceName, AL_CONE_INNER_ANGLE, innerAngle );
- mOpenAL.alSourcef( mSourceName, AL_CONE_OUTER_ANGLE, outerAngle );
- mOpenAL.alSourcef( mSourceName, AL_CONE_OUTER_GAIN, outerVolume );
- }
- void SFXALVoice::setRolloffFactor( F32 factor )
- {
- mOpenAL.alSourcef( mSourceName, AL_ROLLOFF_FACTOR, factor );
- }
|