diff --git a/code/nel/src/sound/driver/openal/listener_al.cpp b/code/nel/src/sound/driver/openal/listener_al.cpp
index 67eaf2478..da7e6bc31 100644
--- a/code/nel/src/sound/driver/openal/listener_al.cpp
+++ b/code/nel/src/sound/driver/openal/listener_al.cpp
@@ -145,9 +145,8 @@ void CListenerAL::getOrientation( NLMISC::CVector& front, NLMISC::CVector& u
*/
void CListenerAL::setGain( float gain )
{
- CSoundDriverAL::getInstance()->setGain(gain);
-// alListenerf( AL_GAIN, gain );
-// alTestError();
+ alListenerf( AL_GAIN, gain );
+ alTestError();
}
@@ -156,15 +155,14 @@ void CListenerAL::setGain( float gain )
*/
float CListenerAL::getGain() const
{
- return CSoundDriverAL::getInstance()->getGain();
-// ALfloat gain;
-//#ifdef NL_OS_WINDOWS
-// alGetListenerf( AL_GAIN, &gain );
-//#else
-// alGetListenerfv( AL_GAIN, &gain );
-//#endif
-// alTestError();
-// return gain;
+ ALfloat gain;
+#ifdef NL_OS_WINDOWS
+ alGetListenerf( AL_GAIN, &gain );
+#else
+ alGetListenerfv( AL_GAIN, &gain );
+#endif
+ alTestError();
+ return gain;
}
diff --git a/code/nel/src/sound/driver/openal/music_channel_al.cpp b/code/nel/src/sound/driver/openal/music_channel_al.cpp
deleted file mode 100644
index b1849b33e..000000000
--- a/code/nel/src/sound/driver/openal/music_channel_al.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-// NeL - MMORPG Framework
-// 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 .
-
-#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(_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 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 */
diff --git a/code/nel/src/sound/driver/openal/music_channel_al.h b/code/nel/src/sound/driver/openal/music_channel_al.h
deleted file mode 100644
index 157c18810..000000000
--- a/code/nel/src/sound/driver/openal/music_channel_al.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// NeL - MMORPG Framework
-// 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 .
-
-#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 */
diff --git a/code/nel/src/sound/driver/openal/sound_driver_al.cpp b/code/nel/src/sound/driver/openal/sound_driver_al.cpp
index ec4f70839..22b1eaf3f 100644
--- a/code/nel/src/sound/driver/openal/sound_driver_al.cpp
+++ b/code/nel/src/sound/driver/openal/sound_driver_al.cpp
@@ -16,7 +16,6 @@
#include "stdopenal.h"
#include "sound_driver_al.h"
-#include "music_channel_al.h"
#include "buffer_al.h"
#include "listener_al.h"
#include "source_al.h"
@@ -174,7 +173,7 @@ uint32 NLSOUND_interfaceVersion ()
*/
CSoundDriverAL::CSoundDriverAL(ISoundDriver::IStringMapperProvider *stringMapper)
: _StringMapper(stringMapper), _AlDevice(NULL), _AlContext(NULL),
-_NbExpBuffers(0), _NbExpSources(0), _RolloffFactor(1.f), _MasterGain(1.f)
+_NbExpBuffers(0), _NbExpSources(0), _RolloffFactor(1.f)
{
alExtInit();
}
@@ -184,21 +183,13 @@ _NbExpBuffers(0), _NbExpSources(0), _RolloffFactor(1.f), _MasterGain(1.f)
*/
CSoundDriverAL::~CSoundDriverAL()
{
- // Release internal resources of all remaining IMusicChannel instances
- if (_MusicChannels.size())
- {
- nlwarning("AL: _MusicChannels.size(): '%u'", (uint32)_MusicChannels.size());
- set::iterator it(_MusicChannels.begin()), end(_MusicChannels.end());
- for (; it != end; ++it) delete *it;
- _MusicChannels.clear();
- }
// Remove the allocated (but not exported) source and buffer names-
// Release internal resources of all remaining ISource instances
if (_Sources.size())
{
nlwarning("AL: _Sources.size(): '%u'", (uint32)_Sources.size());
set::iterator it(_Sources.begin()), end(_Sources.end());
- for (; it != end; ++it) it->release();
+ for (; it != end; ++it) (*it)->release(); // CSourceAL will be deleted by user
_Sources.clear();
}
if (!_Buffers.empty()) alDeleteBuffers(compactAliveNames(_Buffers, alIsBuffer), &*_Buffers.begin());
@@ -207,7 +198,7 @@ CSoundDriverAL::~CSoundDriverAL()
{
nlwarning("AL: _Effects.size(): '%u'", (uint32)_Effects.size());
set::iterator it(_Effects.begin()), end(_Effects.end());
- for (; it != end; ++it) it->release();
+ for (; it != end; ++it) (*it)->release(); // CEffectAL will be deleted by user
_Effects.clear();
}
@@ -622,9 +613,6 @@ void CSoundDriverAL::commit3DChanges()
for (std::set::iterator it(_Sources.begin()), end(_Sources.end()); it != end; ++it)
(*it)->updateManualRolloff();
}
-
- // update the music (XFade etc...)
- updateMusic();
}
/// Write information about the driver to the output stream.
@@ -652,23 +640,6 @@ void CSoundDriverAL::displayBench(NLMISC::CLog *log)
NLMISC::CHTimer::display(log, CHTimer::TotalTime);
}
-/** Get music info. Returns false if the song is not found or the function is not implemented.
- * \param filepath path to file, CPath::lookup done by driver
- * \param artist returns the song artist (empty if not available)
- * \param title returns the title (empty if not available)
- */
-bool CSoundDriverAL::getMusicInfo(const std::string &filepath, std::string &artist, std::string &title)
-{
- // add support for additional non-standard music file types info here
- return IMusicBuffer::getInfo(filepath, artist, title);
-}
-
-void CSoundDriverAL::updateMusic()
-{
- set::iterator it(_MusicChannels.begin()), end(_MusicChannels.end());
- for (; it != end; ++it) (*it)->update();
-}
-
/// Remove a buffer
void CSoundDriverAL::removeBuffer(CBufferAL *buffer)
{
@@ -691,35 +662,6 @@ void CSoundDriverAL::removeEffect(CEffectAL *effect)
else nlwarning("AL: removeEffect already called");
}
-/// Create a music channel
-IMusicChannel *CSoundDriverAL::createMusicChannel()
-{
- CMusicChannelAL *music_channel = new CMusicChannelAL(this);
- _MusicChannels.insert(music_channel);
- return static_cast(music_channel);
-}
-
-/// (Internal) Remove a music channel (should be called by the destructor of the music channel class).
-void CSoundDriverAL::removeMusicChannel(CMusicChannelAL *musicChannel)
-{
- if (_MusicChannels.find(musicChannel) != _MusicChannels.end()) _MusicChannels.erase(musicChannel);
- else nlwarning("AL: removeMusicChannel already called");
-}
-
-/// Set the gain
-void CSoundDriverAL::setGain( float gain )
-{
- clamp(gain, 0.f, 1.f);
- _MasterGain= gain;
- // TODO: update all sources in not using manual rollof ?
-}
-
-/// Get the gain
-float CSoundDriverAL::getGain()
-{
- return _MasterGain;
-}
-
/// Delete a buffer or a source
bool CSoundDriverAL::deleteItem( ALuint name, TDeleteFunctionAL aldeletefunc, vector& names )
{
diff --git a/code/nel/src/sound/driver/openal/sound_driver_al.h b/code/nel/src/sound/driver/openal/sound_driver_al.h
index 50bffa379..154bc6d78 100644
--- a/code/nel/src/sound/driver/openal/sound_driver_al.h
+++ b/code/nel/src/sound/driver/openal/sound_driver_al.h
@@ -19,13 +19,11 @@
#include
-namespace NLSOUND
-{
+namespace NLSOUND {
class CBufferAL;
class CListenerAL;
class CSourceAL;
class CEffectAL;
- class CMusicChannelAL;
// alGenBuffers, alGenSources
//typedef ALAPI ALvoid ALAPIENTRY (*TGenFunctionAL) ( ALsizei, ALuint* );
@@ -82,8 +80,6 @@ private:
std::set _Sources;
// Allocated effects
std::set _Effects;
- /// Array with the allocated music channels created by client code.
- std::set _MusicChannels;
// Number of exported buffers (including any deleted buffers)
uint _NbExpBuffers;
// Number of exported sources (including any deleted sources)
@@ -101,6 +97,10 @@ public:
/// Destructor
virtual ~CSoundDriverAL();
+ inline ALCdevice *getAlDevice() { return _AlDevice; }
+ inline ALCcontext *getAlContext() { return _AlContext; }
+ inline float getRolloffFactor() { return _RolloffFactor; }
+
/// Return a list of available devices for the user. The value at index 0 is empty, and is used for automatic device selection.
virtual void getDevices(std::vector &devices);
/// Initialize the driver with a user selected device. If device.empty(), the default or most appropriate device is used.
@@ -111,73 +111,46 @@ public:
/// Return if an option is enabled (including those that cannot be disabled on this driver).
virtual bool getOption(TSoundOptions option);
- /// Commit all the changes made to 3D settings of listener and sources
- virtual void commit3DChanges();
-
+ /// Create a sound buffer
+ virtual IBuffer *createBuffer();
/// Create the listener instance
virtual IListener *createListener();
- /// Create a source, destroy with delete
+ /// Create a source
virtual ISource *createSource();
- /// Create a sound buffer, destroy with delete
- virtual IBuffer *createBuffer();
/// Create a reverb effect
virtual IReverbEffect *createReverbEffect();
/// Return the maximum number of sources that can created
virtual uint countMaxSources();
/// Return the maximum number of effects that can be created
virtual uint countMaxEffects();
-
- /// Write information about the driver to the output stream.
- virtual void writeProfile(std::string& /* out */);
-
+
virtual void startBench();
virtual void endBench();
virtual void displayBench(NLMISC::CLog * /* log */);
- /// Create a music channel, destroy with destroyMusicChannel.
- virtual IMusicChannel *createMusicChannel();
-
- /** Get music info. Returns false if the song is not found or the function is not implemented.
- * \param filepath path to file, CPath::lookup done by driver
- * \param artist returns the song artist (empty if not available)
- * \param title returns the title (empty if not available)
- */
- virtual bool getMusicInfo(const std::string &filepath, std::string &artist, std::string &title);
-
- /// Get audio/container extensions that are supported natively by the driver implementation.
- virtual void getMusicExtensions(std::vector & /* extensions */) const { }
- /// Return if a music extension is supported by the driver's music channel.
- virtual bool isMusicExtensionSupported(const std::string & /* extension */) const { return false; }
-
- ALCdevice *getAlDevice() { return _AlDevice; }
- ALCcontext *getAlContext() { return _AlContext; }
- float getRolloffFactor() { return _RolloffFactor; }
/// Change the rolloff factor and apply to all sources
void applyRolloffFactor(float f);
+ /// Commit all the changes made to 3D settings of listener and sources
+ virtual void commit3DChanges();
+
+ /// Write information about the driver to the output stream.
+ virtual void writeProfile(std::string& /* out */);
+
/// Remove a buffer
void removeBuffer(CBufferAL *buffer);
/// Remove a source
void removeSource(CSourceAL *source);
/// Remove an effect
void removeEffect(CEffectAL *effect);
- /// (Internal) Remove music channel (should be called by the destructor of the music channel class).
- void removeMusicChannel(CMusicChannelAL *musicChannel);
- /** Set the gain (volume value inside [0 , 1]). (default: 1)
- * 0.0 -> silence
- * 0.5 -> -6dB
- * 1.0 -> no attenuation
- * values > 1 (amplification) not supported by most drivers
- */
- void setGain( float gain );
-
- /// Get the gain
- float getGain();
+ /// Get audio/container extensions that are supported natively by the driver implementation.
+ virtual void getMusicExtensions(std::vector & /* extensions */) const { }
+ /// Return if a music extension is supported by the driver's music channel.
+ virtual bool isMusicExtensionSupported(const std::string & /* extension */) const { return false; }
protected:
- void updateMusic();
/// Allocate nb new buffers or sources
void allocateNewItems( TGenFunctionAL algenfunc, TTestFunctionAL altestfunc,
@@ -195,9 +168,6 @@ protected:
/// Delete a buffer or a source
bool deleteItem( ALuint name, TDeleteFunctionAL aldeletefunc, std::vector& names );
-
- /// Master Volume [0,1]
- float _MasterGain;
};
diff --git a/code/nel/src/sound/driver/openal/source_al.cpp b/code/nel/src/sound/driver/openal/source_al.cpp
index c207f0d31..19ef1780f 100644
--- a/code/nel/src/sound/driver/openal/source_al.cpp
+++ b/code/nel/src/sound/driver/openal/source_al.cpp
@@ -15,55 +15,36 @@
// along with this program. If not, see .
#include "stdopenal.h"
-#include "source_al.h"
#include "sound_driver_al.h"
#include "listener_al.h"
#include "effect_al.h"
#include "buffer_al.h"
+#include "source_al.h"
#include "ext_al.h"
using namespace std;
using namespace NLMISC;
-namespace NLSOUND
+namespace NLSOUND {
+
+CSourceAL::CSourceAL(CSoundDriverAL *soundDriver) :
+_SoundDriver(NULL), _Buffer(NULL), _Source(AL_NONE),
+_DirectFilter(AL_FILTER_NULL), _EffectFilter(AL_FILTER_NULL),
+_IsPlaying(false), _IsPaused(false), _StartTime(0),
+_Pos(0.0f, 0.0f, 0.0f), _Gain(NLSOUND_DEFAULT_GAIN), _Alpha(1.0),
+_MinDistance(1.0f), _MaxDistance(numeric_limits::max()),
+_Effect(NULL), _Direct(true),
+_DirectGain(NLSOUND_DEFAULT_DIRECT_GAIN), _EffectGain(NLSOUND_DEFAULT_EFFECT_GAIN),
+_DirectFilterType(ISource::FilterLowPass), _EffectFilterType(ISource::FilterLowPass),
+_DirectFilterEnabled(false), _EffectFilterEnabled(false),
+_DirectFilterPassGain(NLSOUND_DEFAULT_FILTER_PASS_GAIN), _EffectFilterPassGain(NLSOUND_DEFAULT_FILTER_PASS_GAIN)
{
-
-CSourceAL::CSourceAL(CSoundDriverAL *soundDriver):ISource(), _SoundDriver(NULL), _Source(AL_NONE),
- _DirectFilter(AL_FILTER_NULL), _EffectFilter(AL_FILTER_NULL)
-{
- _IsPlaying = false;
- _IsPaused = false;
- _StartTime = 0;
-
- _Type = SourceSound;
- _Buffer = NULL;
- _BuffersMax = 0;
- _BufferSize = 32768;
-
- _PosRelative = false;
- _Gain = NLSOUND_DEFAULT_GAIN;
- _Alpha = 0.0;
- _Pos = CVector::Null;
- _MinDistance = 1.0f;
- _MaxDistance = numeric_limits::max();
-
- _Effect = NULL;
- _Direct = true;
- _DirectGain = NLSOUND_DEFAULT_DIRECT_GAIN;
- _EffectGain = NLSOUND_DEFAULT_EFFECT_GAIN;
- _DirectFilterType = ISource::FilterLowPass;
- _EffectFilterType = ISource::FilterLowPass;
- _DirectFilterEnabled = false;
- _EffectFilterEnabled = false;
- _DirectFilterPassGain = NLSOUND_DEFAULT_FILTER_PASS_GAIN;
- _EffectFilterPassGain = NLSOUND_DEFAULT_FILTER_PASS_GAIN;
-
// create the al source
alGenSources(1, &_Source);
alTestError();
-
+
// configure rolloff
- if (!soundDriver || soundDriver->getOption(ISoundDriver::OptionManualRolloff))
+ if (soundDriver->getOption(ISoundDriver::OptionManualRolloff))
{
alSourcef(_Source, AL_ROLLOFF_FACTOR, 0);
alTestError();
@@ -73,16 +54,15 @@ CSourceAL::CSourceAL(CSoundDriverAL *soundDriver):ISource(), _SoundDriver(NULL),
alSourcef(_Source, AL_ROLLOFF_FACTOR, soundDriver->getRolloffFactor());
alTestError();
}
-
+
// create filters
- if (soundDriver && soundDriver->getOption(ISoundDriver::OptionEnvironmentEffects))
+ if (soundDriver->getOption(ISoundDriver::OptionEnvironmentEffects))
{
alGenFilters(1, &_DirectFilter);
alFilteri(_DirectFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
alFilterf(_DirectFilter, AL_LOWPASS_GAIN, NLSOUND_DEFAULT_DIRECT_GAIN);
alFilterf(_DirectFilter, AL_LOWPASS_GAINHF, NLSOUND_DEFAULT_FILTER_PASS_GAIN);
alTestError();
-
alGenFilters(1, &_EffectFilter);
alFilteri(_EffectFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
alFilterf(_EffectFilter, AL_LOWPASS_GAIN, NLSOUND_DEFAULT_EFFECT_GAIN);
@@ -103,8 +83,6 @@ CSourceAL::~CSourceAL()
void CSourceAL::release()
{
- unqueueBuffers();
- removeBuffers();
if (_Source != AL_NONE) { alDeleteSources(1, &_Source); _Source = AL_NONE; }
if (_DirectFilter != AL_FILTER_NULL) { alDeleteFilters(1, &_DirectFilter); _DirectFilter = AL_FILTER_NULL; }
if (_EffectFilter != AL_FILTER_NULL) { alDeleteFilters(1, &_EffectFilter); _EffectFilter = AL_FILTER_NULL; }
@@ -114,37 +92,13 @@ void CSourceAL::release()
/// (Internal) Update the 3d changes.
void CSourceAL::updateManualRolloff()
{
- CVector pos = getPos();
-
- // make relative to listener (if not already!)
- if (!_PosRelative)
- pos -= CListenerAL::getInstance()->getPos();
-
- float sqrdist = pos.sqrnorm();
- float rolloff = ISource::computeManualRolloff(_Alpha, sqrdist, _MinDistance, _MaxDistance);
- float volume = _Gain * rolloff;
-
- // apply SFX volume
- if (_SoundDriver && _Type == SourceSound)
- volume *= _SoundDriver->getGain();
-
- // set the attenuated volume
- alSourcef(_Source, AL_GAIN, volume);
+ CVector distanceVector = _Pos - CListenerAL::getInstance()->getPos();
+ float distanceSquare = distanceVector.sqrnorm();
+ float rolloff = ISource::computeManualRolloff(_Alpha, distanceSquare, _MinDistance, _MaxDistance);
+ alSourcef(_Source, AL_GAIN, _Gain * rolloff);
alTestError();
}
-/// Set type of the source
-void CSourceAL::setType(TSourceType type)
-{
- _Type = type;
-}
-
-/// Get type of the source
-TSourceType CSourceAL::getType() const
-{
- return _Type;
-}
-
/// Enable or disable streaming mode. Source must be stopped to call this.
void CSourceAL::setStreaming(bool /* streaming */)
{
@@ -199,11 +153,10 @@ void CSourceAL::submitStreamingBuffer(IBuffer *buffer)
CBufferAL *bufferAL = static_cast(buffer);
ALuint bufferName = bufferAL->bufferName();
nlassert(bufferName);
-
- // queue the buffer
alSourceQueueBuffers(_Source, 1, &bufferName);
alTestError();
-
+ _QueuedBuffers.push(bufferAL);
+
// Resume playback if the internal OpenAL source stopped due to buffer underrun.
ALint srcstate;
alGetSourcei(_Source, AL_SOURCE_STATE, &srcstate);
@@ -218,11 +171,23 @@ void CSourceAL::submitStreamingBuffer(IBuffer *buffer)
/// Return the amount of buffers in the queue (playing and waiting). 3 buffers is optimal.
uint CSourceAL::countStreamingBuffers() const
{
+ // a bit ugly here, but makes a much easier/simpler implementation on both drivers
+ ALint buffersProcessed;
+ alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed);
+ while (buffersProcessed)
+ {
+ ALuint bufferName = _QueuedBuffers.front()->bufferName();
+ alSourceUnqueueBuffers(_Source, 1, &bufferName);
+ alTestError();
+ const_cast &>(_QueuedBuffers).pop();
+ --buffersProcessed;
+ }
// return how many are left in the queue
- ALint buffersQueued;
- alGetSourcei(_Source, AL_BUFFERS_QUEUED, &buffersQueued);
- alTestError();
- return (uint)buffersQueued;
+ //ALint buffersQueued;
+ //alGetSourcei(_SourceName, AL_BUFFERS_QUEUED, &buffersQueued);
+ //alTestError();
+ //return (uint)buffersQueued;
+ return (uint)_QueuedBuffers.size();
}
/// Set looping on/off for future playbacks (default: off)
@@ -260,7 +225,7 @@ bool CSourceAL::play()
_IsPaused = false;
alSourcePlay(_Source);
_IsPlaying = true;
- _StartTime = CTime::getLocalTime();
+ _StartTime = CTime::getLocalTime(); // TODO: Played time should freeze when buffering fails, and be calculated based on the number of buffers played plus passed time. This is necessary for synchronizing animation with sound.
return true;
// Streaming mode
//nlwarning("AL: Cannot play null buffer; streaming not implemented" );
@@ -288,8 +253,14 @@ void CSourceAL::stop()
_IsPaused = false;
alSourceStop(_Source);
alTestError();
-
- unqueueBuffers();
+ // unqueue buffers
+ while (_QueuedBuffers.size())
+ {
+ ALuint bufferName = _QueuedBuffers.front()->bufferName();
+ alSourceUnqueueBuffers(_Source, 1, &bufferName);
+ _QueuedBuffers.pop();
+ alTestError();
+ }
// Streaming mode
//nlwarning("AL: Cannot stop null buffer; streaming not implemented" );
//nlstop;
@@ -379,8 +350,7 @@ bool CSourceAL::isPaused() const
uint32 CSourceAL::getTime()
{
if (!_StartTime) return 0;
-
- return (uint32)(CTime::getLocalTime() - _StartTime);
+ return (uint32)(CTime::getLocalTime() - _StartTime);
}
/// Set the position vector.
@@ -438,16 +408,9 @@ void CSourceAL::getDirection( NLMISC::CVector& dir ) const
void CSourceAL::setGain(float gain)
{
_Gain = std::min(std::max(gain, NLSOUND_MIN_GAIN), NLSOUND_MAX_GAIN);
-
- if ((_SoundDriver == NULL) || !_SoundDriver->getOption(ISoundDriver::OptionManualRolloff))
+ if (!_SoundDriver->getOption(ISoundDriver::OptionManualRolloff))
{
- float gain = _Gain;
-
- // apply SFX volume
- if (_SoundDriver && _Type == SourceSound)
- gain *= _SoundDriver->getGain();
-
- alSourcef(_Source, AL_GAIN, gain);
+ alSourcef(_Source, AL_GAIN, _Gain);
alTestError();
}
}
@@ -481,7 +444,6 @@ float CSourceAL::getPitch() const
/// Set the source relative mode. If true, positions are interpreted relative to the listener position.
void CSourceAL::setSourceRelativeMode( bool mode )
{
- _PosRelative = mode;
alSourcei(_Source, AL_SOURCE_RELATIVE, mode?AL_TRUE:AL_FALSE );
alTestError();
}
@@ -489,29 +451,19 @@ void CSourceAL::setSourceRelativeMode( bool mode )
/// Get the source relative mode (3D mode only)
bool CSourceAL::getSourceRelativeMode() const
{
- return _PosRelative;
-// ALint b;
-// alGetSourcei(_Source, AL_SOURCE_RELATIVE, &b );
-// alTestError();
-// return (b==AL_TRUE);
+ ALint b;
+ alGetSourcei(_Source, AL_SOURCE_RELATIVE, &b );
+ alTestError();
+ return (b==AL_TRUE);
}
/// Set the min and max distances (3D mode only)
void CSourceAL::setMinMaxDistances( float mindist, float maxdist, bool /* deferred */)
{
nlassert( (mindist >= 0.0f) && (maxdist >= 0.0f) );
-
- static float maxSqrt = sqrt(std::numeric_limits::max());
- if (maxdist >= maxSqrt)
- {
- nlwarning("SOUND_DEV (OpenAL): Ridiculously high max distance set on source");
- maxdist = maxSqrt;
- }
-
_MinDistance = mindist;
_MaxDistance = maxdist;
-
- if (!_SoundDriver || !_SoundDriver->getOption(ISoundDriver::OptionManualRolloff))
+ if (!_SoundDriver->getOption(ISoundDriver::OptionManualRolloff))
{
alSourcef(_Source, AL_REFERENCE_DISTANCE, mindist);
alSourcef(_Source, AL_MAX_DISTANCE, maxdist);
@@ -813,122 +765,4 @@ float CSourceAL::getEffectFilterPassGain() const
return _EffectFilterPassGain;
}
-/// Get already processed buffers and unqueue them
-void CSourceAL::getProcessedStreamingBuffers(std::vector &buffers)
-{
- // get the number of processed buffers
- ALint buffersProcessed;
- alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed);
- alTestError();
-
- // exit if more processed buffer than allocated ones
- if ((uint)buffersProcessed > _BuffersMax) return;
-
- // unqueue all previously processed buffers and get their name
- alSourceUnqueueBuffers(_Source, buffersProcessed, &(_BuffersName[0]));
- alTestError();
-
- // add each processed buffer to the array
- for(uint i = 0; i < (uint)buffersProcessed; ++i)
- {
- // if buffer is found, return it
- std::map::const_iterator it = _Buffers.find(_BuffersName[i]);
- if (it != _Buffers.end())
- buffers.push_back(it->second);
- }
-}
-
-/// Get all existing buffers
-void CSourceAL::getStreamingBuffers(std::vector &buffers)
-{
- std::map::const_iterator it = _Buffers.begin(), iend = _Buffers.end();
- while(it != iend)
- {
- buffers.push_back(it->second);
- ++it;
- }
-}
-
-/// Unqueue all buffers
-void CSourceAL::unqueueBuffers()
-{
- // get count of buffers in queue
- uint count = countStreamingBuffers();
-
- if (count > 0)
- {
- // unqueue all of them
- alSourceUnqueueBuffers(_Source, count, &(_BuffersName[0]));
- alTestError();
- }
-}
-
-/// Delete all allocated buffers
-void CSourceAL::removeBuffers()
-{
- // delete each buffer
- std::map::const_iterator it = _Buffers.begin(), iend = _Buffers.end();
- while(it != iend)
- {
- delete it->second;
- ++it;
- }
-
- _Buffers.clear();
-}
-
-/// Get available streaming buffers count
-uint CSourceAL::getStreamingBuffersMax() const
-{
- return _BuffersMax;
-}
-
-/// Set available streaming buffers count and allocate them
-void CSourceAL::setStreamingBuffersMax(uint buffers)
-{
- // remember previous value
- uint oldBuffersMax = _BuffersMax;
-
- _BuffersMax = buffers;
-
- // resize the temporary buffer names array
- _BuffersName.resize(buffers);
-
- // remove all buffers
- unqueueBuffers();
- removeBuffers();
-
- for(uint i = 0; i < _BuffersMax; ++i)
- {
- try
- {
- // create a new buffer
- CBufferAL *buffer = static_cast(_SoundDriver->createBuffer());
- // use StorageSoftware because buffers will be reused
- // deleting and recreating them is a waste of time
- buffer->setStorageMode(IBuffer::StorageSoftware);
- _Buffers[buffer->bufferName()] = buffer;
- }
- catch(const ESoundDriverGenBuf &e)
- {
- nlwarning("Cannot create %d buffers. openal fails after %d buffers", buffers, i);
- _BuffersMax = i;
- _BuffersName.resize(i);
- break;
- }
- }
-}
-
-/// Set the default size for streaming buffers
-void CSourceAL::setStreamingBufferSize(uint size)
-{
- _BufferSize = size;
-}
-
-/// Get the default size for streaming buffers
-uint CSourceAL::getStreamingBufferSize() const
-{
- return _BufferSize;
-}
-
} // NLSOUND
diff --git a/code/nel/src/sound/driver/openal/source_al.h b/code/nel/src/sound/driver/openal/source_al.h
index b5611b997..cae9ff042 100644
--- a/code/nel/src/sound/driver/openal/source_al.h
+++ b/code/nel/src/sound/driver/openal/source_al.h
@@ -17,17 +17,14 @@
#ifndef NL_SOURCE_AL_H
#define NL_SOURCE_AL_H
-#include "nel/sound/driver/source.h"
+#include
-namespace NLSOUND
-{
+namespace NLSOUND {
class IBuffer;
class CBufferAL;
class CSoundDriverAL;
class CEffectAL;
- enum TSourceType { SourceSound, SourceMusic };
-
/**
* OpenAL sound source
*
@@ -50,29 +47,19 @@ private:
/// Sound driver
CSoundDriverAL *_SoundDriver;
+ /// Assigned buffer object
+ CBufferAL *_Buffer;
+ std::queue _QueuedBuffers;
+
/// AL Handles
ALuint _Source;
ALuint _DirectFilter, _EffectFilter;
-
- /// Assigned buffer object
- CBufferAL *_Buffer;
- /// Queued buffers map (uint is buffer name)
- std::map _Buffers;
-
- /// Temporary queued buffers array
- std::vector _BuffersName;
- /// Max count of queued buffers allowed
- uint _BuffersMax;
- /// Default size of a buffer
- uint _BufferSize;
-
- /// Position is relative to listener
- bool _PosRelative;
-
+
/// Playing status
bool _IsPlaying;
bool _IsPaused;
- NLMISC::TTime _StartTime;
+ NLMISC::TTime _StartTime;
+
NLMISC::CVector _Pos;
float _Gain;
double _Alpha;
@@ -90,9 +77,6 @@ private:
TFilter _DirectFilterType, _EffectFilterType;
bool _DirectFilterEnabled, _EffectFilterEnabled;
float _DirectFilterPassGain, _EffectFilterPassGain;
-
- /// Source type can be SourceSound or SourceMusic
- TSourceType _Type;
public:
/// Constructor
@@ -104,13 +88,8 @@ public:
void release();
/// Return the OpenAL source name
- ALuint getSource() const { return _Source; }
-
- /// Set type of the source
- void setType(TSourceType type);
- /// Get type of the source
- TSourceType getType() const;
-
+ inline ALuint getSource() const { return _Source; }
+
/// (Internal) Set the effect send for this source, NULL to disable.
void setEffect(CEffectAL *effect);
/// (Internal) Setup the direct send filter.
@@ -275,22 +254,6 @@ public:
virtual float getEffectFilterPassGain() const;
//@}
- /// Get already processed buffers and unqueue them
- void getProcessedStreamingBuffers(std::vector &buffers);
- /// Get all existing buffers
- void getStreamingBuffers(std::vector &buffers);
- /// Unqueue all buffers
- void unqueueBuffers();
- /// Delete all allocated buffers
- void removeBuffers();
- /// Get available streaming buffers count
- uint getStreamingBuffersMax() const;
- /// Set available streaming buffers count and allocate them
- void setStreamingBuffersMax(uint max);
- /// Set the default size for streaming buffers
- void setStreamingBufferSize(uint size);
- /// Get the default size for streaming buffers
- uint getStreamingBufferSize() const;
};
} // NLSOUND