2011-06-02 21:59:20 +02:00
// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari
// This file is part of the "cAudio Engine"
2011-06-05 23:47:07 +02:00
// For conditions of distribution and use, see copyright notice in cAudio.h
# include "cAudioManager.h"
# include "cAudio.h"
# include "cAudioSource.h"
# include "cAudioPlatform.h"
# include "cAudioSleep.h"
# include "cUtils.h"
# include "cThread.h"
# include "cLogger.h"
# include "cPluginManager.h"
# include "cThread.h"
# include "cMemorySource.h"
# include "cRawAudioDecoderFactory.h"
# include <string.h>
# include <algorithm>
# include "cOpenALDeviceContext.h"
namespace cAudio
{
cAudioManager : : ~ cAudioManager ( )
{
shutDown ( ) ;
}
bool cAudioManager : : initialize ( const char * deviceName , int outputFrequency , int eaxEffectSlots )
{
cAudioMutexBasicLock lock ( Mutex ) ;
if ( Initialized )
return false ;
AudioContext = CAUDIO_NEW cOpenALDeviceContext ( this ) ;
if ( ! AudioContext - > initialize ( deviceName , outputFrequency , eaxEffectSlots ) )
return false ;
# ifdef CAUDIO_USE_INTERNAL_THREAD
if ( ! AudioThread )
{
AudioThread = new cAudioThread ( this ) ;
}
AudioThread - > start ( ) ;
# endif
Initialized = true ;
return true ;
}
void cAudioManager : : shutDown ( )
{
if ( Initialized )
{
if ( AudioThread ) // First wait for our update thread to finish up
{
AudioThread - > join ( ) ;
delete AudioThread ;
AudioThread = NULL ;
}
cAudioMutexBasicLock lock ( Mutex ) ;
releaseAllSources ( ) ;
2011-06-05 22:56:07 +02:00
if ( AudioContext )
{
2011-06-05 23:47:07 +02:00
AudioContext - > shutDown ( ) ;
CAUDIO_DELETE AudioContext ;
2011-06-05 22:56:07 +02:00
AudioContext = NULL ;
2011-06-05 23:47:07 +02:00
}
Initialized = false ;
getLogger ( ) - > logInfo ( " AudioManager " , " Manager successfully shutdown. " ) ;
}
}
void cAudioManager : : update ( )
{
cAudioMutexBasicLock lock ( Mutex ) ;
size_t count = audioSources . size ( ) ;
2011-06-24 23:29:18 +02:00
for ( size_t i = 0 ; i < count ; i + + )
2011-06-05 23:47:07 +02:00
{
IAudioSource * source = audioSources [ i ] ;
if ( source - > isValid ( ) )
{
source - > update ( ) ;
}
}
2011-06-24 23:29:18 +02:00
if ( ! managedAudioSources . empty ( ) )
{
count = managedAudioSources . size ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
IAudioSource * source = managedAudioSources [ i ] ;
if ( source - > isValid ( ) )
{
source - > update ( ) ;
if ( source - > isStopped ( ) )
{
managedAudioSourcesDelBuffer . push_back ( source ) ;
}
}
}
count = managedAudioSourcesDelBuffer . size ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
IAudioSource * source = managedAudioSourcesDelBuffer [ i ] ;
cAudioVector < IAudioSource * > : : Type : : iterator it = std : : find ( managedAudioSources . begin ( ) , managedAudioSources . end ( ) , source ) ;
if ( it ! = managedAudioSources . end ( ) )
{
managedAudioSources . erase ( it ) ;
CAUDIO_DELETE source ;
}
}
managedAudioSourcesDelBuffer . clear ( ) ;
}
2011-06-05 23:47:07 +02:00
}
void cAudioManager : : run ( )
{
if ( ! audioSources . empty ( ) )
update ( ) ;
2011-06-05 22:56:07 +02:00
2011-06-05 23:47:07 +02:00
cAudioSleep ( 1 ) ;
}
bool cAudioManager : : isUpdateThreadRunning ( )
{
return ( AudioThread ! = NULL & & AudioThread - > isRunning ( ) ) ;
}
# if CAUDIO_EFX_ENABLED == 1
IAudioEffects * cAudioManager : : getEffects ( )
{
2011-06-05 22:56:07 +02:00
if ( AudioContext )
2011-06-05 23:47:07 +02:00
{
return AudioContext - > getEffects ( ) ;
}
return NULL ;
}
# endif
2011-06-24 23:29:18 +02:00
IAudioSource * cAudioManager : : play2D ( const char * filename , bool playLooped , bool startPaused )
{
cAudioMutexBasicLock lock ( Mutex ) ;
IAudioSource * pAudioSrc = create ( " " , filename , true ) ;
if ( ! playLooped & & ! startPaused )
{
cAudioVector < IAudioSource * > : : Type : : iterator it = std : : find ( audioSources . begin ( ) , audioSources . end ( ) , pAudioSrc ) ;
if ( it ! = audioSources . end ( ) )
{
audioSources . erase ( it ) ;
}
managedAudioSources . push_back ( pAudioSrc ) ;
pAudioSrc - > play2d ( ) ;
return NULL ;
}
if ( playLooped & & ! startPaused )
{
pAudioSrc - > play2d ( true ) ;
}
return pAudioSrc ;
}
2012-02-18 08:44:04 +01:00
IAudioSource * cAudioManager : : play3D ( const char * filename , cVector3 position , bool playLooped , bool startPaused )
{
cAudioMutexBasicLock lock ( Mutex ) ;
IAudioSource * pAudioSrc = create ( " " , filename , true ) ;
2011-06-24 23:29:18 +02:00
if ( ! playLooped & & ! startPaused )
{
cAudioVector < IAudioSource * > : : Type : : iterator it = std : : find ( audioSources . begin ( ) , audioSources . end ( ) , pAudioSrc ) ;
if ( it ! = audioSources . end ( ) )
{
audioSources . erase ( it ) ;
}
managedAudioSources . push_back ( pAudioSrc ) ;
pAudioSrc - > play3d ( position ) ;
return NULL ;
}
if ( playLooped & & ! startPaused )
{
pAudioSrc - > play3d ( position , 1.0 , true ) ;
}
2012-02-18 08:44:04 +01:00
return pAudioSrc ;
}
2011-06-24 23:29:18 +02:00
void cAudioManager : : setMasterVolume ( float vol )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2011-06-26 02:01:51 +02:00
MasterVolume = vol ;
2011-06-24 23:29:18 +02:00
size_t count = audioSources . size ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
2011-06-25 10:32:37 +02:00
audioSources [ i ] - > setVolume ( audioSources [ i ] - > getVolume ( ) ) ;
2011-06-24 23:29:18 +02:00
}
}
float cAudioManager : : getMasterVolume ( ) const
{
return MasterVolume ;
}
void cAudioManager : : stopAllSounds ( )
{
cAudioMutexBasicLock lock ( Mutex ) ;
size_t count = audioSources . size ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
if ( audioSources [ i ] - > isPlaying ( ) )
audioSources [ i ] - > stop ( ) ;
}
}
2011-06-05 23:47:07 +02:00
IAudioSource * cAudioManager : : createAudioSource ( IAudioDecoder * decoder , const cAudioString & audioName , const cAudioString & dataSource )
{
if ( decoder & & decoder - > isValid ( ) )
{
# if CAUDIO_EFX_ENABLED == 1
2011-06-12 23:57:42 +02:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , AudioContext , ( ( cAudioEffects * ) getEffects ( ) ) - > getEFXInterface ( ) ) ;
2011-06-05 23:47:07 +02:00
# else
2011-06-12 23:57:42 +02:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , AudioContext ) ;
2011-06-05 23:47:07 +02:00
# endif
decoder - > drop ( ) ;
if ( audio & & audio - > isValid ( ) )
{
if ( ! audioName . empty ( ) )
audioIndex [ audioName ] = audio ;
audioSources . push_back ( audio ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Source (%s) created from Data Source %s. " , audioName . c_str ( ) , dataSource . c_str ( ) ) ;
return audio ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Error creating audio source. " , audioName . c_str ( ) ) ;
audio - > drop ( ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder. " , audioName . c_str ( ) , decoder - > getType ( ) . c_str ( ) ) ;
decoder - > drop ( ) ;
return NULL ;
}
IAudioSource * cAudioManager : : create ( const char * name , const char * filename , bool stream )
{
if ( ! Initialized ) return NULL ;
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString audioName = fromUTF8 ( name ) ;
cAudioString path = fromUTF8 ( filename ) ;
2011-06-05 23:47:07 +02:00
cAudioString ext = getExt ( path ) ;
2012-07-04 20:08:23 +02:00
IAudioDecoderFactory * factory = getAudioDecoderFactory ( toUTF8 ( ext ) ) ;
2011-06-05 23:47:07 +02:00
if ( ! factory ) {
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): No decoder could be found for (.%s). " , audioName . c_str ( ) , ext . c_str ( ) ) ;
return NULL ;
}
for ( size_t i = 0 ; i < dataSourcePriorityList . size ( ) ; + + i )
{
const cAudioString dataSourceName = dataSourcePriorityList [ i ] . second ;
IDataSourceFactory * dataFactory = datasourcemap [ dataSourceName ] ;
if ( dataFactory )
{
IDataSource * source = dataFactory - > CreateDataSource ( filename , stream ) ;
if ( source & & source - > isValid ( ) )
{
IAudioDecoder * decoder = factory - > CreateAudioDecoder ( source ) ;
source - > drop ( ) ;
IAudioSource * audio = createAudioSource ( decoder , audioName , dataSourceName ) ;
if ( audio ! = NULL )
return audio ;
if ( source )
source - > drop ( ) ;
return NULL ;
}
}
}
return NULL ;
}
IAudioSource * cAudioManager : : createFromMemory ( const char * name , const char * data , size_t length , const char * extension )
{
if ( ! Initialized ) return NULL ;
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString audioName = fromUTF8 ( name ) ;
cAudioString ext = fromUTF8 ( extension ) ;
IAudioDecoderFactory * factory = getAudioDecoderFactory ( toUTF8 ( ext ) ) ;
2011-06-05 23:47:07 +02:00
if ( ! factory ) {
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Codec (.%s) is not supported. " , audioName . c_str ( ) , ext . c_str ( ) ) ;
return NULL ;
}
cMemorySource * source = CAUDIO_NEW cMemorySource ( data , length , true ) ;
if ( source & & source - > isValid ( ) )
{
IAudioDecoder * decoder = factory - > CreateAudioDecoder ( source ) ;
source - > drop ( ) ;
2012-07-04 20:08:23 +02:00
IAudioSource * audio = createAudioSource ( decoder , audioName , _CTEXT ( " cMemorySource " ) ) ;
2011-06-05 23:47:07 +02:00
if ( audio ! = NULL )
return audio ;
if ( source )
source - > drop ( ) ;
}
return NULL ;
}
2011-06-26 13:16:45 +02:00
IAudioSource * cAudioManager : : createFromAudioBuffer ( const char * name , AudioCaptureBuffer * pBiffer , unsigned int frequency , AudioFormats format )
{
return createFromRaw ( name , pBiffer - > getWriteBuffer ( ) , pBiffer - > getLength ( ) , frequency , format ) ;
}
2011-06-05 23:47:07 +02:00
IAudioSource * cAudioManager : : createFromRaw ( const char * name , const char * data , size_t length , unsigned int frequency , AudioFormats format )
{
if ( ! Initialized ) return NULL ;
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString audioName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
IAudioDecoderFactory * factory = getAudioDecoderFactory ( " raw " ) ;
if ( ! factory ) {
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Codec (.raw) is not supported. " , audioName . c_str ( ) ) ;
return NULL ;
}
cMemorySource * source = CAUDIO_NEW cMemorySource ( data , length , true ) ;
if ( source & & source - > isValid ( ) )
{
IAudioDecoder * decoder = ( ( cRawAudioDecoderFactory * ) factory ) - > CreateAudioDecoder ( source , frequency , format ) ;
source - > drop ( ) ;
2012-07-04 20:08:23 +02:00
IAudioSource * audio = createAudioSource ( decoder , audioName , _CTEXT ( " cMemorySource " ) ) ;
2011-06-05 23:47:07 +02:00
if ( audio ! = NULL )
return audio ;
if ( source )
source - > drop ( ) ;
}
return NULL ;
}
bool cAudioManager : : registerAudioDecoder ( IAudioDecoderFactory * factory , const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString ext = fromUTF8 ( extension ) ;
2011-06-05 23:47:07 +02:00
decodermap [ ext ] = factory ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Decoder for extension .%s registered. " , ext . c_str ( ) ) ;
return true ;
}
void cAudioManager : : unRegisterAudioDecoder ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString ext = fromUTF8 ( extension ) ;
2011-06-05 23:47:07 +02:00
decodermapIterator it = decodermap . find ( ext ) ;
if ( it ! = decodermap . end ( ) )
{
decodermap . erase ( it ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Decoder for extension .%s unregistered. " , ext . c_str ( ) ) ;
}
}
bool cAudioManager : : isAudioDecoderRegistered ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString ext = fromUTF8 ( extension ) ;
2011-06-05 23:47:07 +02:00
decodermapIterator it = decodermap . find ( ext ) ;
return ( it ! = decodermap . end ( ) ) ;
}
IAudioDecoderFactory * cAudioManager : : getAudioDecoderFactory ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString ext = fromUTF8 ( extension ) ;
2011-06-05 23:47:07 +02:00
decodermapIterator it = decodermap . find ( ext ) ;
if ( it ! = decodermap . end ( ) )
{
return it - > second ;
}
return NULL ;
}
void cAudioManager : : unRegisterAllAudioDecoders ( )
{
cAudioMutexBasicLock lock ( Mutex ) ;
decodermap . clear ( ) ;
}
bool compareDataSourcePriorities ( std : : pair < int , cAudioString > left , std : : pair < int , cAudioString > right )
{
return ( left . first > right . first ) ;
}
bool cAudioManager : : registerDataSource ( IDataSourceFactory * factory , const char * name , int priority )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString safeName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
datasourcemap [ safeName ] = factory ;
dataSourcePriorityList . push_back ( std : : pair < int , cAudioString > ( priority , safeName ) ) ;
std : : sort ( dataSourcePriorityList . begin ( ) , dataSourcePriorityList . end ( ) , compareDataSourcePriorities ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Data Source named %s registered (Priority %i). " , safeName . c_str ( ) , priority ) ;
return true ;
}
void cAudioManager : : unRegisterDataSource ( const char * name )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString safeName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
if ( it ! = datasourcemap . end ( ) )
{
datasourcemap . erase ( it ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Data Source named %s unregistered. " , safeName . c_str ( ) ) ;
}
for ( size_t i = 0 ; i < dataSourcePriorityList . size ( ) ; + + i )
{
if ( dataSourcePriorityList [ i ] . second = = safeName )
{
dataSourcePriorityList . erase ( dataSourcePriorityList . begin ( ) + i ) ;
break ;
}
}
std : : sort ( dataSourcePriorityList . begin ( ) , dataSourcePriorityList . end ( ) , compareDataSourcePriorities ) ;
}
bool cAudioManager : : isDataSourceRegistered ( const char * name )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString safeName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
return ( it ! = datasourcemap . end ( ) ) ;
}
IDataSourceFactory * cAudioManager : : getDataSourceFactory ( const char * name )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString safeName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
if ( it ! = datasourcemap . end ( ) )
{
return it - > second ;
}
return NULL ;
}
void cAudioManager : : unRegisterAllDataSources ( )
{
cAudioMutexBasicLock lock ( Mutex ) ;
datasourcemap . clear ( ) ;
dataSourcePriorityList . clear ( ) ;
}
void cAudioManager : : registerEventHandler ( IManagerEventHandler * handler )
{
if ( handler )
{
eventHandlerList . push_back ( handler ) ;
}
}
void cAudioManager : : unRegisterEventHandler ( IManagerEventHandler * handler )
{
if ( handler )
{
eventHandlerList . remove ( handler ) ;
}
}
void cAudioManager : : unRegisterAllEventHandlers ( )
{
eventHandlerList . clear ( ) ;
}
void cAudioManager : : signalEvent ( Events sevent )
{
cAudioMutexBasicLock lock ( Mutex ) ;
cAudioList < IManagerEventHandler * > : : Type : : iterator it = eventHandlerList . begin ( ) ;
if ( it ! = eventHandlerList . end ( ) )
{
switch ( sevent )
{
case ON_INIT :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onInit ( ) ;
}
break ;
case ON_UPDATE :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onUpdate ( ) ;
}
break ;
case ON_RELEASE :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onRelease ( ) ;
}
break ;
case ON_SOURCECREATE :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onSourceCreate ( ) ;
}
break ;
case ON_DECODERREGISTER :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onDecoderRegister ( ) ;
}
break ;
case ON_DATASOURCEREGISTER :
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
( * it ) - > onDataSourceRegister ( ) ;
}
break ;
}
}
}
IAudioSource * cAudioManager : : getSoundByName ( const char * name )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-07-04 20:08:23 +02:00
cAudioString audioName = fromUTF8 ( name ) ;
2011-06-05 23:47:07 +02:00
audioIndexIterator i = audioIndex . find ( audioName ) ;
if ( i = = audioIndex . end ( ) )
{
return NULL ;
}
return i - > second ;
}
void cAudioManager : : releaseAllSources ( )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2012-02-18 08:44:04 +01:00
cAudioVector < IAudioSource * > : : Type : : iterator audioSourcesIter ;
for ( audioSourcesIter = audioSources . begin ( ) ; audioSourcesIter ! = audioSources . end ( ) ; audioSourcesIter + + )
2011-06-05 23:47:07 +02:00
{
2012-02-18 08:44:04 +01:00
if ( ( * audioSourcesIter ) )
( * audioSourcesIter ) - > drop ( ) ;
2011-06-05 23:47:07 +02:00
}
audioSources . clear ( ) ;
audioIndex . clear ( ) ;
2011-06-24 23:29:18 +02:00
2012-02-18 08:44:04 +01:00
cAudioVector < IAudioSource * > : : Type : : iterator managedAudioIter ;
for ( managedAudioIter = managedAudioSources . begin ( ) ; managedAudioIter ! = managedAudioSources . end ( ) ; managedAudioIter + + )
2011-06-24 23:29:18 +02:00
{
2012-02-18 08:44:04 +01:00
if ( ( * managedAudioIter ) )
2011-06-24 23:29:18 +02:00
{
2012-02-18 08:44:04 +01:00
CAUDIO_DELETE ( * managedAudioIter ) ;
2011-06-24 23:29:18 +02:00
}
}
managedAudioSources . clear ( ) ;
2012-02-18 08:44:04 +01:00
cAudioVector < IAudioSource * > : : Type : : iterator managedAudioSourcesDelIter ;
for ( managedAudioSourcesDelIter = managedAudioSourcesDelBuffer . begin ( ) ; managedAudioSourcesDelIter ! = managedAudioSourcesDelBuffer . end ( ) ; managedAudioSourcesDelIter + + )
2011-06-24 23:29:18 +02:00
{
2012-02-18 08:44:04 +01:00
if ( ( * managedAudioSourcesDelIter ) )
2011-06-24 23:29:18 +02:00
{
2012-02-18 08:44:04 +01:00
CAUDIO_DELETE ( * managedAudioSourcesDelIter ) ;
2011-06-24 23:29:18 +02:00
}
}
managedAudioSourcesDelBuffer . clear ( ) ;
2011-06-05 23:47:07 +02:00
}
void cAudioManager : : release ( IAudioSource * source )
{
if ( source )
2011-06-12 23:57:42 +02:00
{
2011-06-05 23:47:07 +02:00
cAudioMutexBasicLock lock ( Mutex ) ;
audioIndexIterator it = audioIndex . begin ( ) ;
for ( it = audioIndex . begin ( ) ; it ! = audioIndex . end ( ) ; it + + )
{
if ( it - > second = = source )
{
audioIndex . erase ( it ) ;
break ;
}
}
for ( unsigned int i = 0 ; i < audioSources . size ( ) ; + + i )
{
if ( source = = audioSources [ i ] )
{
2011-06-12 23:57:42 +02:00
audioSources . erase ( audioSources . begin ( ) + i ) ;
if ( source - > getReferenceCount ( ) < = 1 )
CAUDIO_DELETE source ;
else
source - > drop ( ) ;
2011-06-05 23:47:07 +02:00
break ;
}
}
}
}
} ;