| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- #include "core/AudioManager.h"
- #include <list>
- #include <boost/thread.hpp>
- #include "core/XmlMusicsFile.h"
- #include "core/Logger.h"
- template<>AudioManager *Ogre::Singleton< AudioManager >::msSingleton = NULL;
- ALsizei AudioManager::m_ChannelBufferNumber = 2;
- int AudioManager::m_ChannelBufferSize = 96 * 1024;
- AudioManager::AudioManager():
- m_Initialized( false ),
- m_ThreadContinue( true ),
- m_UpdateMutex(),
- m_Music( &m_UpdateMutex )
- {
- m_ALDevice = alcOpenDevice( NULL );
- if( m_ALDevice != NULL )
- {
- m_ALContext = alcCreateContext( m_ALDevice, NULL );
- if( m_ALContext != NULL )
- {
- alcMakeContextCurrent( m_ALContext );
- // listeners
- ALfloat position[ 3 ] = { 0.0f, 0.0f, 0.0f };
- ALfloat velocity[ 3 ] = { 0.0f, 0.0f, 0.0f };
- ALfloat orientation[ 6 ] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
- alListenerfv( AL_POSITION, position );
- alListenerfv( AL_VELOCITY, velocity );
- alListenerfv( AL_ORIENTATION, orientation );
- m_Initialized = true;
- m_Buffer = new char[ m_ChannelBufferSize ];
- m_UpdateThread = new boost::thread( boost::ref( *this ) );
- LOG_TRIVIAL( "AudioManager initialised." );
- }
- else
- {
- LOG_ERROR( "AudioManager failed to initialised. Could not create context for sound device." );
- }
- }
- else
- {
- LOG_ERROR( "AudioManager failed to initialised. There's no default sound device." );
- }
- // Load musics
- XmlMusicsFile musics( "./data/musics.xml" );
- musics.LoadMusics();
- }
- AudioManager::~AudioManager()
- {
- MusicStop();
- if( m_Initialized )
- {
- m_ThreadContinue = false;
- m_UpdateThread->join();
- delete m_UpdateThread;
- delete[] m_Buffer;
- alcMakeContextCurrent( NULL );
- alcDestroyContext( m_ALContext );
- alcCloseDevice( m_ALDevice );
- LOG_TRIVIAL( "AudioManager destroyed." );
- }
- }
- void
- AudioManager::operator()()
- {
- while( m_ThreadContinue )
- {
- Update();
- boost::xtime xt;
- boost::xtime_get( &xt, boost::TIME_UTC_ );
- xt.nsec += 250000000; // sleep for 250 ms
- boost::thread::sleep( xt );
- m_UpdateThread->yield();
- }
- }
- void
- AudioManager::Update()
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- m_Music.Update();
- }
- void
- AudioManager::MusicPause()
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- m_Music.Pause();
- }
- void
- AudioManager::MusicPlay( const Ogre::String& name )
- {
- if( m_Initialized )
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- AudioManager::Music* music = GetMusic( name );
- if( music == NULL )
- {
- LOG_ERROR( "No music found with name \"" + name + "\"." );
- return;
- }
- m_Music.SetLoop( music->loop );
- m_Music.Play( music->file );
- }
- }
- void
- AudioManager::MusicStop()
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- m_Music.Stop();
- }
- void
- AudioManager::AddMusic( const AudioManager::Music& music )
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- for( std::list< AudioManager::Music >::iterator it = m_MusicList.begin(); it != m_MusicList.end(); ++it )
- {
- if( it->name == music.name )
- {
- LOG_ERROR( "Music with name '" + music.name + "' already exists." );
- return;
- }
- }
- m_MusicList.push_back( music );
- }
- AudioManager::Music*
- AudioManager::GetMusic( const Ogre::String& name )
- {
- boost::recursive_mutex::scoped_lock lock( m_UpdateMutex );
- for( auto it = m_MusicList.begin(); it != m_MusicList.end(); ++it )
- {
- if( it->name == name )
- {
- return &( *it );
- }
- }
- return NULL;
- }
- const char*
- AudioManager::ALError()
- {
- //ALenum error_code = alGetError();
- //if( error_code == AL_NO_ERROR )
- {
- return NULL;
- }
- //else
- //{
- //return alGetString( error_code );
- //}
- }
- const char*
- AudioManager::ALCError( const ALCdevice* device )
- {
- //const ALCdevice *alc_device = ( ( device == NULL ) ? const_cast< ALCdevice* >( m_ALDevice ) : const_cast< ALCdevice* >( device ) );
- //ALCenum error_code = alcGetError( const_cast< ALCdevice* >( alc_device ) );
- //if( error_code == ALC_NO_ERROR )
- {
- return NULL;
- }
- //else
- //{
- //return alcGetString( const_cast< ALCdevice* >( device ), error_code );
- //}
- }
- AudioManager::Player::Player( boost::recursive_mutex* mutex ):
- m_Loop( -1.0 ),
- m_VorbisInfo( NULL ),
- m_VorbisSection( 0 ),
- m_StreamFinished( false ),
- m_UpdateMutex( mutex )
- {
- }
- AudioManager::Player::~Player()
- {
- Stop();
- }
- void
- AudioManager::Player::Pause()
- {
- boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex );
- alSourcePause( m_Source );
- }
- void
- AudioManager::Player::Play( const Ogre::String &file )
- {
- boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex );
- // open vorbis file
- if( ov_fopen( const_cast< char* >( file.c_str() ), &m_VorbisFile ) )
- {
- LOG_ERROR( "Can't play file \"" + file + "\"." );
- return;
- }
- // get file info
- m_VorbisInfo = ov_info( &m_VorbisFile, -1.0f );
- // create sound source
- alGenSources( 1, &m_Source );
- // create buffers
- ALuint buffers[ m_ChannelBufferNumber ];
- alGenBuffers( m_ChannelBufferNumber, buffers );
- // set source parameters
- alSourcei( m_Source, AL_LOOPING, AL_FALSE );
- // fill buffers
- for( int i = 0; i < m_ChannelBufferNumber; ++i )
- {
- ALsizei buffer_size = FillBuffer();
- if( buffer_size )
- {
- alBufferData( buffers[ i ], m_VorbisInfo->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, ( const ALvoid* )AudioManager::getSingleton().m_Buffer, ( ALsizei )buffer_size, ( ALsizei )m_VorbisInfo->rate );
- alSourceQueueBuffers( m_Source, 1, &buffers[ i ] );
- }
- else
- {
- m_StreamFinished = true;
- alDeleteBuffers( 1, &buffers[ i ] );
- }
- }
- // start playback
- alSourcePlay( m_Source );
- }
- void
- AudioManager::Player::Stop()
- {
- boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex );
- // stop source
- alSourceStop( m_Source );
- // get source buffers
- int queued_count = 0;
- alGetSourcei( m_Source, AL_BUFFERS_QUEUED, &queued_count );
- // unqueue and delete buffers
- for( int i = 0; i < queued_count; ++i )
- {
- ALuint buffer_id;
- alSourceUnqueueBuffers( m_Source, 1, &buffer_id );
- alDeleteBuffers( 1, &buffer_id );
- }
- // delete source
- alDeleteSources( 1, &m_Source );
- // rest cleanup
- ov_clear( &m_VorbisFile );
- }
- void
- AudioManager::Player::SetLoop( const float loop )
- {
- boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex );
- m_Loop = loop;
- }
- void
- AudioManager::Player::Update()
- {
- // try to fill processed buffers
- {
- int processed;
- alGetSourcei( m_Source, AL_BUFFERS_PROCESSED, &processed );
- for( int i = 0; i < processed; ++i )
- {
- // try fill buffer
- ALsizei buffer_size = FillBuffer();
- if( buffer_size )
- {
- ALuint buffer_id;
- alSourceUnqueueBuffers( m_Source, 1, &buffer_id );
- alBufferData( buffer_id, m_VorbisInfo->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, ( const ALvoid* )AudioManager::getSingleton().m_Buffer, ( ALsizei )buffer_size, ( ALsizei )m_VorbisInfo->rate );
- alSourceQueueBuffers( m_Source, 1, &buffer_id );
- }
- // finished reading stream
- else
- {
- m_StreamFinished = true;
- break;
- }
- }
- }
- // manage source state
- {
- int processed;
- alGetSourcei( m_Source, AL_BUFFERS_PROCESSED, &processed );
- int queued;
- alGetSourcei( m_Source, AL_BUFFERS_QUEUED, &queued );
- if( m_StreamFinished && processed == queued )
- {
- Stop();
- }
- else
- {
- ALenum source_state;
- alGetSourcei( m_Source, AL_SOURCE_STATE, &source_state );
- if( source_state == AL_STOPPED )
- {
- alSourcePlay( m_Source );
- }
- }
- }
- }
- ALsizei
- AudioManager::Player::FillBuffer()
- {
- ALsizei read = 0;
- if( m_StreamFinished )
- {
- return read;
- }
- char *&buffer = AudioManager::getSingleton().m_Buffer;
- bool finished = false;
- do
- {
- long result = ov_read( &m_VorbisFile, buffer + read, m_ChannelBufferSize - read, 0, 2, 1, &m_VorbisSection );
- switch( result )
- {
- // error
- case OV_HOLE:
- case OV_EBADLINK:
- case OV_EINVAL:
- {
- finished = true;
- }
- break;
- // end of stream
- case 0:
- {
- // if there isn't loop point or can't seek
- if( m_Loop < 0.0f || ov_time_seek( &m_VorbisFile, m_Loop ) )
- {
- finished = true;
- }
- }
- break;
- // readed "result" bytes
- default:
- {
- read += result;
- if( read == m_ChannelBufferSize )
- {
- finished = true;
- }
- }
- }
- }
- while( finished == false );
- return read;
- }
- float
- AudioManager::Player::GetPosition()
- {
- boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex );
- int play_offset;
- alGetSourcei( m_Source, AL_SAMPLE_OFFSET, &play_offset );
- return ( ov_pcm_tell( &m_VorbisFile ) - ( m_ChannelBufferNumber * m_ChannelBufferSize / m_VorbisInfo->channels / sizeof( int16_t ) - play_offset ) ) * 1000 / m_VorbisInfo->rate;
- }
|