123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- //-----------------------------------------------------------------------------
- // 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/openal/sfxALDevice.h"
- #include "sfx/openal/sfxALBuffer.h"
- #include "platform/async/asyncUpdate.h"
- //-----------------------------------------------------------------------------
- SFXALDevice::SFXALDevice( SFXProvider *provider,
- const OPENALFNTABLE &openal,
- String name,
- bool useHardware,
- S32 maxBuffers )
- : Parent( name, provider, useHardware, maxBuffers ),
- mOpenAL( openal ),
- mDevice( NULL ),
- mContext( NULL ),
- mRolloffFactor( 1.0f )
- {
- mMaxBuffers = getMax( maxBuffers, 8 );
- // TODO: The OpenAL device doesn't set the primary buffer
- // $pref::SFX::frequency or $pref::SFX::bitrate!
- mDevice = mOpenAL.alcOpenDevice( name );
- mOpenAL.alcGetError( mDevice );
- if( mDevice )
- {
- mContext = mOpenAL.alcCreateContext( mDevice, NULL );
- if( mContext )
- mOpenAL.alcMakeContextCurrent( mContext );
- U32 err = mOpenAL.alcGetError( mDevice );
-
- if( err != ALC_NO_ERROR )
- Con::errorf( "SFXALDevice - Initialization Error: %s", mOpenAL.alcGetString( mDevice, err ) );
- }
- AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" );
- // Start the update thread.
- #ifndef TORQUE_OS_LINUX
- if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
- {
- SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread
- ( "OpenAL Update Thread", SFXInternal::gBufferUpdateList,
- Con::getIntVariable( "$pref::SFX::updateInterval", SFXInternal::DEFAULT_UPDATE_INTERVAL ) );
- SFXInternal::gUpdateThread->start();
- }
- #endif
- }
- //-----------------------------------------------------------------------------
- SFXALDevice::~SFXALDevice()
- {
- _releaseAllResources();
- mOpenAL.alcMakeContextCurrent( NULL );
- mOpenAL.alcDestroyContext( mContext );
- mOpenAL.alcCloseDevice( mDevice );
- }
- //-----------------------------------------------------------------------------
- SFXBuffer* SFXALDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description )
- {
- AssertFatal( stream, "SFXALDevice::createBuffer() - Got null stream!" );
- AssertFatal( description, "SFXALDevice::createBuffer() - Got null description!" );
- SFXALBuffer* buffer = SFXALBuffer::create( mOpenAL,
- stream,
- description,
- mUseHardware );
- if ( !buffer )
- return NULL;
- _addBuffer( buffer );
- return buffer;
- }
- //-----------------------------------------------------------------------------
- SFXVoice* SFXALDevice::createVoice( bool is3D, SFXBuffer *buffer )
- {
- // Don't bother going any further if we've
- // exceeded the maximum voices.
- if ( mVoices.size() >= mMaxBuffers )
- return NULL;
- AssertFatal( buffer, "SFXALDevice::createVoice() - Got null buffer!" );
- SFXALBuffer* alBuffer = dynamic_cast<SFXALBuffer*>( buffer );
- AssertFatal( alBuffer, "SFXALDevice::createVoice() - Got bad buffer!" );
- SFXALVoice* voice = SFXALVoice::create( this, alBuffer );
- if ( !voice )
- return NULL;
- _addVoice( voice );
- return voice;
- }
- //-----------------------------------------------------------------------------
- void SFXALDevice::setListener( U32 index, const SFXListenerProperties& listener )
- {
- if( index != 0 )
- return;
- // Torque and OpenAL are both right handed
- // systems, so no coordinate flipping is needed.
- const MatrixF &transform = listener.getTransform();
- Point3F pos, tupple[2];
- transform.getColumn( 3, &pos );
- transform.getColumn( 1, &tupple[0] );
- transform.getColumn( 2, &tupple[1] );
- const VectorF &velocity = listener.getVelocity();
- mOpenAL.alListenerfv( AL_POSITION, pos );
- mOpenAL.alListenerfv( AL_VELOCITY, velocity );
- mOpenAL.alListenerfv( AL_ORIENTATION, (const F32 *)&tupple[0] );
- }
- //-----------------------------------------------------------------------------
- void SFXALDevice::setDistanceModel( SFXDistanceModel model )
- {
- switch( model )
- {
- case SFXDistanceModelLinear:
- mOpenAL.alDistanceModel( AL_LINEAR_DISTANCE_CLAMPED );
- if( mRolloffFactor != 1.0f )
- _setRolloffFactor( 1.0f ); // No rolloff on linear.
- break;
-
- case SFXDistanceModelLogarithmic:
- mOpenAL.alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
- if( mUserRolloffFactor != mRolloffFactor )
- _setRolloffFactor( mUserRolloffFactor );
- break;
-
- default:
- AssertWarn( false, "SFXALDevice::setDistanceModel - distance model not implemented" );
- }
-
- mDistanceModel = model;
- }
- //-----------------------------------------------------------------------------
- void SFXALDevice::setDopplerFactor( F32 factor )
- {
- mOpenAL.alDopplerFactor( factor );
- }
- //-----------------------------------------------------------------------------
- void SFXALDevice::_setRolloffFactor( F32 factor )
- {
- mRolloffFactor = factor;
-
- for( U32 i = 0, num = mVoices.size(); i < num; ++ i )
- mOpenAL.alSourcef( ( ( SFXALVoice* ) mVoices[ i ] )->mSourceName, AL_ROLLOFF_FACTOR, factor );
- }
- //-----------------------------------------------------------------------------
- void SFXALDevice::setRolloffFactor( F32 factor )
- {
- if( mDistanceModel == SFXDistanceModelLinear && factor != 1.0f )
- Con::errorf( "SFXALDevice::setRolloffFactor - rolloff factor <> 1.0f ignored in linear distance model" );
- else
- _setRolloffFactor( factor );
-
- mUserRolloffFactor = factor;
- }
|