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 &parameter)
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 &parameter)
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