| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- #include <list>
- #include <boost/thread.hpp>
- #include "core/AudioManager.h"
- #include "core/XmlMusicsFile.h"
- #include "core/Logger.h"
- template<>AudioManager *Ogre::Singleton<AudioManager>::msSingleton = nullptr;
- 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(nullptr);
- if(m_ALDevice != nullptr)
- {
- m_ALContext = alcCreateContext(m_ALDevice, nullptr);
- if(m_ALContext != nullptr)
- {
- 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(nullptr);
- 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 == nullptr)
- {
- 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 nullptr;
- }
- const char*
- AudioManager::ALError()
- {
- //ALenum error_code = alGetError();
- //if( error_code == AL_NO_ERROR )
- {
- return nullptr;
- }
- //else
- //{
- //return alGetString( error_code );
- //}
- }
- const char*
- AudioManager::ALCError(const ALCdevice* device)
- {
- //const ALCdevice *alc_device = ( ( device == nullptr ) ? 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 nullptr;
- }
- //else
- //{
- //return alcGetString( const_cast< ALCdevice* >( device ), error_code );
- //}
- }
- AudioManager::Player::Player(boost::recursive_mutex* mutex):
- m_Loop(-1.0),
- m_VorbisInfo(nullptr),
- 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;
- }
|