X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fsound%2Fsoundmgr_openal.hxx;h=749d84272bffd28f78e313f96d9819a058c375e7;hb=d75ce1e12ee4fba106bc6595a2fb1b3b50ccbbc1;hp=dd4d3913144872add74c5602946e286e5a4be0c2;hpb=c2c0e19305ea3bcf8da63a42a05a70d106c394ae;p=simgear.git diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index dd4d3913..749d8427 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -4,8 +4,10 @@ // 2001 // // C++-ified by Curtis Olson, started March 2001. +// Modified for the new SoundSystem by Erik Hofman, October 2009 // // Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt +// Copyright (C) 2009 Erik Hofman // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -18,8 +20,8 @@ // General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -33,212 +35,292 @@ #ifndef _SG_SOUNDMGR_OPENAL_HXX #define _SG_SOUNDMGR_OPENAL_HXX 1 -#ifndef __cplusplus -# error This library requires C++ -#endif - -#include - -#include STL_STRING +#include +#include #include -#if defined( __APPLE__ ) +#if defined(__APPLE__) # include # include +#elif defined(OPENALSDK) +# include +# include #else # include # include #endif -#include "sample_openal.hxx" +#include +#include +#include + +#include "sample_group.hxx" -SG_USING_STD(map); -SG_USING_STD(string); +struct refUint { + unsigned int refctr; + ALuint id; + refUint() { refctr = 0; id = (ALuint)-1; }; + refUint(ALuint i) { refctr = 1; id = i; }; + ~refUint() {}; +}; -typedef map < string, SGSharedPtr > sample_map; -typedef sample_map::iterator sample_map_iterator; -typedef sample_map::const_iterator const_sample_map_iterator; +typedef std::map < std::string, refUint > buffer_map; +typedef buffer_map::iterator buffer_map_iterator; +typedef buffer_map::const_iterator const_buffer_map_iterator; +typedef std::map < std::string, SGSharedPtr > sample_group_map; +typedef sample_group_map::iterator sample_group_map_iterator; +typedef sample_group_map::const_iterator const_sample_group_map_iterator; /** - * Manage a collection of SGSoundSample instances + * Manage a collection of SGSampleGroup instances */ -class SGSoundMgr +class SGSoundMgr : public SGSubsystem { - - ALCdevice *dev; - ALCcontext *context; - - // Position of the listener. - ALfloat listener_pos[3]; - - // Velocity of the listener. - ALfloat listener_vel[3]; - - // Orientation of the listener. (first 3 elements are "at", second - // 3 are "up") - ALfloat listener_ori[6]; - - sample_map samples; - - bool working; - double safety; - public: SGSoundMgr(); ~SGSoundMgr(); + void init(const char *devname = NULL); + void bind(); + void unbind(); + void update(double dt); + + void suspend(); + void resume(); + void stop(); + + inline void reinit() { stop(); init(); } /** - * (re) initialize the sound manager. + * Test is the sound manager is in a working condition. + * @return true is the sound manager is working */ - void init(); - + inline bool is_working() const { return _working; } /** - * Bind properties for the sound manager. + * Set the sound manager to a working condition. */ - void bind(); + void activate(); + /** + * Test is the sound manager is in an active and working condition. + * @return true is the sound manager is active + */ + inline bool is_active() const { return _active; } /** - * Unbind properties for the sound manager. + * Register a sample group to the sound manager. + * @para sgrp Pointer to a sample group to add + * @param refname Reference name of the sample group + * @return true if successful, false otherwise */ - void unbind(); + bool add( SGSampleGroup *sgrp, const std::string& refname ); + /** + * Remove a sample group from the sound manager. + * @param refname Reference name of the sample group to remove + * @return true if successful, false otherwise + */ + bool remove( const std::string& refname ); /** - * Run the audio scheduler. + * Test if a specified sample group is registered at the sound manager + * @param refname Reference name of the sample group test for + * @return true if the specified sample group exists */ - void update(double dt); + bool exists( const std::string& refname ); + /** + * Find a specified sample group in the sound manager + * @param refname Reference name of the sample group to find + * @return A pointer to the SGSampleGroup + */ + SGSampleGroup *find( const string& refname, bool create = false ); /** - * Pause all sounds. + * Set the Cartesian position of the sound manager. + * @param pos OpenAL listener position */ - void pause(); + void set_position( const SGVec3d& pos, const SGGeod& pos_geod ) { + _base_pos = pos; _geod_pos = pos_geod; _changed = true; + } + void set_position_offset( const SGVec3d& pos ) { + _offset_pos = pos; _changed = true; + } /** - * Resume all sounds. + * Get the position of the sound manager. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @return OpenAL listener position */ - void resume(); - + SGVec3d& get_position() { return _absolute_pos; } /** - * is audio working? + * Set the velocity vector (in meters per second) of the sound manager + * This is the horizontal local frame; x=north, y=east, z=down + * @param Velocity vector */ - inline bool is_working() const { return working; } + void set_velocity( const SGVec3d& vel ) { + _velocity = vel; _changed = true; + } /** - * reinitialize the sound manager + * Get the velocity vector of the sound manager + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @return Velocity vector of the OpenAL listener */ - inline void reinit() { init(); } + inline SGVec3f get_velocity() { return toVec3f(_velocity); } /** - * add a sound effect, return true if successful + * Set the orientation of the sound manager + * @param ori Quaternation containing the orientation information */ - bool add( SGSoundSample *sound, const string& refname); + void set_orientation( const SGQuatd& ori ) { + _orientation = ori; _changed = true; + } - /** - * remove a sound effect, return true if successful + /** + * Get the orientation of the sound manager + * @return Quaternation containing the orientation information */ - bool remove( const string& refname ); + inline const SGQuatd& get_orientation() { return _orientation; } /** - * return true of the specified sound exists in the sound manager system + * Get the direction vector of the sound manager + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @return Look-at direction of the OpenAL listener */ - bool exists( const string& refname ); + SGVec3f get_direction() { + return SGVec3f(_at_up_vec[0], _at_up_vec[1], _at_up_vec[2]); + } + + enum { + NO_SOURCE = (unsigned int)-1, + NO_BUFFER = (unsigned int)-1 + }; /** - * return a pointer to the SGSoundSample if the specified sound - * exists in the sound manager system, otherwise return NULL + * Set the master volume. + * @param vol Volume (must be between 0.0 and 1.0) */ - SGSoundSample *find( const string& refname ); + void set_volume( float vol ); /** - * tell the scheduler to play the indexed sample in a continuous - * loop + * Get the master volume. + * @return Volume (must be between 0.0 and 1.0) */ - bool play_looped( const string& refname ); + inline float get_volume() { return _volume; } /** - * tell the scheduler to play the indexed sample once + * Get a free OpenAL source-id + * @return NO_SOURCE if no source is available */ - bool play_once( const string& refname ); + unsigned int request_source(); /** - * return true of the specified sound is currently being played + * Free an OpenAL source-id for future use + * @param source OpenAL source-id to free */ - bool is_playing( const string& refname ); + void release_source( unsigned int source ); /** - * immediate stop playing the sound + * Get a free OpenAL buffer-id + * The buffer-id will be asigned to the sample by calling this function. + * @param sample Pointer to an audio sample to assign the buffer-id to + * @return NO_BUFFER if loading of the buffer failed. */ - bool stop( const string& refname ); + unsigned int request_buffer(SGSoundSample *sample); /** - * set overall volume for the application. - * @param vol 1.0 is default, must be greater than 0 + * Free an OpenAL buffer-id for this sample + * @param sample Pointer to an audio sample for which to free the buffer */ - inline void set_volume( const ALfloat vol ) { - if ( vol > 0.0 ) { - alListenerf( AL_GAIN, vol ); - } - } + void release_buffer( SGSoundSample *sample ); /** - * set the position of the listener (in opengl coordinates) + * Test if the position of the sound manager has changed. + * The value will be set to false upon the next call to update_late() + * @return true if the position has changed */ - inline void set_listener_pos( ALfloat *pos ) { - listener_pos[0] = pos[0]; - listener_pos[1] = pos[1]; - listener_pos[2] = pos[2]; - alListenerfv( AL_POSITION, listener_pos ); - } + inline bool has_changed() { return _changed; } /** - * set the velocity of the listener (in opengl coordinates) + * Some implementations seem to need the velocity miltyplied by a + * factor of 100 to make them distinct. I've not found if this is + * a problem in the implementation or in out code. Until then + * this function is used to detect the problematic implementations. */ - inline void set_listener_vel( ALfloat *vel ) { - listener_vel[0] = vel[0]; - listener_vel[1] = vel[1]; - listener_vel[2] = vel[2]; - alListenerfv( AL_VELOCITY, listener_vel ); - } + inline bool bad_doppler_effect() { return _bad_doppler; } /** - * set the orientation of the listener (in opengl coordinates) - * - * Description: ORIENTATION is a pair of 3-tuples representing the - * 'at' direction vector and 'up' direction of the Object in - * Cartesian space. AL expects two vectors that are orthogonal to - * each other. These vectors are not expected to be normalized. If - * one or more vectors have zero length, implementation behavior - * is undefined. If the two vectors are linearly dependent, - * behavior is undefined. - */ - inline void set_listener_orientation( ALfloat *ori ) { - listener_ori[0] = ori[0]; - listener_ori[1] = ori[1]; - listener_ori[2] = ori[2]; - listener_ori[3] = ori[3]; - listener_ori[4] = ori[4]; - listener_ori[5] = ori[5]; - alListenerfv( AL_ORIENTATION, listener_ori ); - } + * Load a sample file and return it's configuration and data. + * @param samplepath Path to the file to load + * @param data Pointer to a variable that points to the allocated data + * @param format Pointer to a vairable that gets the OpenAL format + * @param size Pointer to a vairable that gets the sample size in bytes + * @param freq Pointer to a vairable that gets the sample frequency in Herz + * @return true if succesful, false on error + */ + bool load(string &samplepath, void **data, int *format, + size_t *size, int *freq ); /** - * set the positions of all managaged sound sources + * Get a list of available playback devices. */ - void set_source_pos_all( ALfloat *pos ); + std::vector get_available_devices(); /** - * set the velocities of all managaged sound sources + * Get the current OpenAL vendor or rendering backend. */ - void set_source_vel_all( ALfloat *pos ); + const std::string& get_vendor() { return _vendor; } + const std::string& get_renderer() { return _renderer; } + +private: + static int _alut_init; + + bool _working; + bool _active; + bool _changed; + float _volume; + + ALCdevice *_device; + ALCcontext *_context; + + // Position of the listener. + SGVec3d _absolute_pos; + SGVec3d _offset_pos; + SGVec3d _base_pos; + SGGeod _geod_pos; + + // Velocity of the listener. + SGVec3d _velocity; + + // Orientation of the listener. + // first 3 elements are "at" vector, second 3 are "up" vector + SGQuatd _orientation; + ALfloat _at_up_vec[6]; + + sample_group_map _sample_groups; + buffer_map _buffers; + + std::vector _free_sources; + std::vector _sources_in_use; + + bool _bad_doppler; + std::string _renderer; + std::string _vendor; + + bool testForALError(std::string s); + bool testForALCError(std::string s); + bool testForALUTError(std::string s); + bool testForError(void *p, std::string s); + + void update_pos_and_orientation(); + void update_sample_config( SGSampleGroup *sound ); };