1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ultima/nuvie/core/nuvie_defs.h"
24 #include "ultima/nuvie/misc/u6_misc.h"
25 #include "ultima/nuvie/core/u6_objects.h"
26 #include "ultima/nuvie/sound/sound_manager.h"
27 #include "ultima/nuvie/sound/adplug/emu_opl.h"
28 #include "ultima/nuvie/sound/song_adplug.h"
29 #include "ultima/nuvie/core/game.h"
30 #include "ultima/nuvie/core/player.h"
31 #include "ultima/nuvie/gui/widgets/map_window.h"
32 #include "ultima/nuvie/core/effect.h"
33 #include "ultima/nuvie/sound/adplug/emu_opl.h"
34 #include "ultima/nuvie/sound/adlib_sfx_manager.h"
35 #include "ultima/nuvie/sound/pc_speaker_sfx_manager.h"
36 #include "ultima/nuvie/sound/towns_sfx_manager.h"
37 #include "ultima/nuvie/sound/custom_sfx_manager.h"
38 #include "audio/mixer.h"
39 #include "common/algorithm.h"
40
41 namespace Ultima {
42 namespace Nuvie {
43
44 struct ObjSfxLookup { // obj sfx lookup
45 uint16 obj_n;
46 SfxIdType sfx_id;
47 };
48
49 #define SOUNDMANANGER_OBJSFX_TBL_SIZE 5
50
51 static const ObjSfxLookup u6_obj_lookup_tbl[] = {
52 {OBJ_U6_FOUNTAIN, NUVIE_SFX_FOUNTAIN},
53 {OBJ_U6_FIREPLACE, NUVIE_SFX_FIRE},
54 {OBJ_U6_CLOCK, NUVIE_SFX_CLOCK},
55 {OBJ_U6_PROTECTION_FIELD, NUVIE_SFX_PROTECTION_FIELD},
56 {OBJ_U6_WATER_WHEEL, NUVIE_SFX_WATER_WHEEL}
57 };
58
59
60
61 bool SoundManager::g_MusicFinished;
62
musicFinished()63 void musicFinished() {
64 SoundManager::g_MusicFinished = true;
65 }
66
SoundManager(Audio::Mixer * mixer)67 SoundManager::SoundManager(Audio::Mixer *mixer) : _mixer(mixer) {
68 m_pCurrentSong = NULL;
69 m_CurrentGroup = "";
70 g_MusicFinished = true;
71
72 audio_enabled = false;
73 music_enabled = false;
74 sfx_enabled = false;
75
76 m_Config = NULL;
77 m_SfxManager = NULL;
78
79 opl = NULL;
80 }
81
~SoundManager()82 SoundManager::~SoundManager() {
83 // Stop all mixing
84 _mixer->stopAll();
85
86 //thanks to wjp for this one
87 while (!m_Songs.empty()) {
88 delete *(m_Songs.begin());
89 m_Songs.erase(m_Songs.begin());
90 }
91 while (!m_Samples.empty()) {
92 delete *(m_Samples.begin());
93 m_Samples.erase(m_Samples.begin());
94 }
95
96 delete opl;
97
98 for (IntCollectionMap::iterator it = m_ObjectSampleMap.begin(); it != m_ObjectSampleMap.end(); ++it)
99 delete it->_value;
100 for (IntCollectionMap::iterator it = m_TileSampleMap.begin(); it != m_TileSampleMap.end(); ++it)
101 delete it->_value;
102 for (StringCollectionMap::iterator it = m_MusicMap.begin(); it != m_MusicMap.end(); ++it)
103 delete it->_value;
104
105 delete m_SfxManager;
106 }
107
nuvieStartup(Configuration * config)108 bool SoundManager::nuvieStartup(Configuration *config) {
109 Std::string config_key;
110 Std::string music_style;
111 Std::string music_cfg_file; //full path and filename to music.cfg
112 Std::string sound_dir;
113 Std::string sfx_style;
114 bool val;
115
116 m_Config = config;
117
118 m_Config->value("config/mute", val, false);
119 audio_enabled = !val;
120 m_Config->value("config/GameType", game_type);
121 m_Config->value("config/audio/stop_music_on_group_change", stop_music_on_group_change, true);
122
123 /* if(audio_enabled == false) // commented out to allow toggling
124 {
125 music_enabled = false;
126 sfx_enabled = false;
127 music_volume = 0;
128 sfx_volume = 0;
129 mixer = NULL;
130 return false;
131 }*/
132
133 m_Config->value("config/music_mute", val, false);
134 music_enabled = !val;
135 m_Config->value("config/sfx_mute", val, false);
136 sfx_enabled = !val;
137
138 int volume;
139
140 m_Config->value("config/music_volume", volume, Audio::Mixer::kMaxChannelVolume);
141 music_volume = clamp(volume, 0, 255);
142
143 m_Config->value("config/sfx_volume", volume, Audio::Mixer::kMaxChannelVolume);
144 sfx_volume = clamp(volume, 0, 255);
145
146 config_key = config_get_game_key(config);
147 config_key.append("/music");
148 config->value(config_key, music_style, "native");
149
150 config_key = config_get_game_key(config);
151 config_key.append("/sfx");
152 config->value(config_key, sfx_style, "native");
153
154 config_key = config_get_game_key(config);
155 config_key.append("/sounddir");
156 config->value(config_key, sound_dir, "");
157
158 if (game_type == NUVIE_GAME_U6) { // FM-Towns speech
159 config->value("config/speech_mute", val, false);
160 speech_enabled = !val;
161 } else {
162 speech_enabled = false;
163 }
164
165 if (!initAudio()) {
166 return false;
167 }
168
169 // if(music_enabled) // commented out to allow toggling
170 {
171 if (music_style == "native") {
172 if (game_type == NUVIE_GAME_U6)
173 LoadNativeU6Songs(); //FIX need to handle MD & SE music too.
174 } else if (music_style == "custom")
175 LoadCustomSongs(sound_dir);
176 else
177 DEBUG(0, LEVEL_WARNING, "Unknown music style '%s'\n", music_style.c_str());
178
179 musicPlayFrom("random");
180 }
181
182 // if(sfx_enabled) // commented out to allow toggling
183 {
184 //LoadObjectSamples(sound_dir);
185 //LoadTileSamples(sound_dir);
186 LoadSfxManager(sfx_style);
187 }
188
189 return true;
190 }
191
initAudio()192 bool SoundManager::initAudio() {
193 opl = new CEmuopl(_mixer->getOutputRate(), true, true);
194 return true;
195 }
196
LoadNativeU6Songs()197 bool SoundManager::LoadNativeU6Songs() {
198 Song *song;
199
200 string filename;
201
202 config_get_path(m_Config, "brit.m", filename);
203 song = new SongAdPlug(_mixer, opl);
204 // loadSong(song, filename.c_str());
205 loadSong(song, filename.c_str(), "Rule Britannia");
206 groupAddSong("random", song);
207
208 config_get_path(m_Config, "forest.m", filename);
209 song = new SongAdPlug(_mixer, opl);
210 loadSong(song, filename.c_str(), "Wanderer (Forest)");
211 groupAddSong("random", song);
212
213 config_get_path(m_Config, "stones.m", filename);
214 song = new SongAdPlug(_mixer, opl);
215 loadSong(song, filename.c_str(), "Stones");
216 groupAddSong("random", song);
217
218 config_get_path(m_Config, "ultima.m", filename);
219 song = new SongAdPlug(_mixer, opl);
220 loadSong(song, filename.c_str(), "Ultima VI Theme");
221 groupAddSong("random", song);
222
223 config_get_path(m_Config, "engage.m", filename);
224 song = new SongAdPlug(_mixer, opl);
225 loadSong(song, filename.c_str(), "Engagement and Melee");
226 groupAddSong("combat", song);
227
228 config_get_path(m_Config, "hornpipe.m", filename);
229 song = new SongAdPlug(_mixer, opl);
230 loadSong(song, filename.c_str(), "Captain Johne's Hornpipe");
231 groupAddSong("boat", song);
232
233 config_get_path(m_Config, "gargoyle.m", filename);
234 song = new SongAdPlug(_mixer, opl);
235 loadSong(song, filename.c_str(), "Audchar Gargl Zenmur");
236 groupAddSong("gargoyle", song);
237
238 config_get_path(m_Config, "dungeon.m", filename);
239 song = new SongAdPlug(_mixer, opl);
240 loadSong(song, filename.c_str(), "Dungeon");
241 groupAddSong("dungeon", song);
242
243 return true;
244 }
245
LoadCustomSongs(string sound_dir)246 bool SoundManager::LoadCustomSongs(string sound_dir) {
247 char seps[] = ";\r\n";
248 char *token1;
249 char *token2;
250 char *sz;
251 NuvieIOFileRead niof;
252 Song *song;
253 Std::string scriptname;
254 Std::string filename;
255
256 build_path(sound_dir, "music.cfg", scriptname);
257
258 if (niof.open(scriptname) == false)
259 return false;
260
261 sz = (char *)niof.readAll();
262
263 if (sz == NULL)
264 return false;
265
266 token1 = strtok(sz, seps);
267 for (; (token1 != NULL) && ((token2 = strtok(NULL, seps)) != NULL) ; token1 = strtok(NULL, seps)) {
268 build_path(sound_dir, token2, filename);
269
270 song = (Song *)SongExists(token2);
271 if (song == NULL) {
272 song = new Song;
273 if (!loadSong(song, filename.c_str()))
274 continue; //error loading song
275 }
276
277 if (groupAddSong(token1, song))
278 DEBUG(0, LEVEL_DEBUGGING, "%s : %s\n", token1, token2);
279 }
280
281 free(sz);
282
283 return true;
284 }
285
loadSong(Song * song,const char * filename)286 bool SoundManager::loadSong(Song *song, const char *filename) {
287 if (song->Init(filename)) {
288 m_Songs.push_back(song); //add it to our global list
289 return true;
290 } else {
291 DEBUG(0, LEVEL_ERROR, "could not load %s\n", filename);
292 }
293
294 return false;
295 }
296
297 // (SB-X)
loadSong(Song * song,const char * filename,const char * title)298 bool SoundManager::loadSong(Song *song, const char *filename, const char *title) {
299 if (loadSong(song, filename) == true) {
300 song->SetName(title);
301 return true;
302 }
303 return false;
304 }
305
groupAddSong(const char * group,Song * song)306 bool SoundManager::groupAddSong(const char *group, Song *song) {
307 if (song != NULL) {
308 //we have a valid song
309 SoundCollection *psc;
310 Std::map <Common::String, SoundCollection * >::iterator it;
311 it = m_MusicMap.find(group);
312 if (it == m_MusicMap.end()) {
313 //is there already a collection for this entry?
314 psc = new SoundCollection(); // no, create a new sound collection
315 psc->m_Sounds.push_back(song); // add this sound to the collection
316 m_MusicMap[group] = psc; // insert this pair into the map
317 } else {
318 psc = (*it)._value; // yes, get the existing
319 psc->m_Sounds.push_back(song); // add this sound to the collection
320 }
321 }
322
323 return true;
324 }
325
326 /*
327 bool SoundManager::LoadObjectSamples (string sound_dir)
328 {
329 char seps[] = ";\r\n";
330 char *token1;
331 char *token2;
332 NuvieIOFileRead niof;
333 char *sz;
334 string samplename;
335 string scriptname;
336
337 build_path(sound_dir, "obj_samples.cfg", scriptname);
338
339 if(niof.open (scriptname) == false)
340 return false;
341
342 sz = (char *) niof.readAll ();
343
344 token1 = strtok (sz, seps);
345
346 while ((token1 != NULL) && ((token2 = strtok (NULL, seps)) != NULL))
347 {
348 int id = atoi (token1);
349 DEBUG(0,LEVEL_DEBUGGING,"%d : %s\n", id, token2);
350 Sound *ps;
351 ps = SampleExists (token2);
352 if (ps == NULL)
353 {
354 Sample *s;
355 s = new Sample;
356 build_path(sound_dir, token2, samplename);
357 if (!s->Init (samplename.c_str ()))
358 {
359 DEBUG(0,LEVEL_ERROR,"could not load %s\n", samplename.c_str ());
360 }
361 ps = s;
362 m_Samples.push_back (ps); //add it to our global list
363 }
364 if (ps != NULL)
365 { //we have a valid sound
366 SoundCollection *psc;
367 Std::map < int, SoundCollection * >::iterator it;
368 it = m_ObjectSampleMap.find (id);
369 if (it == m_ObjectSampleMap.end ())
370 { //is there already a collection for this entry?
371 psc = new SoundCollection; //no, create a new sound collection
372 psc->m_Sounds.push_back (ps); //add this sound to the collection
373 m_ObjectSampleMap.insert (Std::make_pair (id, psc)); //insert this pair into the map
374 }
375 else
376 {
377 psc = (*it).second; //yes, get the existing
378 psc->m_Sounds.push_back (ps); //add this sound to the collection
379 }
380 }
381 token1 = strtok (NULL, seps);
382 }
383 return true;
384 };
385
386 bool SoundManager::LoadTileSamples (string sound_dir)
387 {
388 char seps[] = ";\r\n";
389 char *token1;
390 char *token2;
391 NuvieIOFileRead niof;
392 char *sz;
393 string samplename;
394 string scriptname;
395
396 build_path(sound_dir, "tile_samples.cfg", scriptname);
397
398 if(niof.open (scriptname) == false)
399 {
400 DEBUG(0,LEVEL_ERROR,"opening %s\n",scriptname.c_str());
401 return false;
402 }
403
404 sz = (char *) niof.readAll ();
405
406 token1 = strtok (sz, seps);
407
408 while ((token1 != NULL) && ((token2 = strtok (NULL, seps)) != NULL))
409 {
410 int id = atoi (token1);
411 DEBUG(0,LEVEL_DEBUGGING,"%d : %s\n", id, token2);
412 Sound *ps;
413 ps = SampleExists (token2);
414 if (ps == NULL)
415 {
416 Sample *s;
417 s = new Sample;
418 build_path(sound_dir, token2, samplename);
419 if (!s->Init (samplename.c_str ()))
420 {
421 DEBUG(0,LEVEL_ERROR,"could not load %s\n", samplename.c_str ());
422 }
423 ps = s;
424 m_Samples.push_back (ps); //add it to our global list
425 }
426 if (ps != NULL)
427 { //we have a valid sound
428 SoundCollection *psc;
429 Std::map < int, SoundCollection * >::iterator it;
430 it = m_TileSampleMap.find (id);
431 if (it == m_TileSampleMap.end ())
432 { //is there already a collection for this entry?
433 psc = new SoundCollection; //no, create a new sound collection
434 psc->m_Sounds.push_back (ps); //add this sound to the collection
435 m_TileSampleMap.insert (Std::make_pair (id, psc)); //insert this pair into the map
436 }
437 else
438 {
439 psc = (*it).second; //yes, get the existing
440 psc->m_Sounds.push_back (ps); //add this sound to the collection
441 }
442 }
443 token1 = strtok (NULL, seps);
444 }
445 return true;
446 };
447 */
LoadSfxManager(string sfx_style)448 bool SoundManager::LoadSfxManager(string sfx_style) {
449 if (m_SfxManager != NULL) {
450 return false;
451 }
452
453 if (sfx_style == "native") {
454 switch (game_type) {
455 case NUVIE_GAME_U6 :
456 if (has_fmtowns_support(m_Config)) {
457 sfx_style = "towns";
458 } else {
459 sfx_style = "pcspeaker";
460 }
461 break;
462 case NUVIE_GAME_MD :
463 case NUVIE_GAME_SE :
464 sfx_style = "adlib";
465 break;
466 }
467 }
468
469 if (sfx_style == "pcspeaker") {
470 m_SfxManager = new PCSpeakerSfxManager(m_Config, _mixer);
471 }
472 if (sfx_style == "adlib") {
473 m_SfxManager = new AdLibSfxManager(m_Config, _mixer);
474 } else if (sfx_style == "towns") {
475 m_SfxManager = new TownsSfxManager(m_Config, _mixer);
476 } else if (sfx_style == "custom") {
477 m_SfxManager = new CustomSfxManager(m_Config, _mixer);
478 }
479 //FIXME what to do if unknown sfx_style is entered in config file.
480 return true;
481 }
482
musicPlayFrom(string group)483 void SoundManager::musicPlayFrom(string group) {
484 if (!music_enabled || !audio_enabled)
485 return;
486 if (m_CurrentGroup != group) {
487 if (stop_music_on_group_change)
488 g_MusicFinished = true;
489 m_CurrentGroup = group;
490 }
491 }
492
musicPause()493 void SoundManager::musicPause() {
494 //Mix_PauseMusic();
495 if (m_pCurrentSong != NULL) {
496 m_pCurrentSong->Stop();
497 }
498 }
499
500 /* don't call if audio or music is disabled */
musicPlay()501 void SoundManager::musicPlay() {
502 // Mix_ResumeMusic();
503
504 // (SB-X) Get a new song if stopped.
505 if (m_pCurrentSong == NULL)
506 m_pCurrentSong = RequestSong(m_CurrentGroup);
507
508 if (m_pCurrentSong != NULL) {
509 m_pCurrentSong->Play();
510 m_pCurrentSong->SetVolume(music_volume);
511 }
512
513 }
514
musicPlay(const char * filename,uint16 song_num)515 void SoundManager::musicPlay(const char *filename, uint16 song_num) {
516 string path;
517
518 if (!music_enabled || !audio_enabled)
519 return;
520
521 config_get_path(m_Config, filename, path);
522 SongAdPlug *song = new SongAdPlug(_mixer, opl);
523 song->Init(path.c_str(), song_num);
524
525 musicStop();
526 m_pCurrentSong = song;
527 m_CurrentGroup = "";
528 musicPlay();
529 }
530
531 // (SB-X) Stop the current song so a new song will play when resumed.
musicStop()532 void SoundManager::musicStop() {
533 musicPause();
534 m_pCurrentSong = NULL;
535 }
536
SoundManagerSfx_find(Std::list<SoundManagerSfx>::iterator first,Std::list<SoundManagerSfx>::iterator last,const SfxIdType & value)537 Std::list < SoundManagerSfx >::iterator SoundManagerSfx_find(Std::list < SoundManagerSfx >::iterator first, Std::list < SoundManagerSfx >::iterator last, const SfxIdType &value) {
538 for (; first != last; first++) {
539 if ((*first).sfx_id == value)
540 break;
541 }
542 return first;
543 }
544
update_map_sfx()545 void SoundManager::update_map_sfx() {
546 unsigned int i;
547 uint16 x, y;
548 uint8 l;
549
550 if (sfx_enabled == false)
551 return;
552
553 string next_group = "";
554 Player *p = Game::get_game()->get_player();
555 MapWindow *mw = Game::get_game()->get_map_window();
556
557 vector < SfxIdType >currentlyActiveSounds;
558 map < SfxIdType, float >volumeLevels;
559
560 p->get_location(&x, &y, &l);
561
562 //m_ViewableTiles
563
564 //get a list of all the sounds
565 for (i = 0; i < mw->m_ViewableObjects.size(); i++) {
566 //DEBUG(0,LEVEL_DEBUGGING,"%d %s",mw->m_ViewableObjects[i]->obj_n,Game::get_game()->get_obj_manager()->get_obj_name(mw->m_ViewableObjects[i]));
567 SfxIdType sfx_id = RequestObjectSfxId(mw->m_ViewableObjects[i]->obj_n); //does this object have an associated sound?
568 if (sfx_id != NUVIE_SFX_NONE) {
569 //calculate the volume
570 uint16 ox = mw->m_ViewableObjects[i]->x;
571 uint16 oy = mw->m_ViewableObjects[i]->y;
572 float dist = sqrtf((float)(x - ox) * (x - ox) + (float)(y - oy) * (y - oy));
573 float vol = (8.0f - dist) / 8.0f;
574 if (vol < 0)
575 vol = 0;
576 //sp->SetVolume(vol);
577 //need the map to adjust volume according to number of active elements
578 Std::map < SfxIdType, float >::iterator it;
579 it = volumeLevels.find(sfx_id);
580 if (it != volumeLevels.end()) {
581 if (volumeLevels[sfx_id] < vol)
582 volumeLevels[sfx_id] = vol;
583 } else {
584 volumeLevels[sfx_id] = vol;
585 }
586 //add to currently active list
587 currentlyActiveSounds.push_back(sfx_id);
588 }
589 }
590 /*
591 for (i = 0; i < mw->m_ViewableTiles.size(); i++)
592 {
593 Sound *sp = RequestTileSound (mw->m_ViewableTiles[i].t->tile_num); //does this object have an associated sound?
594 if (sp != NULL)
595 {
596 //calculate the volume
597 short ox = mw->m_ViewableTiles[i].x - 5;
598 short oy = mw->m_ViewableTiles[i].y - 5;
599 // DEBUG(0,LEVEL_DEBUGGING,"%d %d\n",ox,oy);
600 float dist = sqrtf ((float) (ox) * (ox) + (float) (oy) * (oy));
601 // DEBUG(0,LEVEL_DEBUGGING,"%s %f\n",sp->GetName().c_str(),dist);
602 float vol = (7.0f - (dist - 1)) / 7.0f;
603 if (vol < 0)
604 vol = 0;
605 //sp->SetVolume(vol);
606 //need the map to adjust volume according to number of active elements
607 Std::map < Sound *, float >::iterator it;
608 it = volumeLevels.find (sp);
609 if (it != volumeLevels.end ())
610 {
611 float old = volumeLevels[sp];
612 // DEBUG(0,LEVEL_DEBUGGING,"old:%f new:%f\n",old,vol);
613 if (old < vol)
614 {
615 volumeLevels[sp] = vol;
616 }
617 }
618 else
619 {
620 volumeLevels.insert (Std::make_pair (sp, vol));
621 }
622 //add to currently active list
623 currentlyActiveSounds.push_back (sp);
624 }
625 }
626 */
627 //DEBUG(1,LEVEL_DEBUGGING,"\n");
628 //is this sound new? - activate it.
629 for (i = 0; i < currentlyActiveSounds.size(); i++) {
630 Std::list < SoundManagerSfx >::iterator it;
631 it = SoundManagerSfx_find(m_ActiveSounds.begin(), m_ActiveSounds.end(), currentlyActiveSounds[i]); //is the sound already active?
632 if (it == m_ActiveSounds.end()) {
633 //this is a new sound, add it to the active list
634 //currentlyActiveSounds[i]->Play (true);
635 //currentlyActiveSounds[i]->SetVolume (0);
636 SoundManagerSfx sfx;
637 sfx.sfx_id = currentlyActiveSounds[i];
638 if (m_SfxManager->playSfxLooping(sfx.sfx_id, &sfx.handle, 0)) {
639 m_ActiveSounds.push_back(sfx);//currentlyActiveSounds[i]);
640 }
641 }
642 }
643 //is this sound old? - deactivate it
644 Std::list < SoundManagerSfx >::iterator it;
645 it = m_ActiveSounds.begin();
646 while (it != m_ActiveSounds.end()) {
647 Std::vector<SfxIdType>::iterator fit;
648 SoundManagerSfx sfx = (*it);
649 fit = Common::find(currentlyActiveSounds.begin(), currentlyActiveSounds.end(), sfx.sfx_id); //is the sound in the new active list?
650 if (fit == currentlyActiveSounds.end()) {
651 //its not, stop this sound from playing.
652 //sfx_id->Stop ();
653 _mixer->stopHandle(sfx.handle);
654 it = m_ActiveSounds.erase(it);
655 } else {
656 _mixer->setChannelVolume(sfx.handle, (uint8)(volumeLevels[sfx.sfx_id] * (sfx_volume / 255.0f) * 255.0f));
657 it++;
658 }
659 }
660 }
661
update()662 void SoundManager::update() {
663 if (music_enabled && audio_enabled && g_MusicFinished) {
664 g_MusicFinished = false;
665 if (m_pCurrentSong != NULL) {
666 m_pCurrentSong->Stop();
667 }
668
669 if (m_CurrentGroup.length() > 0)
670 m_pCurrentSong = SoundManager::RequestSong(m_CurrentGroup);
671
672 if (m_pCurrentSong) {
673 DEBUG(0, LEVEL_INFORMATIONAL, "assigning new song! '%s'\n", m_pCurrentSong->GetName().c_str());
674 if (!m_pCurrentSong->Play(false)) {
675 DEBUG(0, LEVEL_ERROR, "play failed!\n");
676 }
677 m_pCurrentSong->SetVolume(music_volume);
678 }
679 }
680
681 }
682
683
SongExists(string name)684 Sound *SoundManager::SongExists(string name) {
685 Std::list < Sound * >::iterator it;
686 for (it = m_Songs.begin(); it != m_Songs.end(); ++it) {
687 if ((*it)->GetName() == name)
688 return *it;
689 }
690
691 return NULL;
692 }
693
SampleExists(string name)694 Sound *SoundManager::SampleExists(string name) {
695 Std::list < Sound * >::iterator it;
696 for (it = m_Samples.begin(); it != m_Samples.end(); ++it) {
697 if ((*it)->GetName() == name)
698 return *it;
699 }
700
701 return NULL;
702 }
703
RequestTileSound(int id)704 Sound *SoundManager::RequestTileSound(int id) {
705 Std::map < int, SoundCollection * >::iterator it;
706 it = m_TileSampleMap.find(id);
707 if (it != m_TileSampleMap.end()) {
708 SoundCollection *psc;
709 psc = (*it)._value;
710 return psc->Select();
711 }
712 return NULL;
713 }
714
RequestObjectSound(int id)715 Sound *SoundManager::RequestObjectSound(int id) {
716 Std::map < int, SoundCollection * >::iterator it;
717 it = m_ObjectSampleMap.find(id);
718 if (it != m_ObjectSampleMap.end()) {
719 SoundCollection *psc;
720 psc = (*it)._value;
721 return psc->Select();
722 }
723 return NULL;
724 }
725
RequestObjectSfxId(uint16 obj_n)726 uint16 SoundManager::RequestObjectSfxId(uint16 obj_n) {
727 uint16 i = 0;
728 for (i = 0; i < SOUNDMANANGER_OBJSFX_TBL_SIZE; i++) {
729 if (u6_obj_lookup_tbl[i].obj_n == obj_n) {
730 return u6_obj_lookup_tbl[i].sfx_id;
731 }
732 }
733
734 return NUVIE_SFX_NONE;
735 }
736
RequestSong(string group)737 Sound *SoundManager::RequestSong(string group) {
738 Std::map<Common::String, SoundCollection * >::iterator it;
739 it = m_MusicMap.find(group);
740 if (it != m_MusicMap.end()) {
741 SoundCollection *psc;
742 psc = (*it)._value;
743 return psc->Select();
744 }
745 return NULL;
746 }
747
playTownsSound(Std::string filename,uint16 sample_num)748 Audio::SoundHandle SoundManager::playTownsSound(Std::string filename, uint16 sample_num) {
749 FMtownsDecoderStream *stream = new FMtownsDecoderStream(filename, sample_num);
750 Audio::SoundHandle handle;
751 _mixer->playStream(Audio::Mixer::kSpeechSoundType, &handle, stream, -1);
752
753 return handle;
754 }
755
isSoundPLaying(Audio::SoundHandle handle)756 bool SoundManager::isSoundPLaying(Audio::SoundHandle handle) {
757 return _mixer->isSoundHandleActive(handle);
758 }
759
playSfx(uint16 sfx_id,bool async)760 bool SoundManager::playSfx(uint16 sfx_id, bool async) {
761 if (m_SfxManager == NULL || audio_enabled == false || sfx_enabled == false)
762 return false;
763
764 if (async) {
765 if (m_SfxManager->playSfx(sfx_id, sfx_volume)) {
766 uint32 duration = m_SfxManager->getLastSfxDuration();
767
768 TimedEffect *timer = new TimedEffect();
769
770 AsyncEffect *e = new AsyncEffect(timer);
771 timer->start_timer(duration);
772 e->run();
773
774 return true;
775 }
776 } else {
777 return m_SfxManager->playSfx(sfx_id, sfx_volume);
778 }
779
780 return false;
781 }
782
set_audio_enabled(bool val)783 void SoundManager::set_audio_enabled(bool val) {
784 audio_enabled = val;
785 if (audio_enabled && music_enabled)
786 musicPlay();
787 else
788 musicStop();
789 }
790
set_music_enabled(bool val)791 void SoundManager::set_music_enabled(bool val) {
792 music_enabled = val;
793 if (audio_enabled && music_enabled)
794 musicPlay();
795 else
796 musicStop();
797 }
798
set_speech_enabled(bool val)799 void SoundManager::set_speech_enabled(bool val) {
800 speech_enabled = val;
801 // FIXME - stop speech
802 }
803
804 } // End of namespace Nuvie
805 } // End of namespace Ultima
806