From b2dd082e3ac1c19bdd18da7d75fd89023b380c0b Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 27 Jul 2010 18:56:34 +0200 Subject: [PATCH] Changed: #1030 Implement music streaming in OpenAL driver --- .../sound/driver/openal/sound_driver_al.cpp | 65 ++++++++++++++++++- .../src/sound/driver/openal/sound_driver_al.h | 58 ++++++++++------- 2 files changed, 99 insertions(+), 24 deletions(-) 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 8a3d4ce93..25f8dfa7c 100644 --- a/code/nel/src/sound/driver/openal/sound_driver_al.cpp +++ b/code/nel/src/sound/driver/openal/sound_driver_al.cpp @@ -16,6 +16,7 @@ #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" @@ -49,6 +50,7 @@ void alTestError() case AL_INVALID_VALUE: nlerror("OpenAL: Invalid value"); case AL_INVALID_OPERATION: nlerror("OpenAL: Invalid operation"); case AL_OUT_OF_MEMORY: nlerror("OpenAL: Out of memory"); + default: nlerror("OpenAL: Unknown error %x", errcode); } } #endif @@ -181,13 +183,21 @@ _NbExpBuffers(0), _NbExpSources(0), _RolloffFactor(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) delete *it; _Sources.clear(); } if (!_Buffers.empty()) alDeleteBuffers(compactAliveNames(_Buffers, alIsBuffer), &*_Buffers.begin()); @@ -196,7 +206,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) delete *it; _Effects.clear(); } @@ -615,6 +625,42 @@ void CSoundDriverAL::commit3DChanges() } } +/// Write information about the driver to the output stream. +void CSoundDriverAL::writeProfile(std::string& out) +{ + // TODO +} + +// Does not create a sound loader .. what does it do then? +void CSoundDriverAL::startBench() +{ + NLMISC::CHTimer::startBench(); +} + +void CSoundDriverAL::endBench() +{ + NLMISC::CHTimer::endBench(); +} + +void CSoundDriverAL::displayBench(NLMISC::CLog *log) +{ + NLMISC::CHTimer::displayHierarchicalByExecutionPathSorted(log, CHTimer::TotalTime, true, 48, 2); + NLMISC::CHTimer::displayHierarchical(log, true, 48, 2); + NLMISC::CHTimer::displayByExecutionPath(log, CHTimer::TotalTime); + 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); +} + /// Remove a buffer void CSoundDriverAL::removeBuffer(CBufferAL *buffer) { @@ -637,6 +683,21 @@ 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"); +} + /// 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 3260acb1f..7e0dbf1a8 100644 --- a/code/nel/src/sound/driver/openal/sound_driver_al.h +++ b/code/nel/src/sound/driver/openal/sound_driver_al.h @@ -24,6 +24,7 @@ namespace NLSOUND { class CListenerAL; class CSourceAL; class CEffectAL; + class CMusicChannelAL; // alGenBuffers, alGenSources //typedef ALAPI ALvoid ALAPIENTRY (*TGenFunctionAL) ( ALsizei, ALuint* ); @@ -80,6 +81,8 @@ 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) @@ -97,10 +100,6 @@ 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,44 +110,59 @@ public: /// Return if an option is enabled (including those that cannot be disabled on this driver). virtual bool getOption(TSoundOptions option); - /// Create a sound buffer - virtual IBuffer *createBuffer(); + /// Commit all the changes made to 3D settings of listener and sources + virtual void commit3DChanges(); + /// Create the listener instance virtual IListener *createListener(); - /// Create a source + /// Create a source, destroy with delete 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(); - - virtual void startBench() { /* todo */ } - virtual void endBench() { /* todo */ } - virtual void displayBench(NLMISC::CLog * /* log */) { /* TODO */ } + /// 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); - - /// 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; } + /// (Internal) Remove music channel (should be called by the destructor of the music channel class). + void removeMusicChannel(CMusicChannelAL *musicChannel); protected: