Removed: OpenAL music implementation
--HG-- branch : sound_devhg/feature/gsoc2012-fabien
parent
dd02d76df8
commit
8491bd4829
@ -1,328 +0,0 @@
|
|||||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
||||||
// Copyright (C) 2010 Winch Gate Property Limited
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program 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
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#include "stdopenal.h"
|
|
||||||
|
|
||||||
// Project includes
|
|
||||||
#include "sound_driver_al.h"
|
|
||||||
#include "source_al.h"
|
|
||||||
#include "buffer_al.h"
|
|
||||||
#include "music_channel_al.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace NLMISC;
|
|
||||||
|
|
||||||
namespace NLSOUND
|
|
||||||
{
|
|
||||||
|
|
||||||
CMusicChannelAL::CMusicChannelAL(CSoundDriverAL *soundDriver)
|
|
||||||
: _SoundDriver(soundDriver), _MusicBuffer(NULL), _Thread(NULL), _Buffer(NULL), _Source(NULL), _Playing(false), _Async(false), _Gain(1.0)
|
|
||||||
{
|
|
||||||
// create a default source for music streaming
|
|
||||||
_Source = static_cast<CSourceAL*>(_SoundDriver->createSource());
|
|
||||||
_Source->setType(SourceMusic);
|
|
||||||
_Source->setStreamingBufferSize(32768);
|
|
||||||
}
|
|
||||||
|
|
||||||
CMusicChannelAL::~CMusicChannelAL()
|
|
||||||
{
|
|
||||||
release();
|
|
||||||
if (_SoundDriver) { _SoundDriver->removeMusicChannel(this); _SoundDriver = NULL; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMusicChannelAL::release()
|
|
||||||
{
|
|
||||||
// stop thread before deleting it
|
|
||||||
stop();
|
|
||||||
|
|
||||||
// delete thread
|
|
||||||
if (_Thread)
|
|
||||||
{
|
|
||||||
delete _Thread;
|
|
||||||
_Thread = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete source
|
|
||||||
if (_Source)
|
|
||||||
{
|
|
||||||
delete _Source;
|
|
||||||
_Source = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fill IBuffer with data from IMusicBuffer
|
|
||||||
bool CMusicChannelAL::fillBuffer(IBuffer *buffer, uint length)
|
|
||||||
{
|
|
||||||
if (!buffer || !length)
|
|
||||||
{
|
|
||||||
nlwarning("AL: No data to stream");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill buffer with music data
|
|
||||||
uint8 *tmp = buffer->lock(length);
|
|
||||||
if (tmp == NULL)
|
|
||||||
{
|
|
||||||
nlwarning("AL: Can't allocate %u bytes for buffer", length);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 size = _MusicBuffer->getNextBytes(tmp, length, length);
|
|
||||||
buffer->unlock(size);
|
|
||||||
|
|
||||||
return size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use buffer format from IMusicBuffer
|
|
||||||
void CMusicChannelAL::setBufferFormat(IBuffer *buffer)
|
|
||||||
{
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
nlwarning("AL: No buffer specified");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use the same format as music for buffers
|
|
||||||
buffer->setFormat(IBuffer::FormatPcm, _MusicBuffer->getChannels(),
|
|
||||||
_MusicBuffer->getBitsPerSample(), _MusicBuffer->getSamplesPerSec());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMusicChannelAL::run()
|
|
||||||
{
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
// use queued buffers
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// buffers to update
|
|
||||||
std::vector<CBufferAL*> buffers;
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
// get all buffers to queue
|
|
||||||
_Source->getStreamingBuffers(buffers);
|
|
||||||
|
|
||||||
// set format for each buffer
|
|
||||||
for(uint i = 0; i < buffers.size(); ++i)
|
|
||||||
setBufferFormat(buffers[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// get unqueued buffers
|
|
||||||
_Source->getProcessedStreamingBuffers(buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill buffers
|
|
||||||
for(uint i = 0; i < buffers.size(); ++i)
|
|
||||||
{
|
|
||||||
if (!fillBuffer(buffers[i], _Source->getStreamingBufferSize()))
|
|
||||||
break;
|
|
||||||
|
|
||||||
// add buffer to streaming buffers queue
|
|
||||||
_Source->submitStreamingBuffer(buffers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// play the source
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
_Source->play();
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait 100ms before rechecking buffers
|
|
||||||
nlSleep(100);
|
|
||||||
}
|
|
||||||
while(!_MusicBuffer->isMusicEnded() && _Playing);
|
|
||||||
|
|
||||||
|
|
||||||
// music finished without interruption
|
|
||||||
if (_Playing)
|
|
||||||
{
|
|
||||||
// wait until source is not playing
|
|
||||||
while(_Source->isPlaying() && _Playing) nlSleep(1000);
|
|
||||||
|
|
||||||
_Source->stop();
|
|
||||||
|
|
||||||
_Playing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Play sync music
|
|
||||||
bool CMusicChannelAL::playSync()
|
|
||||||
{
|
|
||||||
// use an unique buffer managed by CMusicChannelAL
|
|
||||||
_Buffer = _SoundDriver->createBuffer();
|
|
||||||
|
|
||||||
// set format
|
|
||||||
setBufferFormat(_Buffer);
|
|
||||||
|
|
||||||
// fill data
|
|
||||||
fillBuffer(_Buffer, _MusicBuffer->getUncompressedSize());
|
|
||||||
|
|
||||||
// we don't need _MusicBuffer anymore because all is loaded into memory
|
|
||||||
if (_MusicBuffer)
|
|
||||||
{
|
|
||||||
delete _MusicBuffer;
|
|
||||||
_MusicBuffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete previous queued buffers
|
|
||||||
_Source->setStreamingBuffersMax(0);
|
|
||||||
|
|
||||||
// use this buffer as source
|
|
||||||
_Source->setStaticBuffer(_Buffer);
|
|
||||||
|
|
||||||
// play the source
|
|
||||||
return _Source->play();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Play some music (.ogg etc...)
|
|
||||||
* NB: if an old music was played, it is first stop with stopMusic()
|
|
||||||
* \param filepath file path, CPath::lookup is done here
|
|
||||||
* \param async stream music from hard disk, preload in memory if false
|
|
||||||
* \param loop must be true to play the music in loop.
|
|
||||||
*/
|
|
||||||
bool CMusicChannelAL::play(const std::string &filepath, bool async, bool loop)
|
|
||||||
{
|
|
||||||
// stop a previous music
|
|
||||||
stop();
|
|
||||||
|
|
||||||
// when not using async, we must load the whole file once
|
|
||||||
_MusicBuffer = IMusicBuffer::createMusicBuffer(filepath, async, async ? loop:false);
|
|
||||||
|
|
||||||
if (_MusicBuffer)
|
|
||||||
{
|
|
||||||
_Async = async;
|
|
||||||
_Playing = true;
|
|
||||||
|
|
||||||
_Source->setSourceRelativeMode(true);
|
|
||||||
|
|
||||||
if (_Async)
|
|
||||||
{
|
|
||||||
// create the thread if it's not yet created
|
|
||||||
if (!_Thread) _Thread = IThread::create(this);
|
|
||||||
|
|
||||||
if (!_Thread)
|
|
||||||
{
|
|
||||||
nlwarning("AL: Can't create a new thread");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use 4 queued buffers
|
|
||||||
_Source->setStreamingBuffersMax(4);
|
|
||||||
|
|
||||||
// we need to loop the source only if not async
|
|
||||||
_Source->setLooping(false);
|
|
||||||
|
|
||||||
// start the thread
|
|
||||||
_Thread->start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we need to loop the source only if not async
|
|
||||||
_Source->setLooping(loop);
|
|
||||||
|
|
||||||
return playSync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning("AL: Can't stream file %s", filepath.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stop the music previously loaded and played (the Memory is also freed)
|
|
||||||
void CMusicChannelAL::stop()
|
|
||||||
{
|
|
||||||
_Playing = false;
|
|
||||||
|
|
||||||
_Source->stop();
|
|
||||||
|
|
||||||
// if not using async streaming, we manage static buffer ourself
|
|
||||||
if (!_Async && _Buffer)
|
|
||||||
{
|
|
||||||
_Source->setStaticBuffer(NULL);
|
|
||||||
delete _Buffer;
|
|
||||||
_Buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait until thread is finished
|
|
||||||
if (_Thread)
|
|
||||||
_Thread->wait();
|
|
||||||
|
|
||||||
if (_MusicBuffer)
|
|
||||||
{
|
|
||||||
delete _MusicBuffer;
|
|
||||||
_MusicBuffer = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pause the music previously loaded and played (the Memory is not freed)
|
|
||||||
void CMusicChannelAL::pause()
|
|
||||||
{
|
|
||||||
_Source->pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resume the music previously paused
|
|
||||||
void CMusicChannelAL::resume()
|
|
||||||
{
|
|
||||||
_Source->play();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true if a song is finished.
|
|
||||||
bool CMusicChannelAL::isEnded()
|
|
||||||
{
|
|
||||||
return !_Playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true if the song is still loading asynchronously and hasn't started playing yet (false if not async), used to delay fading
|
|
||||||
bool CMusicChannelAL::isLoadingAsync()
|
|
||||||
{
|
|
||||||
return _Async && _Playing && !_Source->isPlaying();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the total length (in second) of the music currently played
|
|
||||||
float CMusicChannelAL::getLength()
|
|
||||||
{
|
|
||||||
if (_MusicBuffer) return _MusicBuffer->getLength();
|
|
||||||
else return .0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the music volume (if any music played). (volume value inside [0 , 1]) (default: 1)
|
|
||||||
* NB: in OpenAL driver, the volume of music IS affected by IListener::setGain()
|
|
||||||
*/
|
|
||||||
void CMusicChannelAL::setVolume(float gain)
|
|
||||||
{
|
|
||||||
_Gain = gain;
|
|
||||||
_Source->setGain(gain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update music
|
|
||||||
void CMusicChannelAL::update()
|
|
||||||
{
|
|
||||||
// stop sync music once finished playing
|
|
||||||
if (_Playing && !_Async && !_Source->isPlaying())
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace NLSOUND */
|
|
||||||
|
|
||||||
/* end of file */
|
|
@ -1,106 +0,0 @@
|
|||||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
||||||
// Copyright (C) 2010 Winch Gate Property Limited
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program 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
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#ifndef NLSOUND_MUSIC_CHANNEL_AL_H
|
|
||||||
#define NLSOUND_MUSIC_CHANNEL_AL_H
|
|
||||||
|
|
||||||
#include "nel/sound/driver/music_channel.h"
|
|
||||||
|
|
||||||
namespace NLSOUND
|
|
||||||
{
|
|
||||||
class CSoundDriverAL;
|
|
||||||
class IMusicBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief CMusicChannelAL
|
|
||||||
* \date 2010-07-27 16:56GMT
|
|
||||||
* \author Kervala
|
|
||||||
* CMusicChannelAL is an implementation of the IMusicChannel interface to run on OpenAL.
|
|
||||||
*/
|
|
||||||
class CMusicChannelAL : public IMusicChannel, public NLMISC::IRunnable
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
// outside pointers
|
|
||||||
CSoundDriverAL* _SoundDriver;
|
|
||||||
|
|
||||||
// pointers
|
|
||||||
IMusicBuffer* _MusicBuffer;
|
|
||||||
NLMISC::IThread* _Thread;
|
|
||||||
|
|
||||||
IBuffer* _Buffer;
|
|
||||||
CSourceAL* _Source;
|
|
||||||
bool _Playing;
|
|
||||||
bool _Async;
|
|
||||||
|
|
||||||
float _Gain;
|
|
||||||
|
|
||||||
/// Fill IBuffer with data from IMusicBuffer
|
|
||||||
bool fillBuffer(IBuffer *buffer, uint length);
|
|
||||||
|
|
||||||
/// Use buffer format from IMusicBuffer
|
|
||||||
void setBufferFormat(IBuffer *buffer);
|
|
||||||
|
|
||||||
/// Declared in NLMISC::IRunnable interface
|
|
||||||
virtual void run();
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMusicChannelAL(CSoundDriverAL *soundDriver);
|
|
||||||
virtual ~CMusicChannelAL();
|
|
||||||
void release();
|
|
||||||
|
|
||||||
/** Play some music (.ogg etc...)
|
|
||||||
* NB: if an old music was played, it is first stop with stopMusic()
|
|
||||||
* \param filepath file path, CPath::lookup is done here
|
|
||||||
* \param async stream music from hard disk, preload in memory if false
|
|
||||||
* \param loop must be true to play the music in loop.
|
|
||||||
*/
|
|
||||||
virtual bool play(const std::string &filepath, bool async, bool loop);
|
|
||||||
|
|
||||||
/// Stop the music previously loaded and played (the Memory is also freed)
|
|
||||||
virtual void stop();
|
|
||||||
|
|
||||||
/// Pause the music previously loaded and played (the Memory is not freed)
|
|
||||||
virtual void pause();
|
|
||||||
|
|
||||||
/// Resume the music previously paused
|
|
||||||
virtual void resume();
|
|
||||||
|
|
||||||
/// Return true if a song is finished.
|
|
||||||
virtual bool isEnded();
|
|
||||||
|
|
||||||
/// Return true if the song is still loading asynchronously and hasn't started playing yet (false if not async), used to delay fading
|
|
||||||
virtual bool isLoadingAsync();
|
|
||||||
|
|
||||||
/// Return the total length (in second) of the music currently played
|
|
||||||
virtual float getLength();
|
|
||||||
|
|
||||||
/** Set the music volume (if any music played). (volume value inside [0 , 1]) (default: 1)
|
|
||||||
* NB: in OpenAL driver, the volume of music IS affected by IListener::setGain()
|
|
||||||
*/
|
|
||||||
virtual void setVolume(float gain);
|
|
||||||
|
|
||||||
/// Play sync music
|
|
||||||
bool playSync();
|
|
||||||
|
|
||||||
/// Update music
|
|
||||||
void update();
|
|
||||||
}; /* class CMusicChannelAL */
|
|
||||||
|
|
||||||
} /* namespace NLSOUND */
|
|
||||||
|
|
||||||
#endif /* #ifndef NLSOUND_MUSIC_CHANNEL_AL_H */
|
|
||||||
|
|
||||||
/* end of file */
|
|
Loading…
Reference in New Issue