1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2008-2015 Joerg Henrichs 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 3 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 #ifndef HEADER_SFX_MANAGER_HPP 20 #define HEADER_SFX_MANAGER_HPP 21 22 #include "utils/can_be_deleted.hpp" 23 #include "utils/leak_check.hpp" 24 #include "utils/no_copy.hpp" 25 #include "utils/synchronised.hpp" 26 #include "utils/vec3.hpp" 27 28 #include <condition_variable> 29 #include <map> 30 #include <string> 31 #include <thread> 32 33 #include <vector> 34 35 #ifdef ENABLE_SOUND 36 # ifdef __APPLE__ 37 # define OPENAL_DEPRECATED 38 # include <OpenAL/al.h> 39 # include <OpenAL/alc.h> 40 # else 41 # include <AL/al.h> 42 # include <AL/alc.h> 43 # endif 44 #else 45 typedef unsigned int ALuint; 46 #endif 47 48 class MusicInformation; 49 class SFXBase; 50 class SFXBuffer; 51 class XMLNode; 52 53 /** 54 * \brief Manager of all sound effects. 55 * The manager reads all sound effects and 56 * maintains the corresponding buffers. Each sound effect objects uses 57 * on of the (shared) buffers from the sound manager. 58 * \ingroup audio 59 */ 60 class SFXManager : public NoCopy, public CanBeDeleted 61 { 62 private: 63 /** Singleton pointer. */ 64 static SFXManager *m_sfx_manager; 65 66 public: 67 68 /** The various commands to be executed by the sfx manager thread 69 * for each sfx. */ 70 enum SFXCommands 71 { 72 SFX_PLAY = 1, 73 SFX_PLAY_POSITION, 74 SFX_STOP, 75 SFX_PAUSE, 76 SFX_PAUSE_ALL, 77 SFX_RESUME, 78 SFX_RESUME_ALL, 79 SFX_DELETE, 80 SFX_SPEED, 81 SFX_POSITION, 82 SFX_SPEED_POSITION, 83 SFX_VOLUME, 84 SFX_MASTER_VOLUME, 85 SFX_LOOP, 86 SFX_LISTENER, 87 SFX_UPDATE, 88 SFX_MUSIC_START, 89 SFX_MUSIC_STOP, 90 SFX_MUSIC_PAUSE, 91 SFX_MUSIC_RESUME, 92 SFX_MUSIC_SWITCH_FAST, 93 SFX_MUSIC_SET_TMP_VOLUME, 94 SFX_MUSIC_WAITING, 95 SFX_MUSIC_DEFAULT_VOLUME, 96 SFX_EXIT, 97 SFX_CREATE_SOURCE 98 }; // SFXCommands 99 100 /** 101 * Entries for custom SFX sounds. These are unique for each kart. 102 * eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN) 103 */ 104 enum CustomSFX : int 105 { 106 CUSTOM_HORN, //!< Replaces default horn 107 CUSTOM_CRASH, //!< Played when colliding with another kart 108 CUSTOM_WIN, //!< Played when racer wins 109 CUSTOM_EXPLODE, //!< Played when struck by bowling ball or dynamite 110 CUSTOM_GOO, //!< Played when driving through goo 111 CUSTOM_PASS, //!< Played when passing another kart 112 CUSTOM_ZIPPER, //!< Played when kart hits zipper 113 CUSTOM_NAME, //!< Introduction (e.g. "I'm Tux!") 114 CUSTOM_ATTACH, //!< Played when something is attached to kart (Uh-Oh) 115 CUSTOM_SHOOT, //!< Played when weapon is used 116 NUM_CUSTOMS 117 }; 118 119 private: 120 121 /** Data structure for the queue, which stores a sfx and the command to 122 * execute for it. */ 123 class SFXCommand : public NoCopy 124 { 125 private: 126 LEAK_CHECK() 127 public: 128 /** The sound effect for which the command should be executed. */ 129 SFXBase *m_sfx; 130 131 /** The sound buffer to play (null = no change) */ 132 SFXBuffer *m_buffer = NULL; 133 134 /** Stores music information for music commands. */ 135 MusicInformation *m_music_information; 136 137 /** The command to execute. */ 138 SFXCommands m_command; 139 /** Optional parameter for commands that need more input. Single 140 * floating point values are stored in the X component. */ 141 Vec3 m_parameter; 142 // -------------------------------------------------------------------- SFXCommand(SFXCommands command,SFXBase * base)143 SFXCommand(SFXCommands command, SFXBase *base) 144 { 145 m_command = command; 146 m_sfx = base; 147 } // SFXCommand() 148 // -------------------------------------------------------------------- 149 /** Constructor for music information commands. */ SFXCommand(SFXCommands command,MusicInformation * mi)150 SFXCommand(SFXCommands command, MusicInformation *mi) 151 { 152 m_command = command; 153 m_music_information = mi; 154 } // SFXCommnd(MusicInformation*) 155 // -------------------------------------------------------------------- 156 /** Constructor for music information commands that take a floating 157 * point parameter (which is stored in the X value of m_parameter). */ SFXCommand(SFXCommands command,MusicInformation * mi,float f)158 SFXCommand(SFXCommands command, MusicInformation *mi, float f) 159 { 160 m_command = command; 161 m_parameter.setX(f); 162 m_music_information = mi; 163 } // SFXCommnd(MusicInformation *, float) 164 // -------------------------------------------------------------------- SFXCommand(SFXCommands command,SFXBase * base,float parameter)165 SFXCommand(SFXCommands command, SFXBase *base, float parameter) 166 { 167 m_command = command; 168 m_sfx = base; 169 m_parameter.setX(parameter); 170 } // SFXCommand(float) 171 // -------------------------------------------------------------------- SFXCommand(SFXCommands command,SFXBase * base,const Vec3 & parameter)172 SFXCommand(SFXCommands command, SFXBase *base, const Vec3 ¶meter) 173 { 174 m_command = command; 175 m_sfx = base; 176 m_parameter = parameter; 177 } // SFXCommand(Vec3) 178 // -------------------------------------------------------------------- 179 /** Store a float and vec3 parameter. The float is stored as W 180 * component of the vector. A bit hacky, but this class is used 181 * very frequently, so should remain as small as possible). */ SFXCommand(SFXCommands command,SFXBase * base,float f,const Vec3 & parameter)182 SFXCommand(SFXCommands command, SFXBase *base, float f, 183 const Vec3 ¶meter) 184 { 185 m_command = command; 186 m_sfx = base; 187 m_parameter = parameter; 188 m_parameter.setW(f); 189 } // SFXCommand(Vec3) 190 }; // SFXCommand 191 // ======================================================================== 192 193 /** The position of the listener. Its lock will be used to 194 * access m_listener_{position,front, up}. */ 195 Synchronised<Vec3> m_listener_position; 196 197 /** The direction the listener is facing. */ 198 Vec3 m_listener_front; 199 200 /** Up vector of the listener. */ 201 Vec3 m_listener_up; 202 203 204 /** The buffers and info for all sound effects. These are shared among all 205 * instances of SFXOpenal. */ 206 std::map<std::string, SFXBuffer*> m_all_sfx_types; 207 208 /** The actual instances (sound sources) */ 209 Synchronised<std::vector<SFXBase*> > m_all_sfx; 210 211 /** The list of sound effects to be played in the next update. */ 212 Synchronised< std::vector<SFXCommand*> > m_sfx_commands; 213 214 /** To play non-positional sounds without having to create a 215 * new object for each. */ 216 Synchronised<std::map<std::string, SFXBase*> > m_quick_sounds; 217 218 /** If the sfx manager has been initialised. */ 219 bool m_initialized; 220 221 /** Master gain value, taken from the user config value. */ 222 float m_master_gain; 223 224 /** Thread id of the thread running in this object. */ 225 std::thread m_thread; 226 227 uint64_t m_last_update_time; 228 229 /** A conditional variable to wake up the main loop. */ 230 std::condition_variable m_condition_variable; 231 232 void loadSfx(); 233 SFXManager(); 234 virtual ~SFXManager(); 235 236 static void mainLoop(void *obj); 237 void deleteSFX(SFXBase *sfx); 238 void queueCommand(SFXCommand *command); 239 void reallyPositionListenerNow(); 240 241 public: 242 static void create(); 243 static void destroy(); 244 void queue(SFXCommands command, SFXBase *sfx=NULL); 245 void queue(SFXCommands command, SFXBase *sfx, float f); 246 void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p); 247 void queue(SFXCommands command, SFXBase *sfx, float f, const Vec3 &p); 248 void queue(SFXCommands command, MusicInformation *mi); 249 void queue(SFXCommands command, MusicInformation *mi, float f); 250 void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer); 251 252 // ------------------------------------------------------------------------ 253 /** Static function to get the singleton sfx manager. */ get()254 static SFXManager *get() 255 { 256 return m_sfx_manager; 257 } // get 258 259 // ------------------------------------------------------------------------ 260 void stopThread(); 261 bool sfxAllowed(); 262 SFXBuffer* loadSingleSfx(const XMLNode* node, 263 const std::string &path=std::string(""), 264 const bool load = true); 265 SFXBuffer* addSingleSfx(const std::string &sfx_name, 266 const std::string &filename, 267 bool positional, 268 float rolloff, 269 float max_dist, 270 float gain, 271 const bool load = true); 272 273 SFXBase* createSoundSource(SFXBuffer* info, 274 const bool add_to_SFX_list=true, 275 const bool owns_buffer=false); 276 SFXBase* createSoundSource(const std::string &name, 277 const bool addToSFXList=true); 278 279 void deleteSFXMapping(const std::string &name); 280 void pauseAll(); 281 void reallyPauseAllNow(); 282 void resumeAll(); 283 void reallyResumeAllNow(); 284 void update(); 285 void reallyUpdateNow(SFXCommand *current); 286 bool soundExist(const std::string &name); 287 void setMasterSFXVolume(float gain); getMasterSFXVolume() const288 float getMasterSFXVolume() const { return m_master_gain; } 289 290 static bool checkError(const std::string &context); 291 static const std::string getErrorString(int err); 292 293 void positionListener(const Vec3 &position, 294 const Vec3 &front, const Vec3 &up); 295 SFXBase* quickSound(const std::string &soundName); 296 297 /** Called when sound was muted/unmuted */ 298 void toggleSound(const bool newValue); 299 300 // ------------------------------------------------------------------------ 301 /** Prints the list of currently loaded sounds to stdout. Useful to 302 * debug audio leaks */ 303 void dump(); 304 305 // ------------------------------------------------------------------------ 306 /** Returns the current position of the listener. */ getListenerPos() const307 Vec3 getListenerPos() const { return m_listener_position.getData(); } 308 309 // ------------------------------------------------------------------------ 310 311 SFXBuffer* getBuffer(const std::string &name); 312 }; 313 314 #endif // HEADER_SFX_MANAGER_HPP 315 316