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 #include "audio/dummy_sfx.hpp"
20 #include "audio/music_manager.hpp"
21 #include "audio/sfx_openal.hpp"
22 #include "audio/sfx_buffer.hpp"
23 #include "config/user_config.hpp"
24 #include "io/file_manager.hpp"
25 #include "modes/world.hpp"
26 #include "race/race_manager.hpp"
27 #include "utils/stk_process.hpp"
28 #include "utils/profiler.hpp"
29 #include "utils/string_utils.hpp"
30 #include "utils/vs.hpp"
31 
32 #include <stdexcept>
33 #include <algorithm>
34 #include <map>
35 
36 #include <functional>
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <limits>
41 #include <math.h>
42 
43 // Define this if the profiler should also collect data of the sfx manager
44 #undef ENABLE_PROFILING_FOR_SFX_MANAGER
45 #ifndef ENABLE_PROFILING_FOR_SFX_MANAGER
46      // Otherwise ignore the profiler push/pop events
47      // Use undef to remove preprocessor warning
48 #    undef PROFILER_PUSH_CPU_MARKER
49 #    undef  PROFILER_POP_CPU_MARKER
50 #    define PROFILER_PUSH_CPU_MARKER(name, r, g, b)
51 #    define PROFILER_POP_CPU_MARKER()
52 #endif
53 
54 SFXManager *SFXManager::m_sfx_manager;
55 
56 // ----------------------------------------------------------------------------
57 /** Static function to create the singleton sfx manager.
58  */
create()59 void SFXManager::create()
60 {
61     assert(!m_sfx_manager);
62     m_sfx_manager = new SFXManager();
63 }   // create
64 
65 // ------------------------------------------------------------------------
66 /** Static function to delete the singleton sfx manager.
67  */
destroy()68 void SFXManager::destroy()
69 {
70     delete m_sfx_manager;
71     m_sfx_manager = NULL;
72 }    // destroy
73 
74 // ----------------------------------------------------------------------------
75 /** Initialises the SFX manager and loads the sfx from a config file.
76  */
SFXManager()77 SFXManager::SFXManager()
78 {
79 
80     // The sound manager initialises OpenAL
81     m_initialized = music_manager->initialized();
82     m_master_gain = UserConfigParams::m_sfx_volume;
83     m_last_update_time = std::numeric_limits<uint64_t>::max();
84     // Init position, since it can be used before positionListener is called.
85     // No need to use lock here, since the thread will be created later.
86     m_listener_position.getData() = Vec3(0, 0, 0);
87     m_listener_front              = Vec3(0, 0, 1);
88     m_listener_up                 = Vec3(0, 1, 0);
89 
90     loadSfx();
91 
92 #ifdef ENABLE_SOUND
93     if (UserConfigParams::m_enable_sound)
94     {
95         // The thread is created even if there atm sfx are disabled
96         // (since the user might enable it later).
97         m_thread = std::thread(std::bind(mainLoop, this));
98         setMasterSFXVolume( UserConfigParams::m_sfx_volume );
99         m_sfx_commands.lock();
100         m_sfx_commands.getData().clear();
101         m_sfx_commands.unlock();
102     }
103 #endif
104 }  // SoundManager
105 
106 //-----------------------------------------------------------------------------
107 /** Destructor, frees all sound effects.
108  */
~SFXManager()109 SFXManager::~SFXManager()
110 {
111 #ifdef ENABLE_SOUND
112     if (UserConfigParams::m_enable_sound)
113     {
114         m_thread.join();
115     }
116 #endif
117 
118     // ---- clear m_all_sfx
119     // not strictly necessary, but might avoid copy&paste problems
120     m_all_sfx.lock();
121     const int sfx_amount = (int) m_all_sfx.getData().size();
122     for (int n=0; n<sfx_amount; n++)
123     {
124         delete m_all_sfx.getData()[n];
125     }
126     m_all_sfx.getData().clear();
127     m_all_sfx.unlock();
128 
129     m_quick_sounds.lock();
130     // ---- clear m_quick_sounds
131     {
132         std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.getData().begin();
133         for (; i != m_quick_sounds.getData().end(); i++)
134         {
135             SFXBase* snd = (*i).second;
136             delete snd;
137         }
138     }
139     m_quick_sounds.getData().clear();
140     m_quick_sounds.unlock();
141 
142     // ---- clear m_all_sfx_types
143     {
144         std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.begin();
145         for (; i != m_all_sfx_types.end(); i++)
146         {
147             SFXBuffer* buffer = (*i).second;
148             buffer->unload();
149             delete buffer;
150         }
151         m_all_sfx_types.clear();
152     }
153     m_all_sfx_types.clear();
154 
155 }   // ~SFXManager
156 
157 //----------------------------------------------------------------------------
158 /** Adds a sound effect command to the queue of the sfx manager. Openal
159  *  commands can sometimes cause a 5ms delay, so it is done in a separate
160  *  thread.
161  *  \param command The command to execute.
162  *  \param sfx The sound effect to be started.
163  */
queue(SFXCommands command,SFXBase * sfx)164 void SFXManager::queue(SFXCommands command,  SFXBase *sfx)
165 {
166 #ifdef ENABLE_SOUND
167     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
168         return;
169 
170     SFXCommand *sfx_command = new SFXCommand(command, sfx);
171     queueCommand(sfx_command);
172 #endif
173 }   // queue
174 
175 //----------------------------------------------------------------------------
176 /** Adds a sound effect command with a single floating point parameter to the
177  *  queue of the sfx manager. Openal commands can sometimes cause a 5ms delay,
178  *  so it is done in a separate thread.
179  *  \param command The command to execute.
180  *  \param sfx The sound effect to be started.
181  *  \param f Floating point parameter for the command.
182  */
queue(SFXCommands command,SFXBase * sfx,float f)183 void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f)
184 {
185 #ifdef ENABLE_SOUND
186     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
187         return;
188 
189     SFXCommand *sfx_command = new SFXCommand(command, sfx, f);
190     queueCommand(sfx_command);
191 #endif
192 }   // queue(float)
193 
194 //----------------------------------------------------------------------------
195 /** Adds a sound effect command with a Vec3 parameter to the queue of the sfx
196  *  manager. Openal commands can sometimes cause a 5ms delay, so it is done in
197  *  a separate thread.
198  *  \param command The command to execute.
199  *  \param sfx The sound effect to be started.
200  *  \param p A Vec3 parameter for the command.
201  */
queue(SFXCommands command,SFXBase * sfx,const Vec3 & p)202 void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
203 {
204 #ifdef ENABLE_SOUND
205     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
206         return;
207 
208     SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
209     queueCommand(sfx_command);
210 #endif
211 }   // queue (Vec3)
212 
213 //----------------------------------------------------------------------------
214 
queue(SFXCommands command,SFXBase * sfx,const Vec3 & p,SFXBuffer * buffer)215 void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer)
216 {
217 #ifdef ENABLE_SOUND
218     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
219         return;
220 
221     SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
222     sfx_command->m_buffer = buffer;
223     queueCommand(sfx_command);
224 #endif
225 }   // queue (Vec3)
226 
227 //----------------------------------------------------------------------------
228 /** Adds a sound effect command with a float and a Vec3 parameter to the queue
229  *  of the sfx manager. Openal commands can sometimes cause a 5ms delay, so it
230  *   is done in a separate thread.
231  *  \param command The command to execute.
232  *  \param sfx The sound effect to be started.
233  *  \param f A float parameter for the command.
234  *  \param p A Vec3 parameter for the command.
235  */
queue(SFXCommands command,SFXBase * sfx,float f,const Vec3 & p)236 void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f,
237                        const Vec3 &p)
238 {
239 #ifdef ENABLE_SOUND
240     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
241         return;
242 
243     SFXCommand *sfx_command = new SFXCommand(command, sfx, f, p);
244     queueCommand(sfx_command);
245 #endif
246 }   // queue(float, Vec3)
247 
248 //----------------------------------------------------------------------------
249 /** Queues a command for the music manager.
250  *  \param mi The music for which the command is.
251  */
queue(SFXCommands command,MusicInformation * mi)252 void SFXManager::queue(SFXCommands command, MusicInformation *mi)
253 {
254 #ifdef ENABLE_SOUND
255     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
256         return;
257 
258     SFXCommand *sfx_command = new SFXCommand(command, mi);
259     queueCommand(sfx_command);
260 #endif
261 }   // queue(MusicInformation)
262 //----------------------------------------------------------------------------
263 /** Queues a command for the music manager that takes a floating point value
264  *  (e.g. setTemporaryVolume).
265  *  \param mi The music for which the command is.
266  *  \param f The floating point parameter.
267  */
queue(SFXCommands command,MusicInformation * mi,float f)268 void SFXManager::queue(SFXCommands command, MusicInformation *mi, float f)
269 {
270 #ifdef ENABLE_SOUND
271     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
272         return;
273 
274     SFXCommand *sfx_command = new SFXCommand(command, mi, f);
275     queueCommand(sfx_command);
276 #endif
277 }   // queue(MusicInformation)
278 
279 //----------------------------------------------------------------------------
280 /** Enqueues a command to the sfx queue threadsafe. Then signal the
281  *  sfx manager to wake up.
282  *  \param command Pointer to the command to queue up.
283  */
queueCommand(SFXCommand * command)284 void SFXManager::queueCommand(SFXCommand *command)
285 {
286 #ifdef ENABLE_SOUND
287     if (!UserConfigParams::m_enable_sound || STKProcess::getType() != PT_MAIN)
288         return;
289 
290     m_sfx_commands.lock();
291     if(World::getWorld() &&
292         m_sfx_commands.getData().size() > 20*RaceManager::get()->getNumberOfKarts()+20 &&
293         RaceManager::get()->getMinorMode() != RaceManager::MINOR_MODE_CUTSCENE)
294     {
295         if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
296            command->m_command==SFX_SPEED    ||
297            command->m_command==SFX_SPEED_POSITION                               )
298         {
299             delete command;
300             static int count_messages = 0;
301             if(count_messages < 5)
302             {
303                 Log::warn("SFXManager", "Throttling sfx - queue size %d",
304                          m_sfx_commands.getData().size());
305                 count_messages++;
306             }
307             m_sfx_commands.unlock();
308             return;
309         }   // if throttling
310     }
311     m_sfx_commands.getData().push_back(command);
312     m_sfx_commands.unlock();
313 #endif
314 }   // queueCommand
315 
316 //----------------------------------------------------------------------------
317 /** Puts a NULL request into the queue, which will trigger the thread to
318  *  exit.
319  */
stopThread()320 void SFXManager::stopThread()
321 {
322 #ifdef ENABLE_SOUND
323     if (UserConfigParams::m_enable_sound)
324     {
325         queue(SFX_EXIT);
326         // Make sure the thread wakes up.
327         m_condition_variable.notify_one();
328     }
329     else
330 #endif
331     {
332         setCanBeDeleted();
333     }
334 }   // stopThread
335 
336 //----------------------------------------------------------------------------
337 /** This loops runs in a different threads, and starts sfx to be played.
338  *  This can sometimes take up to 5 ms, so it needs to be handled in a thread
339  *  in order to avoid rendering delays.
340  *  \param obj A pointer to the SFX singleton.
341  */
mainLoop(void * obj)342 void SFXManager::mainLoop(void *obj)
343 {
344 #ifdef ENABLE_SOUND
345     if (!UserConfigParams::m_enable_sound)
346         return;
347 
348     VS::setThreadName("SFXManager");
349     SFXManager *me = (SFXManager*)obj;
350 
351     std::unique_lock<std::mutex> ul = me->m_sfx_commands.acquireMutex();
352 
353     // Wait till we have an empty sfx in the queue
354     while (me->m_sfx_commands.getData().empty() ||
355            me->m_sfx_commands.getData().front()->m_command!=SFX_EXIT)
356     {
357         PROFILER_PUSH_CPU_MARKER("Wait", 255, 0, 0);
358         bool empty = me->m_sfx_commands.getData().empty();
359 
360         // Wait in cond_wait for a request to arrive. The 'while' is necessary
361         // since "spurious wakeups from the pthread_cond_wait ... may occur"
362         // (pthread_cond_wait man page)!
363         while (empty)
364         {
365             me->m_condition_variable.wait(ul);
366             empty = me->m_sfx_commands.getData().empty();
367         }
368         SFXCommand *current = me->m_sfx_commands.getData().front();
369         me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
370 
371         if (current->m_command == SFX_EXIT)
372         {
373             delete current;
374             break;
375         }
376         ul.unlock();
377         PROFILER_POP_CPU_MARKER();
378         PROFILER_PUSH_CPU_MARKER("Execute", 0, 255, 0);
379         switch (current->m_command)
380         {
381         case SFX_PLAY:     current->m_sfx->reallyPlayNow();       break;
382         case SFX_PLAY_POSITION:
383             current->m_sfx->reallyPlayNow(current->m_parameter, current->m_buffer);  break;
384         case SFX_STOP:     current->m_sfx->reallyStopNow();       break;
385         case SFX_PAUSE:    current->m_sfx->reallyPauseNow();      break;
386         case SFX_RESUME:   current->m_sfx->reallyResumeNow();     break;
387         case SFX_SPEED:    current->m_sfx->reallySetSpeed(
388                                   current->m_parameter.getX());   break;
389         case SFX_POSITION: current->m_sfx->reallySetPosition(
390                                          current->m_parameter);   break;
391         case SFX_SPEED_POSITION: current->m_sfx->reallySetSpeedPosition(
392                                          // Extract float from W component
393                                          current->m_parameter.getW(),
394                                          current->m_parameter);   break;
395         case SFX_VOLUME:   current->m_sfx->reallySetVolume(
396                                   current->m_parameter.getX());   break;
397         case SFX_MASTER_VOLUME:
398             current->m_sfx->reallySetMasterVolumeNow(
399                                   current->m_parameter.getX());   break;
400         case SFX_LOOP:     current->m_sfx->reallySetLoop(
401                              current->m_parameter.getX() != 0);   break;
402         case SFX_DELETE:     me->deleteSFX(current->m_sfx);       break;
403         case SFX_PAUSE_ALL:  me->reallyPauseAllNow();             break;
404         case SFX_RESUME_ALL: me->reallyResumeAllNow();            break;
405         case SFX_LISTENER:   me->reallyPositionListenerNow();     break;
406         case SFX_UPDATE:     me->reallyUpdateNow(current);        break;
407         case SFX_MUSIC_START:
408         {
409             current->m_music_information->setDefaultVolume();
410             current->m_music_information->startMusic();           break;
411         }
412         case SFX_MUSIC_STOP:
413             current->m_music_information->stopMusic();            break;
414         case SFX_MUSIC_PAUSE:
415             current->m_music_information->pauseMusic();           break;
416         case SFX_MUSIC_RESUME:
417             current->m_music_information->resumeMusic();
418             // This might be necessasary if the volume was changed
419             // in the in-game menu
420             current->m_music_information->setDefaultVolume();     break;
421         case SFX_MUSIC_SWITCH_FAST:
422             current->m_music_information->switchToFastMusic();    break;
423         case SFX_MUSIC_SET_TMP_VOLUME:
424         {
425             MusicInformation *mi = current->m_music_information;
426             mi->setTemporaryVolume(current->m_parameter.getX());  break;
427         }
428         case SFX_MUSIC_WAITING:
429                current->m_music_information->setMusicWaiting();   break;
430         case SFX_MUSIC_DEFAULT_VOLUME:
431         {
432             current->m_music_information->setDefaultVolume();
433             break;
434         }
435         case SFX_CREATE_SOURCE:
436             current->m_sfx->init(); break;
437         default: assert("Not yet supported.");
438         }
439         delete current;
440         current = NULL;
441         PROFILER_POP_CPU_MARKER();
442         PROFILER_PUSH_CPU_MARKER("yield", 0, 0, 255);
443         // We access the size without lock, doesn't matter if we
444         // should get an incorrect value because of concurrent read/writes
445         if (me->m_sfx_commands.getData().size() == 0 && me->sfxAllowed())
446         {
447             // Wait some time to let other threads run, then queue an
448             // update event to keep music playing.
449             uint64_t t = StkTime::getMonoTimeMs();
450             StkTime::sleep(1);
451             t = StkTime::getMonoTimeMs() - t;
452             me->queue(SFX_UPDATE, (SFXBase*)NULL, float(t / 1000.0));
453         }
454         ul = me->m_sfx_commands.acquireMutex();
455         PROFILER_POP_CPU_MARKER();
456     }   // while
457 
458     // Signal that the sfx manager can now be deleted.
459     // We signal this even before cleaning up memory, since there is no
460     // need to keep the user waiting for STK to exit.
461     me->setCanBeDeleted();
462 
463     // Clean up memory to avoid leak detection
464     while(!me->m_sfx_commands.getData().empty())
465     {
466         delete me->m_sfx_commands.getData().front();
467         me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
468     }
469 #endif
470     return;
471 }   // mainLoop
472 
473 //----------------------------------------------------------------------------
474 /** Called when sound is globally switched on or off. It either pauses or
475  *  resumes all sound effects.
476  *  \param on If sound is switched on or off.
477  */
toggleSound(const bool on)478 void SFXManager::toggleSound(const bool on)
479 {
480     // When activating SFX, load all buffers
481     if (on)
482     {
483         std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.begin();
484         for (; i != m_all_sfx_types.end(); i++)
485         {
486             SFXBuffer* buffer = (*i).second;
487             buffer->load();
488         }
489 
490         reallyResumeAllNow();
491         m_all_sfx.lock();
492         const int sfx_amount = (int)m_all_sfx.getData().size();
493         for (int n=0; n<sfx_amount; n++)
494         {
495             m_all_sfx.getData()[n]->onSoundEnabledBack();
496         }
497         m_all_sfx.unlock();
498     }
499     else
500     {
501         // First stop all sfx that are not looped
502         const int sfx_amount = (int)m_all_sfx.getData().size();
503         m_all_sfx.lock();
504         for (int i=0; i<sfx_amount; i++)
505         {
506             if(!m_all_sfx.getData()[i]->isLooped())
507             {
508                 m_all_sfx.getData()[i]->reallyStopNow();
509             }
510         }
511         m_all_sfx.unlock();
512         pauseAll();
513     }
514 }   // toggleSound
515 
516 //----------------------------------------------------------------------------
517 /** Returns if sfx can be played. This means sfx are enabled and
518  *  the manager is correctly initialised.
519  */
sfxAllowed()520 bool SFXManager::sfxAllowed()
521 {
522     if (STKProcess::getType() != PT_MAIN)
523         return false;
524     if(!UserConfigParams::m_sfx || !m_initialized)
525         return false;
526     else
527         return true;
528 }   // sfxAllowed
529 
530 //----------------------------------------------------------------------------
531 /** Loads all sounds specified in the sound config file.
532  */
loadSfx()533 void SFXManager::loadSfx()
534 {
535     std::string sfx_config_name = file_manager->getAsset(FileManager::SFX, "sfx.xml");
536     XMLNode* root = file_manager->createXMLTree(sfx_config_name);
537     if (!root || root->getName()!="sfx-config")
538     {
539         Log::fatal("SFXManager", "Could not read sound effects XML file '%s'.",
540                    sfx_config_name.c_str());
541     }
542 
543     int i;
544 
545     const int amount = root->getNumNodes();
546     for (i=0; i<amount; i++)
547     {
548         const XMLNode* node = root->getNode(i);
549 
550         if (node->getName() == "sfx")
551         {
552             loadSingleSfx(node, "", false);
553         }
554         else
555         {
556             Log::warn("SFXManager", "Unknown node '%s' in sfx XML file '%s'.",
557                       node->getName().c_str(), sfx_config_name.c_str());
558             throw std::runtime_error("Unknown node in sfx XML file");
559         }
560     }// nend for
561 
562     delete root;
563 
564     // Now load them in parallel
565     const int max = (int)m_all_sfx_types.size();
566     SFXBuffer **array = new SFXBuffer *[max];
567     i = 0;
568 
569     for (std::map<std::string, SFXBuffer*>::iterator it = m_all_sfx_types.begin();
570          it != m_all_sfx_types.end(); it++)
571     {
572         SFXBuffer* const buffer = (*it).second;
573         array[i++] = buffer;
574     }
575 
576     for (i = 0; i < max; i++)
577     {
578         array[i]->load();
579     }
580 
581     delete [] array;
582 }   // loadSfx
583 
584 // -----------------------------------------------------------------------------
585 /** Introduces a mechanism by which one can load sound effects beyond the basic
586  *  enumerated types.  This will be used when loading custom sound effects for
587  *  individual karts (character voices) so that we can avoid creating an
588  *  enumeration for each effect, for each kart.
589  *  \param sfx_name
590  *  \param sfxFile must be an absolute pathname
591  *  \return        whether loading this sound effect was successful
592 
593 */
addSingleSfx(const std::string & sfx_name,const std::string & sfx_file,bool positional,float rolloff,float max_dist,float gain,const bool load)594 SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
595                                     const std::string &sfx_file,
596                                     bool               positional,
597                                     float              rolloff,
598                                     float              max_dist,
599                                     float              gain,
600                                     const bool         load)
601 {
602 
603     SFXBuffer* buffer = new SFXBuffer(sfx_file, positional, rolloff,
604                                       max_dist, gain);
605 
606     m_all_sfx_types[sfx_name] = buffer;
607 
608     if (!m_initialized)
609     {
610         // Keep the buffer even if SFX is disabled, in case
611         // SFX is enabled back later
612         return NULL;
613     }
614 
615     if (UserConfigParams::logMisc())
616         Log::debug("SFXManager", "Loading SFX %s", sfx_file.c_str());
617 
618     if (load && buffer->load()) return buffer;
619 
620     return NULL;
621 } // addSingleSFX
622 
623 //----------------------------------------------------------------------------
624 /** Loads a single sfx from the XML specification.
625  *  \param node The XML node with the data for this sfx.
626  */
loadSingleSfx(const XMLNode * node,const std::string & path,const bool load)627 SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
628                                      const std::string &path,
629                                      const bool load)
630 {
631     std::string filename;
632 
633     if (node->get("filename", &filename) == 0)
634     {
635         Log::error("SFXManager",
636                 "The 'filename' attribute is mandatory in the SFX XML file!");
637         return NULL;
638     }
639 
640     std::string sfx_name = StringUtils::removeExtension(filename);
641 
642     if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
643     {
644         Log::error("SFXManager",
645                 "There is already a sfx named '%s' installed - new one is ignored.",
646                 sfx_name.c_str());
647         return NULL;
648     }
649 
650     // Only use the filename if no full path is specified. This is used
651     // to load terrain specific sfx.
652     const std::string full_path = (path == "")
653                                 ? file_manager->getAsset(FileManager::SFX,filename)
654                                 : path+"/"+filename;
655 
656     SFXBuffer tmpbuffer(full_path, node);
657 
658     return addSingleSfx(sfx_name, full_path,
659                         tmpbuffer.isPositional(),
660                         tmpbuffer.getRolloff(),
661                         tmpbuffer.getMaxDist(),
662                         tmpbuffer.getGain(),
663                         load);
664 
665 }   // loadSingleSfx
666 
667 //----------------------------------------------------------------------------
668 /** Creates a new SFX object. The memory for this object is managed completely
669  *  by the SFXManager. This makes it easy to use different implementations of
670  *  SFX - since createSoundSource can return whatever type is used. To free the memory,
671  *  call deleteSFX().
672  *  \param id Identifier of the sound effect to create.
673  */
createSoundSource(SFXBuffer * buffer,const bool add_to_SFX_list,const bool owns_buffer)674 SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
675                                        const bool add_to_SFX_list,
676                                        const bool owns_buffer)
677 {
678     bool positional = false;
679 
680     if (RaceManager::get()->getNumLocalPlayers() < 2)
681     {
682         positional = buffer->isPositional();
683     }
684 
685     SFXBase* sfx = NULL;
686 
687 #ifdef ENABLE_SOUND
688     if (UserConfigParams::m_enable_sound && STKProcess::getType() == PT_MAIN)
689     {
690         //assert( alIsBuffer(buffer->getBufferID()) ); crashes on server
691         sfx = new SFXOpenAL(buffer, positional, buffer->getGain(), owns_buffer);
692     }
693     else
694 #endif
695     {
696         sfx = new DummySFX(buffer, positional, buffer->getGain());
697 
698         if (owns_buffer)
699         {
700             delete buffer;
701         }
702     }
703 
704     sfx->setMasterVolume(m_master_gain);
705 
706     if (add_to_SFX_list)
707     {
708         m_all_sfx.lock();
709         m_all_sfx.getData().push_back(sfx);
710         m_all_sfx.unlock();
711     }
712 
713     return sfx;
714 }   // createSoundSource
715 
716 //----------------------------------------------------------------------------
createSoundSource(const std::string & name,const bool add_to_SFXList)717 SFXBase* SFXManager::createSoundSource(const std::string &name,
718                                        const bool add_to_SFXList)
719 {
720     std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.find(name);
721     if ( i == m_all_sfx_types.end() )
722     {
723         Log::error("SFXManager",
724                    "SFXManager::createSoundSource could not find the "
725                    "requested sound effect : '%s'.", name.c_str());
726         return NULL;
727     }
728 
729     return createSoundSource( i->second, add_to_SFXList );
730 }  // createSoundSource
731 
732 //----------------------------------------------------------------------------
733 
getBuffer(const std::string & name)734 SFXBuffer* SFXManager::getBuffer(const std::string &name)
735 {
736     std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.find(name);
737     if (i == m_all_sfx_types.end())
738     {
739         Log::error("SFXManager",
740             "SFXManager::getBuffer could not find the "
741             "requested sound effect : '%s'.", name.c_str());
742         return NULL;
743     }
744 
745     return i->second;
746 }
747 
748 //----------------------------------------------------------------------------
749 /** Returns true if a sfx with the given name exists.
750  *  \param name The internal name of the sfx (not the name of the ogg file)
751  */
soundExist(const std::string & name)752 bool SFXManager::soundExist(const std::string &name)
753 {
754     return m_all_sfx_types.find(name) != m_all_sfx_types.end();
755 }   // soundExist
756 
757 //----------------------------------------------------------------------------
758 /** This function removes a sfx buffer info entry from the mapping, and
759  *  frees the openal buffer.
760  *  \param name The name of the mapping entry to remove.
761  */
deleteSFXMapping(const std::string & name)762 void SFXManager::deleteSFXMapping(const std::string &name)
763 {
764     std::map<std::string, SFXBuffer*>::iterator i;
765     i = m_all_sfx_types.find(name);
766 
767     if (i == m_all_sfx_types.end())
768     {
769         Log::warn("SFXManager",
770              "SFXManager::deleteSFXMapping : Warning: sfx not found in list.");
771         return;
772     }
773     (*i).second->unload();
774 
775     m_all_sfx_types.erase(i);
776 
777 }   // deleteSFXMapping
778 
779 //----------------------------------------------------------------------------
780 /** Make sure that the sfx thread is started at least once per frame. It also
781  *  adds an update command for the music manager.
782  *  \param dt Time step size.
783  */
update()784 void SFXManager::update()
785 {
786 #ifdef ENABLE_SOUND
787     if (!UserConfigParams::m_enable_sound)
788         return;
789 
790     queue(SFX_UPDATE, (SFXBase*)NULL);
791     // Wake up the sfx thread to handle all queued up audio commands.
792     m_condition_variable.notify_one();
793 #endif
794 }   // update
795 
796 //----------------------------------------------------------------------------
797 /** Updates the status of all playing sfx (to test if they are finished).
798  *  This function is executed once per frame (triggered by the audio thread).
799  *  \param current The sfx command - used to get timestep information.
800 */
reallyUpdateNow(SFXCommand * current)801 void SFXManager::reallyUpdateNow(SFXCommand *current)
802 {
803 #ifdef ENABLE_SOUND
804     if (!UserConfigParams::m_enable_sound)
805         return;
806 
807     if (m_last_update_time == std::numeric_limits<uint64_t>::max())
808     {
809         // first time
810         m_last_update_time = StkTime::getMonoTimeMs();
811     }
812 
813     uint64_t previous_update_time = m_last_update_time;
814     m_last_update_time = StkTime::getMonoTimeMs();
815     float dt = float(m_last_update_time - previous_update_time) / 1000.0f;
816 
817     assert(current->m_command==SFX_UPDATE);
818     if (music_manager->getCurrentMusic())
819         music_manager->getCurrentMusic()->update(dt);
820     m_all_sfx.lock();
821     for (std::vector<SFXBase*>::iterator i =  m_all_sfx.getData().begin();
822                                          i != m_all_sfx.getData().end(); i++)
823     {
824         if((*i)->getStatus()==SFXBase::SFX_PLAYING)
825             (*i)->updatePlayingSFX(dt);
826     }   // for i in m_all_sfx
827     m_all_sfx.unlock();
828 
829     // We need to lock the quick sounds during update, since adding more
830     // quick sounds by another thread could invalidate the iterator.
831     m_quick_sounds.lock();
832     std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.getData().begin();
833     for (; i != m_quick_sounds.getData().end(); i++)
834     {
835         if (i->second->getStatus() == SFXBase::SFX_PLAYING)
836             i->second->updatePlayingSFX(dt);
837     }   // for i in m_all_sfx
838     m_quick_sounds.unlock();
839 #endif
840 }   // reallyUpdateNow
841 
842 //----------------------------------------------------------------------------
843 /** Delete a sound effect object, and removes it from the internal list of
844  *  all SFXs. This call deletes the object, and removes it from the list of
845  *  all SFXs.
846  *  \param sfx SFX object to delete.
847  */
deleteSFX(SFXBase * sfx)848 void SFXManager::deleteSFX(SFXBase *sfx)
849 {
850     if(sfx) sfx->reallyStopNow();
851     std::vector<SFXBase*>::iterator i;
852 
853     // The whole block needs to be locked, otherwise the iterator
854     // could become invalid.
855     m_all_sfx.lock();
856     i=std::find(m_all_sfx.getData().begin(), m_all_sfx.getData().end(), sfx);
857 
858     if(i==m_all_sfx.getData().end())
859     {
860         Log::warn("SFXManager",
861                   "SFXManager::deleteSFX : Warning: sfx '%s' %lx not found in list.",
862                   sfx->getBuffer()->getFileName().c_str(), sfx);
863         m_all_sfx.unlock();
864         return;
865     }
866 
867     m_all_sfx.getData().erase(i);
868     m_all_sfx.unlock();
869 
870     delete sfx;
871 }   // deleteSFX
872 
873 //----------------------------------------------------------------------------
874 /** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
875  *  otherwise not possible to determine which SFX must be resumed (i.e. were
876  *  actually playing at the time pause was called).
877  */
pauseAll()878 void SFXManager::pauseAll()
879 {
880     if (!sfxAllowed()) return;
881     queue(SFX_PAUSE_ALL);
882 }   // pauseAll
883 
884 //----------------------------------------------------------------------------
885 /** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
886  *  otherwise not possible to determine which SFX must be resumed (i.e. were
887  *  actually playing at the time pause was called.
888  */
reallyPauseAllNow()889 void SFXManager::reallyPauseAllNow()
890 {
891     m_all_sfx.lock();
892     for (std::vector<SFXBase*>::iterator i= m_all_sfx.getData().begin();
893                                          i!=m_all_sfx.getData().end(); i++)
894     {
895         (*i)->reallyPauseNow();
896     }   // for i in m_all_sfx
897     m_all_sfx.unlock();
898 }   // pauseAll
899 
900 //----------------------------------------------------------------------------
901 /** Resumes all paused SFXs. If sound is disabled, does nothing.
902   */
resumeAll()903 void SFXManager::resumeAll()
904 {
905     // ignore unpausing if sound is disabled
906     if (!sfxAllowed()) return;
907     queue(SFX_RESUME_ALL);
908 }   // resumeAll
909 
910 //----------------------------------------------------------------------------
911 /** Resumes all paused SFXs. If sound is disabled, does nothing.
912   */
reallyResumeAllNow()913 void SFXManager::reallyResumeAllNow()
914 {
915     m_all_sfx.lock();
916     for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
917                                          i!=m_all_sfx.getData().end(); i++)
918     {
919         (*i)->reallyResumeNow();
920     }   // for i in m_all_sfx
921     m_all_sfx.unlock();
922 }   // resumeAll
923 
924 //-----------------------------------------------------------------------------
925 /** Returns whether or not an openal error has occurred. If so, an error
926  *  message is printed containing the given context.
927  *  \param context Context to specify in the error message.
928  *  \return True if no error happened.
929  */
checkError(const std::string & context)930 bool SFXManager::checkError(const std::string &context)
931 {
932 #ifdef ENABLE_SOUND
933     if (!UserConfigParams::m_enable_sound)
934         return true;
935 
936     // Check (and clear) the error flag
937     int error = alGetError();
938 
939     if (error != AL_NO_ERROR)
940     {
941         Log::error("SFXManager", "SFXOpenAL OpenAL error while %s: %s",
942                    context.c_str(), SFXManager::getErrorString(error).c_str());
943         return false;
944     }
945 #endif
946     return true;
947 }   // checkError
948 
949 //-----------------------------------------------------------------------------
950 /** Sets the master volume for all sound effects.
951  *  \param gain The volume to set.
952  */
setMasterSFXVolume(float gain)953 void SFXManager::setMasterSFXVolume(float gain)
954 {
955     if (gain > 1.0)  gain = 1.0f;
956     if (gain < 0.0f) gain = 0.0f;
957 
958     m_master_gain = gain;
959 
960     // regular SFX
961     {
962         m_all_sfx.lock();
963         for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
964                                              i!=m_all_sfx.getData().end(); i++)
965         {
966             (*i)->setMasterVolume(m_master_gain);
967         }   // for i in m_all_sfx
968         m_all_sfx.unlock();
969     }
970 
971     // quick SFX
972     {
973         m_quick_sounds.lock();
974         std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.getData().begin();
975         for (; i != m_quick_sounds.getData().end(); i++)
976         {
977             (*i).second->setMasterVolume(m_master_gain);
978         }
979         m_quick_sounds.unlock();
980     }
981 
982 }   // setMasterSFXVolume
983 
984 //-----------------------------------------------------------------------------
getErrorString(int err)985 const std::string SFXManager::getErrorString(int err)
986 {
987 #ifdef ENABLE_SOUND
988     if (!UserConfigParams::m_enable_sound)
989         return std::string("sound disabled");
990 
991     switch(err)
992     {
993         case AL_NO_ERROR:          return std::string("AL_NO_ERROR"         );
994         case AL_INVALID_NAME:      return std::string("AL_INVALID_NAME"     );
995         case AL_INVALID_ENUM:      return std::string("AL_INVALID_ENUM"     );
996         case AL_INVALID_VALUE:     return std::string("AL_INVALID_VALUE"    );
997         case AL_INVALID_OPERATION: return std::string("AL_INVALID_OPERATION");
998         case AL_OUT_OF_MEMORY:     return std::string("AL_OUT_OF_MEMORY"    );
999         default:                   return std::string("UNKNOWN");
1000     };
1001 #endif
1002 
1003     return std::string("sound disabled");
1004 }   // getErrorString
1005 
1006 //-----------------------------------------------------------------------------
1007 /** Sets the position and orientation of the listener.
1008  *  \param position Position of the listener.
1009  *  \param front Which way the listener is facing.
1010  *  \param up The up direction of the listener.
1011  */
positionListener(const Vec3 & position,const Vec3 & front,const Vec3 & up)1012 void SFXManager::positionListener(const Vec3 &position, const Vec3 &front,
1013                                   const Vec3 &up)
1014 {
1015     m_listener_position.lock();
1016     m_listener_position.getData() = position;
1017     m_listener_front              = front;
1018     m_listener_up                 = up;
1019     m_listener_position.unlock();
1020     queue(SFX_LISTENER);
1021 }   // positionListener
1022 
1023 //-----------------------------------------------------------------------------
1024 /** Sets the position and orientation of the listener.
1025  *  \param position Position of the listener.
1026  *  \param front Which way the listener is facing.
1027  */
reallyPositionListenerNow()1028 void SFXManager::reallyPositionListenerNow()
1029 {
1030 #ifdef ENABLE_SOUND
1031     if (!sfxAllowed()) return;
1032 
1033     m_listener_position.lock();
1034     {
1035 
1036         //forward vector
1037         float orientation[6];
1038         orientation[0] = m_listener_front.getX();
1039         orientation[1] = m_listener_front.getY();
1040         orientation[2] = -m_listener_front.getZ();
1041 
1042         //up vector
1043         orientation[3] = m_listener_up.getX();
1044         orientation[4] = m_listener_up.getY();
1045         orientation[5] = -m_listener_up.getZ();
1046 
1047         const Vec3 &pos = m_listener_position.getData();
1048         alListener3f(AL_POSITION, pos.getX(), pos.getY(), -pos.getZ());
1049         alListenerfv(AL_ORIENTATION, orientation);
1050     }
1051     m_listener_position.unlock();
1052 
1053 #endif
1054 }   // reallyPositionListenerNow
1055 
1056 //-----------------------------------------------------------------------------
1057 /** Positional sound is cool, but creating a new object just to play a simple
1058  *  menu sound is not. This function allows for 'quick sounds' in a single call.
1059  *  \param sound_type Internal name of the sfx to play.
1060  *  \return a pointer to the sound, for instance to check when the sound finished.
1061  *          don't delete the returned pointer.
1062  */
quickSound(const std::string & sound_type)1063 SFXBase* SFXManager::quickSound(const std::string &sound_type)
1064 {
1065 #ifdef ENABLE_SOUND
1066     if (!sfxAllowed()) return NULL;
1067 
1068     std::unique_lock<std::mutex> ul = m_quick_sounds.acquireMutex();
1069     std::map<std::string, SFXBase*>::iterator sound =
1070                                      m_quick_sounds.getData().find(sound_type);
1071 
1072     if (sound == m_quick_sounds.getData().end())
1073     {
1074         // sound not yet in our local list of quick sounds
1075         SFXBase* new_sound = createSoundSource(sound_type, false);
1076         if (new_sound == NULL) return NULL;
1077         new_sound->play();
1078         m_quick_sounds.getData()[sound_type] = new_sound;
1079         return new_sound;
1080     }
1081     else
1082     {
1083         SFXBase *base_sound = sound->second;
1084         if (base_sound->getStatus() != SFXBase::SFX_PLAYING)
1085             base_sound->play();
1086         return base_sound;
1087     }
1088 #else
1089     return NULL;
1090 #endif
1091 }   // quickSound
1092 
1093