mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
202 lines
6.8 KiB
C++
202 lines
6.8 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/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;
|
|
}
|