2009-08-09 21:16:39 +00:00
/*
2011-02-18 23:47:37 +00:00
* * * * * * BEGIN GPL LICENSE BLOCK * * * * *
2009-08-09 21:16:39 +00:00
*
2011-02-18 23:47:37 +00:00
* Copyright 2009 - 2011 Jörg Hermann Müller
2009-08-09 21:16:39 +00:00
*
* This file is part of AudaSpace .
*
2011-02-18 23:47:37 +00:00
* Audaspace is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
2009-08-09 21:16:39 +00:00
* ( at your option ) any later version .
*
* AudaSpace is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2011-02-18 23:47:37 +00:00
* GNU General Public License for more details .
2009-08-09 21:16:39 +00:00
*
2011-02-18 23:47:37 +00:00
* You should have received a copy of the GNU General Public License
* along with Audaspace ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2009-08-09 21:16:39 +00:00
*
2011-02-18 23:47:37 +00:00
* * * * * * END GPL LICENSE BLOCK * * * * *
2009-08-09 21:16:39 +00:00
*/
2011-02-25 10:21:56 +00:00
/** \file audaspace/OpenAL/AUD_OpenALDevice.cpp
* \ ingroup audopenal
*/
2009-08-09 21:16:39 +00:00
# include "AUD_OpenALDevice.h"
2010-07-28 09:36:03 +00:00
# include "AUD_IFactory.h"
2009-08-09 21:16:39 +00:00
# include "AUD_IReader.h"
2010-07-28 09:36:03 +00:00
# include "AUD_ConverterReader.h"
2012-10-24 21:33:44 +00:00
# include "AUD_MutexLock.h"
2009-08-09 21:16:39 +00:00
# include <cstring>
# include <limits>
# ifdef WIN32
# include <windows.h>
# else
# include <unistd.h>
# endif
2011-06-21 20:21:43 +00:00
/*struct AUD_OpenALBufferedFactory
{
/// The factory.
AUD_IFactory * factory ;
/// The OpenAL buffer.
ALuint buffer ;
} ; */
//typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
/******************************************************************************/
/*********************** AUD_OpenALHandle Handle Code *************************/
/******************************************************************************/
static const char * genbuffer_error = " AUD_OpenALDevice: Buffer couldn't be "
" generated. " ;
static const char * gensource_error = " AUD_OpenALDevice: Source couldn't be "
" generated. " ;
static const char * queue_error = " AUD_OpenALDevice: Buffer couldn't be "
" queued to the source. " ;
static const char * bufferdata_error = " AUD_OpenALDevice: Buffer couldn't be "
" filled with data. " ;
2009-08-09 21:16:39 +00:00
2013-08-14 21:21:00 +00:00
bool AUD_OpenALDevice : : AUD_OpenALHandle : : pause ( bool keep )
{
if ( m_status )
{
AUD_MutexLock lock ( * m_device ) ;
if ( m_status = = AUD_STATUS_PLAYING )
{
for ( AUD_HandleIterator it = m_device - > m_playingSounds . begin ( ) ; it ! = m_device - > m_playingSounds . end ( ) ; it + + )
{
if ( it - > get ( ) = = this )
{
boost : : shared_ptr < AUD_OpenALHandle > This = * it ;
m_device - > m_playingSounds . erase ( it ) ;
m_device - > m_pausedSounds . push_back ( This ) ;
alSourcePause ( m_source ) ;
m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED ;
return true ;
}
}
}
}
return false ; }
2012-11-05 14:24:35 +00:00
AUD_OpenALDevice : : AUD_OpenALHandle : : AUD_OpenALHandle ( AUD_OpenALDevice * device , ALenum format , boost : : shared_ptr < AUD_IReader > reader , bool keep ) :
2011-06-21 20:21:43 +00:00
m_isBuffered ( false ) , m_reader ( reader ) , m_keep ( keep ) , m_format ( format ) , m_current ( 0 ) ,
m_eos ( false ) , m_loopcount ( 0 ) , m_stop ( NULL ) , m_stop_data ( NULL ) , m_status ( AUD_STATUS_PLAYING ) ,
m_device ( device )
2009-08-09 21:16:39 +00:00
{
2011-06-21 20:21:43 +00:00
AUD_DeviceSpecs specs = m_device - > m_specs ;
specs . specs = m_reader - > getSpecs ( ) ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
// OpenAL playback code
alGenBuffers ( CYCLE_BUFFERS , m_buffers ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , genbuffer_error ) ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
try
{
m_device - > m_buffer . assureSize ( m_device - > m_buffersize * AUD_DEVICE_SAMPLE_SIZE ( specs ) ) ;
int length ;
bool eos ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
for ( int i = 0 ; i < CYCLE_BUFFERS ; i + + )
{
length = m_device - > m_buffersize ;
reader - > read ( length , eos , m_device - > m_buffer . getBuffer ( ) ) ;
2013-11-07 23:40:06 +00:00
if ( length = = 0 )
{
// AUD_XXX: TODO: don't fill all buffers and enqueue them later
length = 1 ;
memset ( m_device - > m_buffer . getBuffer ( ) , 0 , length * AUD_DEVICE_SAMPLE_SIZE ( specs ) ) ;
}
2011-06-21 20:21:43 +00:00
alBufferData ( m_buffers [ i ] , m_format , m_device - > m_buffer . getBuffer ( ) ,
length * AUD_DEVICE_SAMPLE_SIZE ( specs ) ,
specs . rate ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , bufferdata_error ) ;
}
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
alGenSources ( 1 , & m_source ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , gensource_error ) ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
try
{
2013-11-07 23:40:06 +00:00
alSourceQueueBuffers ( m_source , CYCLE_BUFFERS , m_buffers ) ;
2011-06-21 20:21:43 +00:00
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , queue_error ) ;
}
catch ( AUD_Exception & )
{
alDeleteSources ( 1 , & m_source ) ;
throw ;
}
}
catch ( AUD_Exception & )
{
alDeleteBuffers ( CYCLE_BUFFERS , m_buffers ) ;
throw ;
}
alSourcei ( m_source , AL_SOURCE_RELATIVE , 1 ) ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : pause ( )
{
2013-08-14 21:21:00 +00:00
return pause ( false ) ;
2011-06-21 20:21:43 +00:00
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : resume ( )
2009-08-09 21:16:39 +00:00
{
2011-06-21 20:21:43 +00:00
if ( m_status )
{
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
if ( m_status = = AUD_STATUS_PAUSED )
{
2012-11-05 14:24:35 +00:00
for ( AUD_HandleIterator it = m_device - > m_pausedSounds . begin ( ) ; it ! = m_device - > m_pausedSounds . end ( ) ; it + + )
{
if ( it - > get ( ) = = this )
{
boost : : shared_ptr < AUD_OpenALHandle > This = * it ;
2011-06-21 20:21:43 +00:00
2012-11-05 14:24:35 +00:00
m_device - > m_pausedSounds . erase ( it ) ;
m_device - > m_playingSounds . push_back ( This ) ;
m_device - > start ( ) ;
m_status = AUD_STATUS_PLAYING ;
return true ;
}
}
2011-06-21 20:21:43 +00:00
}
}
return false ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : stop ( )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-11-03 09:49:49 +00:00
m_status = AUD_STATUS_INVALID ;
2011-06-21 20:21:43 +00:00
alDeleteSources ( 1 , & m_source ) ;
if ( ! m_isBuffered )
alDeleteBuffers ( CYCLE_BUFFERS , m_buffers ) ;
2012-11-03 09:49:49 +00:00
for ( AUD_HandleIterator it = m_device - > m_playingSounds . begin ( ) ; it ! = m_device - > m_playingSounds . end ( ) ; it + + )
{
if ( it - > get ( ) = = this )
{
2012-11-05 14:24:35 +00:00
boost : : shared_ptr < AUD_OpenALHandle > This = * it ;
2012-11-03 09:49:49 +00:00
m_device - > m_playingSounds . erase ( it ) ;
return true ;
}
}
for ( AUD_HandleIterator it = m_device - > m_pausedSounds . begin ( ) ; it ! = m_device - > m_pausedSounds . end ( ) ; it + + )
{
if ( it - > get ( ) = = this )
{
m_device - > m_pausedSounds . erase ( it ) ;
return true ;
}
}
return false ;
2011-06-21 20:21:43 +00:00
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : getKeep ( )
{
if ( m_status )
return m_keep ;
return false ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setKeep ( bool keep )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
m_keep = keep ;
2011-06-21 20:21:43 +00:00
return true ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : seek ( float position )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
if ( m_isBuffered )
alSourcef ( m_source , AL_SEC_OFFSET , position ) ;
else
{
m_reader - > seek ( ( int ) ( position * m_reader - > getSpecs ( ) . rate ) ) ;
m_eos = false ;
ALint info ;
alGetSourcei ( m_source , AL_SOURCE_STATE , & info ) ;
if ( info ! = AL_PLAYING )
{
if ( info = = AL_PAUSED )
alSourceStop ( m_source ) ;
alSourcei ( m_source , AL_BUFFER , 0 ) ;
m_current = 0 ;
ALenum err ;
if ( ( err = alGetError ( ) ) = = AL_NO_ERROR )
{
int length ;
AUD_DeviceSpecs specs = m_device - > m_specs ;
specs . specs = m_reader - > getSpecs ( ) ;
m_device - > m_buffer . assureSize ( m_device - > m_buffersize * AUD_DEVICE_SAMPLE_SIZE ( specs ) ) ;
for ( int i = 0 ; i < CYCLE_BUFFERS ; i + + )
{
length = m_device - > m_buffersize ;
m_reader - > read ( length , m_eos , m_device - > m_buffer . getBuffer ( ) ) ;
2013-11-07 23:40:06 +00:00
if ( length = = 0 )
{
// AUD_XXX: TODO: don't fill all buffers and enqueue them later
length = 1 ;
memset ( m_device - > m_buffer . getBuffer ( ) , 0 , length * AUD_DEVICE_SAMPLE_SIZE ( specs ) ) ;
}
2011-06-21 20:21:43 +00:00
alBufferData ( m_buffers [ i ] , m_format , m_device - > m_buffer . getBuffer ( ) ,
length * AUD_DEVICE_SAMPLE_SIZE ( specs ) , specs . rate ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
break ;
}
if ( m_loopcount ! = 0 )
m_eos = false ;
alSourceQueueBuffers ( m_source , CYCLE_BUFFERS , m_buffers ) ;
}
alSourceRewind ( m_source ) ;
}
}
2013-08-14 21:21:00 +00:00
if ( m_status = = AUD_STATUS_STOPPED )
m_status = AUD_STATUS_PAUSED ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getPosition ( )
{
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
if ( ! m_status )
return 0.0f ;
2011-06-21 20:21:43 +00:00
float position = 0.0f ;
alGetSourcef ( m_source , AL_SEC_OFFSET , & position ) ;
if ( ! m_isBuffered )
{
AUD_Specs specs = m_reader - > getSpecs ( ) ;
position + = ( m_reader - > getPosition ( ) - m_device - > m_buffersize *
CYCLE_BUFFERS ) / ( float ) specs . rate ;
}
return position ;
}
AUD_Status AUD_OpenALDevice : : AUD_OpenALHandle : : getStatus ( )
{
return m_status ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getVolume ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_GAIN , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setVolume ( float volume )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_GAIN , volume ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getPitch ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_PITCH , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setPitch ( float pitch )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_PITCH , pitch ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
int AUD_OpenALDevice : : AUD_OpenALHandle : : getLoopCount ( )
{
if ( ! m_status )
return 0 ;
return m_loopcount ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setLoopCount ( int count )
{
if ( ! m_status )
return false ;
2013-08-14 21:21:00 +00:00
if ( m_status = = AUD_STATUS_STOPPED & & ( count > m_loopcount | | count < 0 ) )
m_status = AUD_STATUS_PAUSED ;
2011-06-21 20:21:43 +00:00
m_loopcount = count ;
2013-08-14 21:21:00 +00:00
2011-06-21 20:21:43 +00:00
return true ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setStopCallback ( stopCallback callback , void * data )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
m_stop = callback ;
m_stop_data = data ;
return true ;
}
/******************************************************************************/
/********************* AUD_OpenALHandle 3DHandle Code *************************/
/******************************************************************************/
AUD_Vector3 AUD_OpenALDevice : : AUD_OpenALHandle : : getSourceLocation ( )
{
AUD_Vector3 result = AUD_Vector3 ( 0 , 0 , 0 ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
ALfloat p [ 3 ] ;
alGetSourcefv ( m_source , AL_POSITION , p ) ;
result = AUD_Vector3 ( p [ 0 ] , p [ 1 ] , p [ 2 ] ) ;
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setSourceLocation ( const AUD_Vector3 & location )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcefv ( m_source , AL_POSITION , ( ALfloat * ) location . get ( ) ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
AUD_Vector3 AUD_OpenALDevice : : AUD_OpenALHandle : : getSourceVelocity ( )
{
AUD_Vector3 result = AUD_Vector3 ( 0 , 0 , 0 ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
ALfloat v [ 3 ] ;
alGetSourcefv ( m_source , AL_VELOCITY , v ) ;
result = AUD_Vector3 ( v [ 0 ] , v [ 1 ] , v [ 2 ] ) ;
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setSourceVelocity ( const AUD_Vector3 & velocity )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcefv ( m_source , AL_VELOCITY , ( ALfloat * ) velocity . get ( ) ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
AUD_Quaternion AUD_OpenALDevice : : AUD_OpenALHandle : : getSourceOrientation ( )
{
2011-08-07 11:54:58 +00:00
return m_orientation ;
2011-06-21 20:21:43 +00:00
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setSourceOrientation ( const AUD_Quaternion & orientation )
{
ALfloat direction [ 3 ] ;
direction [ 0 ] = - 2 * ( orientation . w ( ) * orientation . y ( ) +
orientation . x ( ) * orientation . z ( ) ) ;
direction [ 1 ] = 2 * ( orientation . x ( ) * orientation . w ( ) -
orientation . z ( ) * orientation . y ( ) ) ;
direction [ 2 ] = 2 * ( orientation . x ( ) * orientation . x ( ) +
orientation . y ( ) * orientation . y ( ) ) - 1 ;
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
if ( ! m_status )
return false ;
alSourcefv ( m_source , AL_DIRECTION , direction ) ;
2011-06-21 20:21:43 +00:00
2011-08-07 11:54:58 +00:00
m_orientation = orientation ;
2011-06-21 20:21:43 +00:00
return true ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : isRelative ( )
{
2011-07-12 13:11:00 +00:00
int result ;
2011-06-21 20:21:43 +00:00
if ( ! m_status )
2011-07-12 13:11:00 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcei ( m_source , AL_SOURCE_RELATIVE , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setRelative ( bool relative )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcei ( m_source , AL_SOURCE_RELATIVE , relative ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getVolumeMaximum ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_MAX_GAIN , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setVolumeMaximum ( float volume )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_MAX_GAIN , volume ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getVolumeMinimum ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_MIN_GAIN , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setVolumeMinimum ( float volume )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_MIN_GAIN , volume ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getDistanceMaximum ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_MAX_DISTANCE , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setDistanceMaximum ( float distance )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_MAX_DISTANCE , distance ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getDistanceReference ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_REFERENCE_DISTANCE , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setDistanceReference ( float distance )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_REFERENCE_DISTANCE , distance ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getAttenuation ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_ROLLOFF_FACTOR , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setAttenuation ( float factor )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_ROLLOFF_FACTOR , factor ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getConeAngleOuter ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_CONE_OUTER_ANGLE , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setConeAngleOuter ( float angle )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_CONE_OUTER_ANGLE , angle ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getConeAngleInner ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_CONE_INNER_ANGLE , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setConeAngleInner ( float angle )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_CONE_INNER_ANGLE , angle ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
float AUD_OpenALDevice : : AUD_OpenALHandle : : getConeVolumeOuter ( )
{
float result = std : : numeric_limits < float > : : quiet_NaN ( ) ;
if ( ! m_status )
2012-10-24 21:33:44 +00:00
return false ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return result ;
2011-06-21 20:21:43 +00:00
2012-10-24 21:33:44 +00:00
alGetSourcef ( m_source , AL_CONE_OUTER_GAIN , & result ) ;
2011-06-21 20:21:43 +00:00
return result ;
}
bool AUD_OpenALDevice : : AUD_OpenALHandle : : setConeVolumeOuter ( float volume )
{
if ( ! m_status )
return false ;
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * m_device ) ;
2009-08-09 21:16:39 +00:00
2012-10-24 21:33:44 +00:00
if ( ! m_status )
return false ;
2009-08-09 21:16:39 +00:00
2012-10-24 21:33:44 +00:00
alSourcef ( m_source , AL_CONE_OUTER_GAIN , volume ) ;
2011-06-21 20:21:43 +00:00
return true ;
}
2009-08-09 21:16:39 +00:00
/******************************************************************************/
/**************************** Threading Code **********************************/
/******************************************************************************/
2012-09-16 00:26:36 +00:00
static void * AUD_openalRunThread ( void * device )
2009-08-09 21:16:39 +00:00
{
AUD_OpenALDevice * dev = ( AUD_OpenALDevice * ) device ;
dev - > updateStreams ( ) ;
return NULL ;
}
2011-07-23 15:59:10 +00:00
void AUD_OpenALDevice : : start ( bool join )
2009-08-09 21:16:39 +00:00
{
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * this ) ;
2009-08-09 21:16:39 +00:00
if ( ! m_playing )
{
2011-07-23 15:59:10 +00:00
if ( join )
pthread_join ( m_thread , NULL ) ;
2009-08-09 21:16:39 +00:00
pthread_attr_t attr ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_JOINABLE ) ;
pthread_create ( & m_thread , & attr , AUD_openalRunThread , this ) ;
pthread_attr_destroy ( & attr ) ;
m_playing = true ;
}
}
void AUD_OpenALDevice : : updateStreams ( )
{
2012-11-05 14:24:35 +00:00
boost : : shared_ptr < AUD_OpenALHandle > sound ;
2009-08-09 21:16:39 +00:00
int length ;
ALint info ;
2010-01-01 05:09:30 +00:00
AUD_DeviceSpecs specs = m_specs ;
2010-12-22 10:51:34 +00:00
ALCenum cerr ;
2012-11-05 14:24:35 +00:00
std : : list < boost : : shared_ptr < AUD_OpenALHandle > > stopSounds ;
std : : list < boost : : shared_ptr < AUD_OpenALHandle > > pauseSounds ;
2011-02-03 13:25:05 +00:00
AUD_HandleIterator it ;
2009-08-09 21:16:39 +00:00
while ( 1 )
{
lock ( ) ;
alcSuspendContext ( m_context ) ;
2010-12-22 10:51:34 +00:00
cerr = alcGetError ( m_device ) ;
if ( cerr = = ALC_NO_ERROR )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
// for all sounds
2011-06-21 20:21:43 +00:00
for ( it = m_playingSounds . begin ( ) ; it ! = m_playingSounds . end ( ) ; it + + )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
sound = * it ;
2009-08-09 21:16:39 +00:00
2009-09-26 20:03:01 +00:00
// is it a streamed sound?
2011-06-21 20:21:43 +00:00
if ( ! sound - > m_isBuffered )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
// check for buffer refilling
2011-06-21 20:21:43 +00:00
alGetSourcei ( sound - > m_source , AL_BUFFERS_PROCESSED , & info ) ;
2009-08-09 21:16:39 +00:00
2009-09-26 20:03:01 +00:00
if ( info )
2009-08-09 21:16:39 +00:00
{
2011-06-21 20:21:43 +00:00
specs . specs = sound - > m_reader - > getSpecs ( ) ;
2011-06-21 20:13:27 +00:00
m_buffer . assureSize ( m_buffersize * AUD_DEVICE_SAMPLE_SIZE ( specs ) ) ;
2009-08-09 21:16:39 +00:00
2009-09-26 20:03:01 +00:00
// for all empty buffers
while ( info - - )
{
// if there's still data to play back
2011-06-21 20:21:43 +00:00
if ( ! sound - > m_eos )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
// read data
length = m_buffersize ;
2011-06-21 20:21:43 +00:00
sound - > m_reader - > read ( length , sound - > m_eos , m_buffer . getBuffer ( ) ) ;
2009-09-26 20:03:01 +00:00
2010-07-31 10:03:08 +00:00
// looping necessary?
2011-06-21 20:21:43 +00:00
if ( length = = 0 & & sound - > m_loopcount )
2010-07-31 10:03:08 +00:00
{
2011-06-21 20:21:43 +00:00
if ( sound - > m_loopcount > 0 )
sound - > m_loopcount - - ;
2010-07-31 10:03:08 +00:00
2011-06-21 20:21:43 +00:00
sound - > m_reader - > seek ( 0 ) ;
2010-07-31 10:03:08 +00:00
length = m_buffersize ;
2011-06-21 20:21:43 +00:00
sound - > m_reader - > read ( length , sound - > m_eos , m_buffer . getBuffer ( ) ) ;
2010-07-31 10:03:08 +00:00
}
2011-06-21 20:21:43 +00:00
if ( sound - > m_loopcount ! = 0 )
sound - > m_eos = false ;
2011-06-21 20:14:53 +00:00
2009-09-26 20:03:01 +00:00
// read nothing?
if ( length = = 0 )
{
break ;
}
2013-11-07 23:40:06 +00:00
// unqueue buffer (warning: this might fail for slow early returning sources (none exist so far) if the buffer was not queued due to recent changes - has to be tested)
alSourceUnqueueBuffers ( sound - > m_source , 1 , & sound - > m_buffers [ sound - > m_current ] ) ;
2009-09-26 20:03:01 +00:00
ALenum err ;
if ( ( err = alGetError ( ) ) ! = AL_NO_ERROR )
{
2011-06-21 20:21:43 +00:00
sound - > m_eos = true ;
2009-09-26 20:03:01 +00:00
break ;
}
// fill with new data
2011-06-21 20:21:43 +00:00
alBufferData ( sound - > m_buffers [ sound - > m_current ] ,
sound - > m_format ,
2011-06-14 12:13:19 +00:00
m_buffer . getBuffer ( ) , length *
2010-01-01 05:09:30 +00:00
AUD_DEVICE_SAMPLE_SIZE ( specs ) ,
2009-09-26 20:03:01 +00:00
specs . rate ) ;
2010-02-07 23:41:17 +00:00
if ( ( err = alGetError ( ) ) ! = AL_NO_ERROR )
2009-09-26 20:03:01 +00:00
{
2011-06-21 20:21:43 +00:00
sound - > m_eos = true ;
2009-09-26 20:03:01 +00:00
break ;
}
// and queue again
2011-06-21 20:21:43 +00:00
alSourceQueueBuffers ( sound - > m_source , 1 ,
& sound - > m_buffers [ sound - > m_current ] ) ;
2009-09-26 20:03:01 +00:00
if ( alGetError ( ) ! = AL_NO_ERROR )
{
2011-06-21 20:21:43 +00:00
sound - > m_eos = true ;
2009-09-26 20:03:01 +00:00
break ;
}
2011-06-21 20:21:43 +00:00
sound - > m_current = ( sound - > m_current + 1 ) %
AUD_OpenALHandle : : CYCLE_BUFFERS ;
2009-08-09 21:16:39 +00:00
}
2009-09-26 20:03:01 +00:00
else
2009-08-09 21:16:39 +00:00
break ;
}
}
}
2009-09-26 20:03:01 +00:00
// check if the sound has been stopped
2011-06-21 20:21:43 +00:00
alGetSourcei ( sound - > m_source , AL_SOURCE_STATE , & info ) ;
2009-08-09 21:16:39 +00:00
2009-09-26 20:03:01 +00:00
if ( info ! = AL_PLAYING )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
// if it really stopped
2014-03-10 11:30:50 +00:00
if ( sound - > m_eos & & info ! = AL_INITIAL )
2009-09-26 20:03:01 +00:00
{
2011-06-21 20:21:43 +00:00
if ( sound - > m_stop )
sound - > m_stop ( sound - > m_stop_data ) ;
2010-08-02 18:22:34 +00:00
2009-09-26 20:03:01 +00:00
// pause or
2011-06-21 20:21:43 +00:00
if ( sound - > m_keep )
2011-02-03 13:25:05 +00:00
pauseSounds . push_back ( sound ) ;
2009-09-26 20:03:01 +00:00
// stop
else
2011-02-03 13:25:05 +00:00
stopSounds . push_back ( sound ) ;
2009-09-26 20:03:01 +00:00
}
// continue playing
2009-08-09 21:16:39 +00:00
else
2011-06-21 20:21:43 +00:00
alSourcePlay ( sound - > m_source ) ;
2009-08-09 21:16:39 +00:00
}
}
2011-02-03 13:25:05 +00:00
for ( it = pauseSounds . begin ( ) ; it ! = pauseSounds . end ( ) ; it + + )
2013-08-14 21:21:00 +00:00
( * it ) - > pause ( true ) ;
2011-02-03 13:25:05 +00:00
for ( it = stopSounds . begin ( ) ; it ! = stopSounds . end ( ) ; it + + )
2011-06-21 20:21:43 +00:00
( * it ) - > stop ( ) ;
2011-02-03 13:25:05 +00:00
pauseSounds . clear ( ) ;
stopSounds . clear ( ) ;
2010-12-22 10:51:34 +00:00
alcProcessContext ( m_context ) ;
}
2009-08-09 21:16:39 +00:00
// stop thread
2011-06-21 20:21:43 +00:00
if ( m_playingSounds . empty ( ) | | ( cerr ! = ALC_NO_ERROR ) )
2009-08-09 21:16:39 +00:00
{
m_playing = false ;
2011-07-23 15:59:10 +00:00
unlock ( ) ;
2009-08-09 21:16:39 +00:00
pthread_exit ( NULL ) ;
}
unlock ( ) ;
# ifdef WIN32
Sleep ( 20 ) ;
# else
usleep ( 20000 ) ;
# endif
}
}
/******************************************************************************/
/**************************** IDevice Code ************************************/
/******************************************************************************/
2010-08-03 08:07:21 +00:00
static const char * open_error = " AUD_OpenALDevice: Device couldn't be opened. " ;
2010-01-01 05:09:30 +00:00
AUD_OpenALDevice : : AUD_OpenALDevice ( AUD_DeviceSpecs specs , int buffersize )
2009-08-09 21:16:39 +00:00
{
// cannot determine how many channels or which format OpenAL uses, but
// it at least is able to play 16 bit stereo audio
specs . format = AUD_FORMAT_S16 ;
2010-01-16 22:12:19 +00:00
#if 0
if ( alcIsExtensionPresent ( NULL , " ALC_ENUMERATION_EXT " ) = = AL_TRUE )
{
ALCchar * devices = const_cast < ALCchar * > ( alcGetString ( NULL , ALC_DEVICE_SPECIFIER ) ) ;
printf ( " OpenAL devices (standard is: %s): \n " , alcGetString ( NULL , ALC_DEFAULT_DEVICE_SPECIFIER ) ) ;
while ( * devices )
{
printf ( " %s \n " , devices ) ;
devices + = strlen ( devices ) + 1 ;
}
}
# endif
2010-01-18 20:11:31 +00:00
m_device = alcOpenDevice ( NULL ) ;
2009-08-09 21:16:39 +00:00
if ( ! m_device )
2010-08-03 08:07:21 +00:00
AUD_THROW ( AUD_ERROR_OPENAL , open_error ) ;
2009-08-09 21:16:39 +00:00
// at least try to set the frequency
2012-09-16 00:26:36 +00:00
ALCint attribs [ ] = { ALC_FREQUENCY , ( ALCint ) specs . rate , 0 } ;
2009-08-09 21:16:39 +00:00
ALCint * attributes = attribs ;
if ( specs . rate = = AUD_RATE_INVALID )
attributes = NULL ;
m_context = alcCreateContext ( m_device , attributes ) ;
alcMakeContextCurrent ( m_context ) ;
alcGetIntegerv ( m_device , ALC_FREQUENCY , 1 , ( ALCint * ) & specs . rate ) ;
// check for specific formats and channel counts to be played back
if ( alIsExtensionPresent ( " AL_EXT_FLOAT32 " ) = = AL_TRUE )
specs . format = AUD_FORMAT_FLOAT32 ;
m_useMC = alIsExtensionPresent ( " AL_EXT_MCFORMATS " ) = = AL_TRUE ;
2012-10-25 10:42:09 +00:00
if ( ( ! m_useMC & & specs . channels > AUD_CHANNELS_STEREO ) | |
specs . channels = = AUD_CHANNELS_STEREO_LFE | |
specs . channels = = AUD_CHANNELS_SURROUND5 )
specs . channels = AUD_CHANNELS_STEREO ;
2009-08-09 21:16:39 +00:00
alGetError ( ) ;
2011-02-03 13:25:05 +00:00
alcGetError ( m_device ) ;
2009-08-09 21:16:39 +00:00
m_specs = specs ;
m_buffersize = buffersize ;
m_playing = false ;
2011-06-21 20:21:43 +00:00
// m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
2009-08-09 21:16:39 +00:00
pthread_mutexattr_t attr ;
pthread_mutexattr_init ( & attr ) ;
pthread_mutexattr_settype ( & attr , PTHREAD_MUTEX_RECURSIVE ) ;
pthread_mutex_init ( & m_mutex , & attr ) ;
pthread_mutexattr_destroy ( & attr ) ;
2011-07-23 15:59:10 +00:00
start ( false ) ;
2009-08-09 21:16:39 +00:00
}
AUD_OpenALDevice : : ~ AUD_OpenALDevice ( )
{
lock ( ) ;
alcSuspendContext ( m_context ) ;
2011-06-21 20:21:43 +00:00
while ( ! m_playingSounds . empty ( ) )
m_playingSounds . front ( ) - > stop ( ) ;
while ( ! m_pausedSounds . empty ( ) )
m_pausedSounds . front ( ) - > stop ( ) ;
2009-08-09 21:16:39 +00:00
// delete all buffered factories
2011-06-21 20:21:43 +00:00
/*while(!m_bufferedFactories->empty())
2009-08-09 21:16:39 +00:00
{
alDeleteBuffers ( 1 , & ( * ( m_bufferedFactories - > begin ( ) ) ) - > buffer ) ;
2010-07-28 09:36:03 +00:00
delete * m_bufferedFactories - > begin ( ) ;
2009-08-09 21:16:39 +00:00
m_bufferedFactories - > erase ( m_bufferedFactories - > begin ( ) ) ;
2011-06-21 20:21:43 +00:00
} */
2009-08-09 21:16:39 +00:00
alcProcessContext ( m_context ) ;
// wait for the thread to stop
2011-07-23 15:59:10 +00:00
unlock ( ) ;
pthread_join ( m_thread , NULL ) ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
//delete m_bufferedFactories;
2009-08-09 21:16:39 +00:00
// quit OpenAL
alcMakeContextCurrent ( NULL ) ;
alcDestroyContext ( m_context ) ;
alcCloseDevice ( m_device ) ;
pthread_mutex_destroy ( & m_mutex ) ;
}
2010-07-28 09:36:03 +00:00
AUD_DeviceSpecs AUD_OpenALDevice : : getSpecs ( ) const
2009-08-09 21:16:39 +00:00
{
return m_specs ;
}
bool AUD_OpenALDevice : : getFormat ( ALenum & format , AUD_Specs specs )
{
bool valid = true ;
format = 0 ;
2010-01-01 05:09:30 +00:00
switch ( m_specs . format )
2009-08-09 21:16:39 +00:00
{
case AUD_FORMAT_S16 :
switch ( specs . channels )
{
case AUD_CHANNELS_MONO :
format = AL_FORMAT_MONO16 ;
break ;
case AUD_CHANNELS_STEREO :
format = AL_FORMAT_STEREO16 ;
break ;
case AUD_CHANNELS_SURROUND4 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_QUAD16 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND51 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_51CHN16 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND61 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_61CHN16 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND71 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_71CHN16 " ) ;
break ;
}
default :
valid = false ;
}
break ;
case AUD_FORMAT_FLOAT32 :
switch ( specs . channels )
{
case AUD_CHANNELS_MONO :
format = alGetEnumValue ( " AL_FORMAT_MONO_FLOAT32 " ) ;
break ;
case AUD_CHANNELS_STEREO :
format = alGetEnumValue ( " AL_FORMAT_STEREO_FLOAT32 " ) ;
break ;
case AUD_CHANNELS_SURROUND4 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_QUAD32 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND51 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_51CHN32 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND61 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_61CHN32 " ) ;
break ;
}
case AUD_CHANNELS_SURROUND71 :
if ( m_useMC )
{
format = alGetEnumValue ( " AL_FORMAT_71CHN32 " ) ;
break ;
}
default :
valid = false ;
}
break ;
default :
valid = false ;
}
if ( ! format )
valid = false ;
return valid ;
}
2012-11-05 14:24:35 +00:00
boost : : shared_ptr < AUD_IHandle > AUD_OpenALDevice : : play ( boost : : shared_ptr < AUD_IReader > reader , bool keep )
2009-08-09 21:16:39 +00:00
{
2011-06-21 20:21:43 +00:00
AUD_Specs specs = reader - > getSpecs ( ) ;
2009-08-09 21:16:39 +00:00
// check format
2011-06-21 20:21:43 +00:00
if ( specs . channels = = AUD_CHANNELS_INVALID )
2012-11-05 14:24:35 +00:00
return boost : : shared_ptr < AUD_IHandle > ( ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 09:36:03 +00:00
if ( m_specs . format ! = AUD_FORMAT_FLOAT32 )
2012-11-05 14:24:35 +00:00
reader = boost : : shared_ptr < AUD_IReader > ( new AUD_ConverterReader ( reader , m_specs ) ) ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
ALenum format ;
2009-08-09 21:16:39 +00:00
2011-06-21 20:21:43 +00:00
if ( ! getFormat ( format , specs ) )
2012-11-05 14:24:35 +00:00
return boost : : shared_ptr < AUD_IHandle > ( ) ;
2009-08-09 21:16:39 +00:00
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * this ) ;
2009-08-09 21:16:39 +00:00
alcSuspendContext ( m_context ) ;
2012-11-05 14:24:35 +00:00
boost : : shared_ptr < AUD_OpenALDevice : : AUD_OpenALHandle > sound ;
2011-06-21 20:21:43 +00:00
2009-08-09 21:16:39 +00:00
try
{
2011-06-21 20:21:43 +00:00
// create the handle
2012-11-05 14:24:35 +00:00
sound = boost : : shared_ptr < AUD_OpenALDevice : : AUD_OpenALHandle > ( new AUD_OpenALDevice : : AUD_OpenALHandle ( this , format , reader , keep ) ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-28 09:36:03 +00:00
catch ( AUD_Exception & )
2009-08-09 21:16:39 +00:00
{
alcProcessContext ( m_context ) ;
throw ;
}
2011-06-21 20:21:43 +00:00
alcProcessContext ( m_context ) ;
2009-08-09 21:16:39 +00:00
// play sound
2011-06-21 20:21:43 +00:00
m_playingSounds . push_back ( sound ) ;
2009-08-09 21:16:39 +00:00
start ( ) ;
2012-11-05 14:24:35 +00:00
return boost : : shared_ptr < AUD_IHandle > ( sound ) ;
2009-08-09 21:16:39 +00:00
}
2012-11-05 14:24:35 +00:00
boost : : shared_ptr < AUD_IHandle > AUD_OpenALDevice : : play ( boost : : shared_ptr < AUD_IFactory > factory , bool keep )
2011-02-18 23:50:27 +00:00
{
2011-06-03 23:28:57 +00:00
/* AUD_XXX disabled
2011-02-18 23:50:27 +00:00
AUD_OpenALHandle * sound = NULL ;
lock ( ) ;
try
{
// check if it is a buffered factory
for ( AUD_BFIterator i = m_bufferedFactories - > begin ( ) ;
i ! = m_bufferedFactories - > end ( ) ; i + + )
{
if ( ( * i ) - > factory = = factory )
{
// create the handle
sound = new AUD_OpenALHandle ;
sound - > keep = keep ;
sound - > current = - 1 ;
sound - > isBuffered = true ;
2011-06-21 20:14:53 +00:00
sound - > eos = true ;
2011-02-18 23:50:27 +00:00
sound - > loopcount = 0 ;
sound - > stop = NULL ;
sound - > stop_data = NULL ;
alcSuspendContext ( m_context ) ;
// OpenAL playback code
try
{
alGenSources ( 1 , & sound - > source ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , gensource_error ) ;
try
{
alSourcei ( sound - > source , AL_BUFFER , ( * i ) - > buffer ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL , queue_error ) ;
}
catch ( AUD_Exception & )
{
alDeleteSources ( 1 , & sound - > source ) ;
throw ;
}
}
catch ( AUD_Exception & )
{
delete sound ;
alcProcessContext ( m_context ) ;
throw ;
}
// play sound
m_playingSounds - > push_back ( sound ) ;
alSourcei ( sound - > source , AL_SOURCE_RELATIVE , 1 ) ;
start ( ) ;
alcProcessContext ( m_context ) ;
}
}
}
2011-06-21 20:21:43 +00:00
catch ( AUD_Exception & )
{
unlock ( ) ;
throw ;
}
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
unlock ( ) ;
2011-06-21 20:21:43 +00:00
if ( sound )
return sound ; */
2010-07-28 12:43:59 +00:00
2011-06-21 20:21:43 +00:00
return play ( factory - > createReader ( ) , keep ) ;
2010-07-28 12:43:59 +00:00
}
2011-08-07 11:54:58 +00:00
void AUD_OpenALDevice : : stopAll ( )
{
2012-10-24 21:33:44 +00:00
AUD_MutexLock lock ( * this ) ;
2011-08-07 11:54:58 +00:00
alcSuspendContext ( m_context ) ;
while ( ! m_playingSounds . empty ( ) )
m_playingSounds . front ( ) - > stop ( ) ;
while ( ! m_pausedSounds . empty ( ) )
m_pausedSounds . front ( ) - > stop ( ) ;
alcProcessContext ( m_context ) ;
}
2011-06-21 20:21:43 +00:00
void AUD_OpenALDevice : : lock ( )
2010-07-28 12:43:59 +00:00
{
2011-06-21 20:21:43 +00:00
pthread_mutex_lock ( & m_mutex ) ;
2010-07-28 12:43:59 +00:00
}
2011-06-21 20:21:43 +00:00
void AUD_OpenALDevice : : unlock ( )
2010-07-31 10:03:08 +00:00
{
2011-06-21 20:21:43 +00:00
pthread_mutex_unlock ( & m_mutex ) ;
2010-07-31 10:03:08 +00:00
}
2011-06-21 20:21:43 +00:00
float AUD_OpenALDevice : : getVolume ( ) const
2010-07-31 10:03:08 +00:00
{
2011-06-21 20:21:43 +00:00
float result ;
alGetListenerf ( AL_GAIN , & result ) ;
2010-07-31 10:03:08 +00:00
return result ;
}
2011-06-21 20:21:43 +00:00
void AUD_OpenALDevice : : setVolume ( float volume )
2010-08-02 18:22:34 +00:00
{
2011-06-21 20:21:43 +00:00
alListenerf ( AL_GAIN , volume ) ;
2010-08-02 18:22:34 +00:00
}
2010-07-28 12:43:59 +00:00
/* AUD_XXX Temorary disabled
bool AUD_OpenALDevice : : bufferFactory ( void * value )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
bool result = false ;
2010-07-28 12:43:59 +00:00
AUD_IFactory * factory = ( AUD_IFactory * ) value ;
// load the factory into an OpenAL buffer
if ( factory )
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
// check if the factory is already buffered
lock ( ) ;
for ( AUD_BFIterator i = m_bufferedFactories - > begin ( ) ;
i ! = m_bufferedFactories - > end ( ) ; i + + )
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
if ( ( * i ) - > factory = = factory )
2009-08-09 21:16:39 +00:00
{
2009-09-26 20:03:01 +00:00
result = true ;
2010-07-28 12:43:59 +00:00
break ;
2009-08-09 21:16:39 +00:00
}
}
2010-07-28 12:43:59 +00:00
unlock ( ) ;
if ( result )
return result ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
AUD_IReader * reader = factory - > createReader ( ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
if ( reader = = NULL )
return false ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
AUD_DeviceSpecs specs = m_specs ;
specs . specs = reader - > getSpecs ( ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
if ( m_specs . format ! = AUD_FORMAT_FLOAT32 )
reader = new AUD_ConverterReader ( reader , m_specs ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
ALenum format ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
if ( ! getFormat ( format , specs . specs ) )
{
return false ;
}
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
// load into a buffer
lock ( ) ;
alcSuspendContext ( m_context ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
AUD_OpenALBufferedFactory * bf = new AUD_OpenALBufferedFactory ;
bf - > factory = factory ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
try
{
alGenBuffers ( 1 , & bf - > buffer ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
try
{
sample_t * buf ;
int length = reader - > getLength ( ) ;
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
reader - > read ( length , buf ) ;
alBufferData ( bf - > buffer , format , buf ,
length * AUD_DEVICE_SAMPLE_SIZE ( specs ) ,
specs . rate ) ;
if ( alGetError ( ) ! = AL_NO_ERROR )
AUD_THROW ( AUD_ERROR_OPENAL ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-28 12:43:59 +00:00
catch ( AUD_Exception & )
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
alDeleteBuffers ( 1 , & bf - > buffer ) ;
throw ;
2009-08-09 21:16:39 +00:00
}
}
2010-07-28 12:43:59 +00:00
catch ( AUD_Exception & )
{
delete bf ;
alcProcessContext ( m_context ) ;
unlock ( ) ;
return false ;
}
2009-08-09 21:16:39 +00:00
2010-07-28 12:43:59 +00:00
m_bufferedFactories - > push_back ( bf ) ;
2009-09-26 20:03:01 +00:00
2010-07-28 12:43:59 +00:00
alcProcessContext ( m_context ) ;
unlock ( ) ;
}
else
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
// stop all playing and paused buffered sources
lock ( ) ;
alcSuspendContext ( m_context ) ;
AUD_OpenALHandle * sound ;
AUD_HandleIterator it = m_playingSounds - > begin ( ) ;
while ( it ! = m_playingSounds - > end ( ) )
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
sound = * it ;
+ + it ;
if ( sound - > isBuffered )
stop ( sound ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-28 12:43:59 +00:00
alcProcessContext ( m_context ) ;
while ( ! m_bufferedFactories - > empty ( ) )
2009-08-09 21:16:39 +00:00
{
2010-07-28 12:43:59 +00:00
alDeleteBuffers ( 1 ,
& ( * ( m_bufferedFactories - > begin ( ) ) ) - > buffer ) ;
delete * m_bufferedFactories - > begin ( ) ;
m_bufferedFactories - > erase ( m_bufferedFactories - > begin ( ) ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-28 12:43:59 +00:00
unlock ( ) ;
2009-08-09 21:16:39 +00:00
}
2009-09-26 20:03:01 +00:00
2010-07-28 12:43:59 +00:00
return true ;
} */
2009-08-09 21:16:39 +00:00
/******************************************************************************/
/**************************** 3D Device Code **********************************/
/******************************************************************************/
2010-07-30 22:20:08 +00:00
AUD_Vector3 AUD_OpenALDevice : : getListenerLocation ( ) const
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
ALfloat p [ 3 ] ;
alGetListenerfv ( AL_POSITION , p ) ;
return AUD_Vector3 ( p [ 0 ] , p [ 1 ] , p [ 2 ] ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-30 22:20:08 +00:00
void AUD_OpenALDevice : : setListenerLocation ( const AUD_Vector3 & location )
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
alListenerfv ( AL_POSITION , ( ALfloat * ) location . get ( ) ) ;
}
2009-08-09 21:16:39 +00:00
2010-07-30 22:20:08 +00:00
AUD_Vector3 AUD_OpenALDevice : : getListenerVelocity ( ) const
{
ALfloat v [ 3 ] ;
alGetListenerfv ( AL_VELOCITY , v ) ;
return AUD_Vector3 ( v [ 0 ] , v [ 1 ] , v [ 2 ] ) ;
}
void AUD_OpenALDevice : : setListenerVelocity ( const AUD_Vector3 & velocity )
{
alListenerfv ( AL_VELOCITY , ( ALfloat * ) velocity . get ( ) ) ;
}
AUD_Quaternion AUD_OpenALDevice : : getListenerOrientation ( ) const
{
2011-08-07 11:54:58 +00:00
return m_orientation ;
2010-07-30 22:20:08 +00:00
}
void AUD_OpenALDevice : : setListenerOrientation ( const AUD_Quaternion & orientation )
{
ALfloat direction [ 6 ] ;
direction [ 0 ] = - 2 * ( orientation . w ( ) * orientation . y ( ) +
orientation . x ( ) * orientation . z ( ) ) ;
direction [ 1 ] = 2 * ( orientation . x ( ) * orientation . w ( ) -
orientation . z ( ) * orientation . y ( ) ) ;
direction [ 2 ] = 2 * ( orientation . x ( ) * orientation . x ( ) +
orientation . y ( ) * orientation . y ( ) ) - 1 ;
direction [ 3 ] = 2 * ( orientation . x ( ) * orientation . y ( ) -
orientation . w ( ) * orientation . z ( ) ) ;
direction [ 4 ] = 1 - 2 * ( orientation . x ( ) * orientation . x ( ) +
orientation . z ( ) * orientation . z ( ) ) ;
direction [ 5 ] = 2 * ( orientation . w ( ) * orientation . x ( ) +
orientation . y ( ) * orientation . z ( ) ) ;
alListenerfv ( AL_ORIENTATION , direction ) ;
2011-08-07 11:54:58 +00:00
m_orientation = orientation ;
2010-07-30 22:20:08 +00:00
}
float AUD_OpenALDevice : : getSpeedOfSound ( ) const
{
return alGetFloat ( AL_SPEED_OF_SOUND ) ;
}
void AUD_OpenALDevice : : setSpeedOfSound ( float speed )
{
alSpeedOfSound ( speed ) ;
2009-08-09 21:16:39 +00:00
}
2010-07-30 22:20:08 +00:00
float AUD_OpenALDevice : : getDopplerFactor ( ) const
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
return alGetFloat ( AL_DOPPLER_FACTOR ) ;
}
void AUD_OpenALDevice : : setDopplerFactor ( float factor )
{
alDopplerFactor ( factor ) ;
}
AUD_DistanceModel AUD_OpenALDevice : : getDistanceModel ( ) const
{
switch ( alGetInteger ( AL_DISTANCE_MODEL ) )
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
case AL_INVERSE_DISTANCE :
return AUD_DISTANCE_MODEL_INVERSE ;
case AL_INVERSE_DISTANCE_CLAMPED :
return AUD_DISTANCE_MODEL_INVERSE_CLAMPED ;
case AL_LINEAR_DISTANCE :
return AUD_DISTANCE_MODEL_LINEAR ;
case AL_LINEAR_DISTANCE_CLAMPED :
return AUD_DISTANCE_MODEL_LINEAR_CLAMPED ;
case AL_EXPONENT_DISTANCE :
return AUD_DISTANCE_MODEL_EXPONENT ;
case AL_EXPONENT_DISTANCE_CLAMPED :
return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED ;
2009-08-09 21:16:39 +00:00
default :
2010-07-30 22:20:08 +00:00
return AUD_DISTANCE_MODEL_INVALID ;
2009-08-09 21:16:39 +00:00
}
}
2010-07-30 22:20:08 +00:00
void AUD_OpenALDevice : : setDistanceModel ( AUD_DistanceModel model )
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
switch ( model )
2009-08-09 21:16:39 +00:00
{
2010-07-30 22:20:08 +00:00
case AUD_DISTANCE_MODEL_INVERSE :
alDistanceModel ( AL_INVERSE_DISTANCE ) ;
break ;
case AUD_DISTANCE_MODEL_INVERSE_CLAMPED :
alDistanceModel ( AL_INVERSE_DISTANCE_CLAMPED ) ;
break ;
case AUD_DISTANCE_MODEL_LINEAR :
alDistanceModel ( AL_LINEAR_DISTANCE ) ;
break ;
case AUD_DISTANCE_MODEL_LINEAR_CLAMPED :
alDistanceModel ( AL_LINEAR_DISTANCE_CLAMPED ) ;
break ;
case AUD_DISTANCE_MODEL_EXPONENT :
alDistanceModel ( AL_EXPONENT_DISTANCE ) ;
break ;
case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED :
alDistanceModel ( AL_EXPONENT_DISTANCE_CLAMPED ) ;
break ;
2009-08-09 21:16:39 +00:00
default :
2010-07-30 22:20:08 +00:00
alDistanceModel ( AL_NONE ) ;
2009-08-09 21:16:39 +00:00
}
}