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 "audio/audiostream.h"
24 #include "audio/decoders/raw.h"
25 #include "common/config-manager.h"
26 #include "common/translation.h"
27 #include "gui/error.h"
28
29 #include "sci/sci.h"
30 #include "sci/console.h"
31 #include "sci/resource/resource.h"
32 #include "sci/engine/features.h"
33 #include "sci/engine/kernel.h"
34 #include "sci/engine/state.h"
35 #include "sci/sound/midiparser_sci.h"
36 #include "sci/sound/music.h"
37
38 //#define DEBUG_REMAP
39
40 namespace Sci {
41
SciMusic(SciVersion soundVersion,bool useDigitalSFX)42 SciMusic::SciMusic(SciVersion soundVersion, bool useDigitalSFX)
43 : _soundVersion(soundVersion), _soundOn(true), _masterVolume(15), _globalReverb(0), _useDigitalSFX(useDigitalSFX), _needsResume(soundVersion > SCI_VERSION_0_LATE), _globalPause(0) {
44
45 // Reserve some space in the playlist, to avoid expensive insertion
46 // operations
47 _playList.reserve(10);
48
49 for (int i = 0; i < 16; i++) {
50 _usedChannel[i] = 0;
51 _channelRemap[i] = -1;
52 _channelMap[i]._song = 0;
53 _channelMap[i]._channel = -1;
54 }
55
56 _queuedCommands.reserve(1000);
57 }
58
~SciMusic()59 SciMusic::~SciMusic() {
60 if (_pMidiDrv) {
61 _pMidiDrv->close();
62 delete _pMidiDrv;
63 }
64 }
65
init()66 void SciMusic::init() {
67 // system init
68 _pMixer = g_system->getMixer();
69 // SCI sound init
70 _dwTempo = 0;
71
72 const Common::Platform platform = g_sci->getPlatform();
73 uint32 deviceFlags;
74 if (g_sci->_features->generalMidiOnly()) {
75 deviceFlags = MDT_MIDI;
76 } else {
77 deviceFlags = MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI;
78 }
79
80 // Default to MIDI for Windows versions of SCI1.1 games, as their
81 // soundtrack is written for GM.
82 if (g_sci->_features->useAltWinGMSound())
83 deviceFlags |= MDT_PREFER_GM;
84
85 // SCI_VERSION_0_EARLY games apparently don't support the CMS. At least there
86 // is no patch resource 101 and I also haven't seen any CMS driver file so far.
87 if (getSciVersion() > SCI_VERSION_0_EARLY && getSciVersion() <= SCI_VERSION_1_1)
88 deviceFlags |= MDT_CMS;
89
90 if (platform == Common::kPlatformFMTowns) {
91 if (getSciVersion() > SCI_VERSION_1_EARLY)
92 deviceFlags = MDT_TOWNS;
93 else
94 deviceFlags |= MDT_TOWNS;
95 }
96
97 if (platform == Common::kPlatformPC98)
98 deviceFlags |= MDT_PC98;
99
100 uint32 dev = MidiDriver::detectDevice(deviceFlags);
101 _musicType = MidiDriver::getMusicType(dev);
102
103 if (g_sci->_features->useAltWinGMSound() && _musicType != MT_GM) {
104 warning("A Windows CD version with an alternate MIDI soundtrack has been chosen, "
105 "but no MIDI music device has been selected. Reverting to the DOS soundtrack");
106 g_sci->_features->forceDOSTracks();
107 #ifdef ENABLE_SCI32
108 } else if (g_sci->_features->generalMidiOnly() && _musicType != MT_GM) {
109 warning("This game only supports General MIDI, but a non-GM device has "
110 "been selected. Some music may be wrong or missing");
111 #endif
112 }
113
114 switch (_musicType) {
115 case MT_ADLIB:
116 // FIXME: There's no Amiga sound option, so we hook it up to AdLib
117 if (platform == Common::kPlatformMacintosh || platform == Common::kPlatformAmiga) {
118 if (getSciVersion() <= SCI_VERSION_0_LATE)
119 _pMidiDrv = MidiPlayer_AmigaMac0_create(_soundVersion, platform);
120 else
121 _pMidiDrv = MidiPlayer_AmigaMac1_create(_soundVersion, platform);
122 } else
123 _pMidiDrv = MidiPlayer_AdLib_create(_soundVersion);
124 break;
125 case MT_PCJR:
126 _pMidiDrv = MidiPlayer_PCJr_create(_soundVersion);
127 break;
128 case MT_PCSPK:
129 _pMidiDrv = MidiPlayer_PCSpeaker_create(_soundVersion);
130 break;
131 case MT_CMS:
132 _pMidiDrv = MidiPlayer_CMS_create(_soundVersion);
133 break;
134 case MT_TOWNS:
135 _pMidiDrv = MidiPlayer_FMTowns_create(_soundVersion);
136 break;
137 case MT_PC98:
138 _pMidiDrv = MidiPlayer_PC9801_create(_soundVersion);
139 break;
140 default:
141 if (ConfMan.getInt("midi_mode") == kMidiModeFB01
142 || (ConfMan.hasKey("native_fb01") && ConfMan.getBool("native_fb01")))
143 _pMidiDrv = MidiPlayer_Fb01_create(_soundVersion);
144 else
145 _pMidiDrv = MidiPlayer_Midi_create(_soundVersion);
146 }
147
148 if (_pMidiDrv && !_pMidiDrv->open()) {
149 _pMidiDrv->setTimerCallback(this, &miditimerCallback);
150 _dwTempo = _pMidiDrv->getBaseTempo();
151 } else {
152 if (g_sci->getGameId() == GID_FUNSEEKER ||
153 (g_sci->getGameId() == GID_GK2 && g_sci->isDemo())) {
154 // HACK: The Fun Seeker's Guide demo doesn't have patch 3 and the version
155 // of the Adlib driver (adl.drv) that it includes is unsupported. That demo
156 // doesn't have any sound anyway, so this shouldn't be fatal.
157 } else {
158 const char *missingFiles = _pMidiDrv->reportMissingFiles();
159 if (missingFiles) {
160 Common::U32String message = _(
161 "The selected audio driver requires the following file(s):\n\n"
162 );
163 message += Common::U32String(missingFiles);
164 message += _("\n\n"
165 "Some audio drivers (at least for some games) were made\n"
166 "available by Sierra as aftermarket patches and thus might not\n"
167 "have been installed as part of the original game setup.\n\n"
168 "Please copy these file(s) into your game data directory.\n\n"
169 "However, please note that the file(s) might not be available\n"
170 "separately but only as content of (patched) resource bundles.\n"
171 "In that case you may need to apply the original Sierra patch.\n\n"
172 );
173 ::GUI::displayErrorDialog(message);
174 }
175 error("Failed to initialize sound driver");
176 }
177 }
178
179 // Find out what the first possible channel is (used, when doing channel
180 // remapping).
181 _driverFirstChannel = _pMidiDrv->getFirstChannel();
182 _driverLastChannel = _pMidiDrv->getLastChannel();
183 if (getSciVersion() <= SCI_VERSION_0_LATE)
184 _globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0
185
186 _currentlyPlayingSample = NULL;
187 _timeCounter = 0;
188 _needsRemap = false;
189 }
190
miditimerCallback(void * p)191 void SciMusic::miditimerCallback(void *p) {
192 SciMusic *sciMusic = (SciMusic *)p;
193
194 Common::StackLock lock(sciMusic->_mutex);
195 sciMusic->onTimer();
196 }
197
onTimer()198 void SciMusic::onTimer() {
199 const MusicList::iterator end = _playList.end();
200 // sending out queued commands that were "sent" via main thread
201 sendMidiCommandsFromQueue();
202
203 // remap channels, if requested
204 if (_needsRemap)
205 remapChannels(false);
206 _needsRemap = false;
207
208 for (MusicList::iterator i = _playList.begin(); i != end; ++i)
209 (*i)->onTimer();
210 }
211
putMidiCommandInQueue(byte status,byte firstOp,byte secondOp)212 void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) {
213 putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
214 }
215
putMidiCommandInQueue(uint32 midi)216 void SciMusic::putMidiCommandInQueue(uint32 midi) {
217 _queuedCommands.push_back(MidiCommand(MidiCommand::kTypeMidiMessage, midi));
218 }
219
putTrackInitCommandInQueue(MusicEntry * psnd)220 void SciMusic::putTrackInitCommandInQueue(MusicEntry *psnd) {
221 _queuedCommands.push_back(MidiCommand(MidiCommand::kTypeTrackInit, psnd));
222 }
223
removeTrackInitCommandsFromQueue(MusicEntry * psnd)224 void SciMusic::removeTrackInitCommandsFromQueue(MusicEntry *psnd) {
225 for (MidiCommandQueue::iterator i = _queuedCommands.begin(); i != _queuedCommands.end(); )
226 i = (i->_type == MidiCommand::kTypeTrackInit && i->_dataPtr == (void*)psnd) ? _queuedCommands.erase(i) : i + 1;
227 }
228
229 // This sends the stored commands from queue to driver (is supposed to get
230 // called only during onTimer()). At least mt32 emulation doesn't like getting
231 // note-on commands from main thread (if we directly send, we would get a crash
232 // during piano scene in lsl5).
sendMidiCommandsFromQueue()233 void SciMusic::sendMidiCommandsFromQueue() {
234 uint curCommand = 0;
235 uint commandCount = _queuedCommands.size();
236
237 while (curCommand < commandCount) {
238 if (_queuedCommands[curCommand]._type == MidiCommand::kTypeTrackInit) {
239 if (_queuedCommands[curCommand]._dataPtr) {
240 MusicList::iterator psnd = Common::find(_playList.begin(), _playList.end(), static_cast<MusicEntry*>(_queuedCommands[curCommand]._dataPtr));
241 if (psnd != _playList.end() && (*psnd)->pMidiParser)
242 (*psnd)->pMidiParser->initTrack();
243 }
244 } else {
245 _pMidiDrv->send(_queuedCommands[curCommand]._dataVal);
246 }
247 curCommand++;
248 }
249 _queuedCommands.clear();
250 }
251
clearPlayList()252 void SciMusic::clearPlayList() {
253 // we must NOT lock our mutex here. Playlist is modified inside soundKill() which will lock the mutex
254 // during deletion. If we lock it here, a deadlock may occur within soundStop() because that one
255 // calls the mixer, which will also lock the mixer mutex and if the mixer thread is active during
256 // that time, we will get a deadlock.
257 while (!_playList.empty()) {
258 soundStop(_playList[0]);
259 soundKill(_playList[0]);
260 }
261 }
262
pauseAll(bool pause)263 void SciMusic::pauseAll(bool pause) {
264 const MusicList::iterator end = _playList.end();
265 if (pause)
266 _globalPause++;
267 else
268 _globalPause = MAX<int>(_globalPause - 1, 0);
269 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
270 #ifdef ENABLE_SCI32
271 // The entire DAC will have been paused by the caller;
272 // do not pause the individual samples too
273 if (_soundVersion >= SCI_VERSION_2 && (*i)->isSample) {
274 continue;
275 }
276 #endif
277 soundToggle(*i, pause);
278 }
279 }
280
stopAll()281 void SciMusic::stopAll() {
282 const MusicList::iterator end = _playList.end();
283 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
284 soundStop(*i);
285 }
286 }
287
stopAllSamples()288 void SciMusic::stopAllSamples() {
289 const MusicList::iterator end = _playList.end();
290 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
291 if ((*i)->isSample) {
292 soundStop(*i);
293 }
294 }
295 }
296
soundSetSoundOn(bool soundOnFlag)297 void SciMusic::soundSetSoundOn(bool soundOnFlag) {
298 Common::StackLock lock(_mutex);
299
300 _soundOn = soundOnFlag;
301 _pMidiDrv->playSwitch(soundOnFlag);
302 }
303
soundGetVoices()304 uint16 SciMusic::soundGetVoices() {
305 Common::StackLock lock(_mutex);
306
307 return _pMidiDrv->getPolyphony();
308 }
309
getSlot(reg_t obj)310 MusicEntry *SciMusic::getSlot(reg_t obj) {
311 Common::StackLock lock(_mutex);
312
313 const MusicList::iterator end = _playList.end();
314 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
315 if ((*i)->soundObj == obj)
316 return *i;
317 }
318
319 return NULL;
320 }
321
getFirstSlotWithStatus(SoundStatus status)322 MusicEntry *SciMusic::getFirstSlotWithStatus(SoundStatus status) {
323 for (MusicList::iterator i = _playList.begin(); i != _playList.end(); ++i) {
324 if ((*i)->status == status)
325 return *i;
326 }
327 return 0;
328 }
329
setGlobalReverb(int8 reverb)330 void SciMusic::setGlobalReverb(int8 reverb) {
331 Common::StackLock lock(_mutex);
332 if (reverb != 127) {
333 // Set global reverb normally
334 _globalReverb = reverb;
335
336 // Check the reverb of the active song...
337 const MusicList::iterator end = _playList.end();
338 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
339 if ((*i)->status == kSoundPlaying) {
340 if ((*i)->reverb == 127) // Active song has no reverb
341 _pMidiDrv->setReverb(reverb); // Set the global reverb
342 break;
343 }
344 }
345 } else {
346 // Set reverb of the active song
347 const MusicList::iterator end = _playList.end();
348 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
349 if ((*i)->status == kSoundPlaying) {
350 _pMidiDrv->setReverb((*i)->reverb); // Set the song's reverb
351 break;
352 }
353 }
354 }
355 }
356
getCurrentReverb()357 byte SciMusic::getCurrentReverb() {
358 Common::StackLock lock(_mutex);
359 return _pMidiDrv->getReverb();
360 }
361
362 // A larger priority value has higher priority. For equal priority values,
363 // songs that have been added later have higher priority.
musicEntryCompare(const MusicEntry * l,const MusicEntry * r)364 static bool musicEntryCompare(const MusicEntry *l, const MusicEntry *r) {
365 return (l->priority > r->priority) || (l->priority == r->priority && l->time > r->time);
366 }
367
sortPlayList()368 void SciMusic::sortPlayList() {
369 // Sort the play list in descending priority order
370 Common::sort(_playList.begin(), _playList.end(), musicEntryCompare);
371 }
372
soundInitSnd(MusicEntry * pSnd)373 void SciMusic::soundInitSnd(MusicEntry *pSnd) {
374 // Remove all currently mapped channels of this MusicEntry first,
375 // since they will no longer be valid.
376 for (int i = 0; i < 16; ++i) {
377 if (_channelMap[i]._song == pSnd) {
378 _channelMap[i]._song = 0;
379 _channelMap[i]._channel = -1;
380 }
381 }
382
383 int channelFilterMask = 0;
384 SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId());
385
386 // If MIDI device is selected but there is no digital track in sound
387 // resource try to use Adlib's digital sample if possible. Also, if the
388 // track couldn't be found, load the digital track, as some games depend on
389 // this (e.g. the Longbow demo).
390 if (!track || (_useDigitalSFX && track->digitalChannelNr == -1)) {
391 SoundResource::Track *digital = pSnd->soundRes->getDigitalTrack();
392 if (digital)
393 track = digital;
394 }
395
396 pSnd->time = ++_timeCounter;
397
398 if (track) {
399 bool playSample;
400
401 if (_soundVersion <= SCI_VERSION_0_LATE && !_useDigitalSFX) {
402 // For SCI0 the digital sample is present in the same track as the
403 // MIDI. If the user specifically requests not to use the digital
404 // samples, play the MIDI data instead. If the MIDI portion of the
405 // track is empty however, play the digital sample anyway. This is
406 // necessary for e.g. the "Where am I?" sample in the SQ3 intro.
407 playSample = false;
408
409 if (track->channelCount == 2) {
410 SoundResource::Channel &chan = track->channels[0];
411 if (chan.data.size() < 2 || chan.data[1] == SCI_MIDI_EOT) {
412 playSample = true;
413 }
414 }
415 } else
416 playSample = (track->digitalChannelNr != -1 && (_useDigitalSFX || track->channelCount == 1));
417
418 // Play digital sample
419 if (playSample) {
420 const SciSpan<const byte> &channelData = track->channels[track->digitalChannelNr].data;
421 delete pSnd->pStreamAud;
422 byte flags = Audio::FLAG_UNSIGNED;
423 // Amiga SCI1 games had signed sound data
424 if (_soundVersion >= SCI_VERSION_1_EARLY && g_sci->getPlatform() == Common::kPlatformAmiga)
425 flags = 0;
426 int endPart = track->digitalSampleEnd > 0 ? (track->digitalSampleSize - track->digitalSampleEnd) : 0;
427 const uint size = track->digitalSampleSize - track->digitalSampleStart - endPart;
428 pSnd->pStreamAud = Audio::makeRawStream(channelData.getUnsafeDataAt(track->digitalSampleStart),
429 size, track->digitalSampleRate, flags, DisposeAfterUse::NO);
430 assert(pSnd->pStreamAud);
431 delete pSnd->pLoopStream;
432 pSnd->pLoopStream = 0;
433 pSnd->soundType = Audio::Mixer::kSFXSoundType;
434 pSnd->hCurrentAud = Audio::SoundHandle();
435 pSnd->playBed = false;
436 pSnd->overridePriority = false;
437 pSnd->isSample = true;
438 } else {
439 // play MIDI track
440 Common::StackLock lock(_mutex);
441 pSnd->soundType = Audio::Mixer::kMusicSoundType;
442 if (pSnd->pMidiParser == NULL) {
443 pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
444 pSnd->pMidiParser->setMidiDriver(_pMidiDrv);
445 pSnd->pMidiParser->setTimerRate(_dwTempo);
446 pSnd->pMidiParser->setMasterVolume(_masterVolume);
447 }
448
449 pSnd->pauseCounter = 0;
450
451 // Find out what channels to filter for SCI0
452 channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
453
454 for (int i = 0; i < 16; ++i)
455 pSnd->_usedChannels[i] = 0xFF;
456 for (int i = 0; i < track->channelCount; ++i) {
457 // skip digital channel
458 if (i == track->digitalChannelNr) {
459 continue;
460 }
461
462 SoundResource::Channel &chan = track->channels[i];
463
464 assert(chan.number < ARRAYSIZE(pSnd->_chan));
465 pSnd->_usedChannels[i] = chan.number;
466 pSnd->_chan[chan.number]._dontRemap = (chan.flags & 2);
467 pSnd->_chan[chan.number]._prio = chan.prio;
468 pSnd->_chan[chan.number]._voices = chan.poly;
469
470 // CHECKME: Some SCI versions use chan.flags & 1 for this:
471 pSnd->_chan[chan.number]._dontMap = false;
472
473 // FIXME: Most MIDI tracks use the first 10 bytes for
474 // fixed MIDI commands. SSCI skips those the first iteration,
475 // but _does_ update channel state (including volume) with
476 // them. Specifically, prio/voices, patch, volume, pan.
477 // This should probably be implemented in
478 // MidiParser_SCI::loadMusic.
479 }
480
481 pSnd->pMidiParser->mainThreadBegin();
482 // loadMusic() below calls jumpToTick.
483 // Disable sound looping and hold before jumpToTick is called,
484 // otherwise the song may keep looping forever when it ends in
485 // jumpToTick (e.g. LSL3, when going left from room 210).
486 uint16 prevLoop = pSnd->loop;
487 int16 prevHold = pSnd->hold;
488 pSnd->loop = 0;
489 pSnd->hold = -1;
490 pSnd->playBed = false;
491 pSnd->overridePriority = false;
492
493 pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
494 pSnd->reverb = pSnd->pMidiParser->getSongReverb();
495
496 // Restore looping and hold
497 pSnd->loop = prevLoop;
498 pSnd->hold = prevHold;
499 pSnd->pMidiParser->mainThreadEnd();
500 }
501 }
502 }
503
soundPlay(MusicEntry * pSnd,bool restoring)504 void SciMusic::soundPlay(MusicEntry *pSnd, bool restoring) {
505 _mutex.lock();
506
507 if (_soundVersion <= SCI_VERSION_1_EARLY && pSnd->playBed) {
508 // If pSnd->playBed, and version <= SCI1_EARLY, then kill
509 // existing sounds with playBed enabled.
510
511 uint playListCount = _playList.size();
512 for (uint i = 0; i < playListCount; i++) {
513 if (_playList[i] != pSnd && _playList[i]->playBed) {
514 debugC(2, kDebugLevelSound, "Automatically stopping old playBed song from soundPlay");
515 MusicEntry *old = _playList[i];
516 _mutex.unlock();
517 soundStop(old);
518 _mutex.lock();
519 break;
520 }
521 }
522 }
523
524 uint playListCount = _playList.size();
525 uint playListNo = playListCount;
526 MusicEntry *alreadyPlaying = NULL;
527
528 // searching if sound is already in _playList
529 for (uint i = 0; i < playListCount; i++) {
530 if (_playList[i] == pSnd)
531 playListNo = i;
532 if ((_playList[i]->status == kSoundPlaying) && (_playList[i]->pMidiParser))
533 alreadyPlaying = _playList[i];
534 }
535 if (playListNo == playListCount) { // not found
536 _playList.push_back(pSnd);
537 }
538
539 pSnd->time = ++_timeCounter;
540 sortPlayList();
541
542 _mutex.unlock(); // unlock to perform mixer-related calls
543
544 if (pSnd->pMidiParser) {
545 // Original SCI0 doesn't use this function to restore sound. The function it has
546 // for that will not check priorities.
547 if ((_soundVersion <= SCI_VERSION_0_LATE) && alreadyPlaying && !restoring) {
548 // Music already playing in SCI0?
549 if (pSnd->priority > alreadyPlaying->priority) {
550 // And new priority higher? pause previous music and play new one immediately.
551 // Example of such case: lsl3, when getting points (jingle is played then)
552 soundPause(alreadyPlaying);
553 } else {
554 // And new priority equal or lower? queue up music and play it afterwards done by
555 // SoundCommandParser::updateSci0Cues()
556 // Example of such case: iceman room 14
557 pSnd->status = kSoundPaused;
558 return;
559 }
560 }
561 }
562
563 if (pSnd->isSample) {
564 #ifdef ENABLE_SCI32
565 if (_soundVersion >= SCI_VERSION_2) {
566 // TODO: Sound number, loop state, and volume come from soundObj
567 // in SSCI. Getting them from MusicEntry could cause a bug if the
568 // soundObj was updated by a game script and not copied back to
569 // MusicEntry.
570 g_sci->_audio32->restart(ResourceId(kResourceTypeAudio, pSnd->resourceId), true, pSnd->loop != 0 && pSnd->loop != 1, pSnd->volume, pSnd->soundObj, false);
571 return;
572 }
573 #endif
574 if (_currentlyPlayingSample && _pMixer->isSoundHandleActive(_currentlyPlayingSample->hCurrentAud)) {
575 // Another sample is already playing, we have to stop that one
576 // SSCI is only able to play 1 sample at a time
577 // In Space Quest 5 room 250 the player is able to open the air-hatch and kill himself.
578 // In that situation the scripts are playing 2 samples at the same time and the first sample
579 // is not supposed to play.
580 // TODO: SSCI actually calls kDoAudio(play) internally, which stops other samples from being played
581 // but such a change isn't trivial, because we also handle Sound resources in here, that contain samples
582 _pMixer->stopHandle(_currentlyPlayingSample->hCurrentAud);
583 warning("kDoSound: sample already playing, old resource %d, new resource %d", _currentlyPlayingSample->resourceId, pSnd->resourceId);
584 }
585 // Sierra SCI ignores volume set when playing samples via kDoSound
586 // At least freddy pharkas/CD has a script bug that sets volume to 0
587 // when playing the "score" sample
588 if (pSnd->loop > 1) {
589 pSnd->pLoopStream = new Audio::LoopingAudioStream(pSnd->pStreamAud, pSnd->loop, DisposeAfterUse::NO);
590 _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud,
591 pSnd->pLoopStream, -1, _pMixer->kMaxChannelVolume, 0,
592 DisposeAfterUse::NO);
593 } else {
594 // Rewind in case we play the same sample multiple times
595 // (non-looped) like in pharkas right at the start
596 pSnd->pStreamAud->rewind();
597 _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud,
598 pSnd->pStreamAud, -1, _pMixer->kMaxChannelVolume, 0,
599 DisposeAfterUse::NO);
600 }
601 // Remember the sample, that is now playing
602 _currentlyPlayingSample = pSnd;
603 } else {
604 if (pSnd->pMidiParser) {
605 Common::StackLock lock(_mutex);
606 pSnd->pMidiParser->mainThreadBegin();
607
608 // The track init always needs to be done. Otherwise some sounds will not be properly set up (bug #11476).
609 // It is also safe to do this for paused tracks, since the jumpToTick() command further down will parse through
610 // the song from the beginning up to the resume position and ensure that the actual current voice mapping,
611 // instrument and volume settings etc. are correct.
612 // First glance at disasm might suggest that it has to be called only once per sound. But the truth is that
613 // when calling the sound driver opcode for sound restoring (opcode no. 9, we don't have that) it will
614 // internally also call initTrack(). And it wouldn't make sense otherwise, since without that the channel setup
615 // from the last sound would still be active.
616 pSnd->pMidiParser->initTrack();
617
618 if (pSnd->status != kSoundPaused)
619 pSnd->pMidiParser->sendInitCommands();
620 pSnd->pMidiParser->setVolume(pSnd->volume);
621
622 // Disable sound looping and hold before jumpToTick is called,
623 // otherwise the song may keep looping forever when it ends in jumpToTick.
624 // This is needed when loading saved games, or when a game
625 // stops the same sound twice (e.g. LSL3 Amiga, going left from
626 // room 210 to talk with Kalalau). Fixes bugs #5404 and #5503.
627 uint16 prevLoop = pSnd->loop;
628 int16 prevHold = pSnd->hold;
629 pSnd->loop = 0;
630 pSnd->hold = -1;
631
632 bool fastForward = (pSnd->status == kSoundPaused) || (pSnd->status == kSoundPlaying && restoring);
633 if (!fastForward) {
634 pSnd->pMidiParser->jumpToTick(0);
635 } else {
636 // Fast forward to the last position and perform associated events when loading
637 pSnd->pMidiParser->jumpToTick(pSnd->ticker, true, true, true);
638 }
639
640 // Restore looping and hold
641 pSnd->loop = prevLoop;
642 pSnd->hold = prevHold;
643 pSnd->pMidiParser->mainThreadEnd();
644 }
645 }
646
647 pSnd->status = kSoundPlaying;
648
649 _mutex.lock();
650 remapChannels();
651 _mutex.unlock();
652 }
653
soundStop(MusicEntry * pSnd)654 void SciMusic::soundStop(MusicEntry *pSnd) {
655 SoundStatus previousStatus = pSnd->status;
656 pSnd->status = kSoundStopped;
657
658 if (pSnd->isSample) {
659 #ifdef ENABLE_SCI32
660 if (_soundVersion >= SCI_VERSION_2) {
661 g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
662 } else {
663 #endif
664 if (_currentlyPlayingSample == pSnd)
665 _currentlyPlayingSample = NULL;
666 _pMixer->stopHandle(pSnd->hCurrentAud);
667 #ifdef ENABLE_SCI32
668 }
669 #endif
670 }
671
672 if (pSnd->pMidiParser) {
673 Common::StackLock lock(_mutex);
674 pSnd->pMidiParser->mainThreadBegin();
675 // We shouldn't call stop in case it's paused, otherwise we would send
676 // allNotesOff() again
677 if (previousStatus == kSoundPlaying)
678 pSnd->pMidiParser->stop();
679 pSnd->pMidiParser->mainThreadEnd();
680 remapChannels();
681 }
682
683 pSnd->fadeStep = 0; // end fading, if fading was in progress
684
685 // SSCI0 resumes the next available sound from the (priority ordered) list with a paused status.
686 if (_soundVersion <= SCI_VERSION_0_LATE && (pSnd = getFirstSlotWithStatus(kSoundPaused)))
687 soundResume(pSnd);
688 }
689
soundSetVolume(MusicEntry * pSnd,byte volume)690 void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
691 assert(volume <= MUSIC_VOLUME_MAX);
692 if (!pSnd->isSample && pSnd->pMidiParser) {
693 Common::StackLock lock(_mutex);
694 pSnd->pMidiParser->mainThreadBegin();
695 pSnd->pMidiParser->setVolume(volume);
696 pSnd->pMidiParser->mainThreadEnd();
697 }
698 }
699
700 // this is used to set volume of the sample, used for fading only!
soundSetSampleVolume(MusicEntry * pSnd,byte volume)701 void SciMusic::soundSetSampleVolume(MusicEntry *pSnd, byte volume) {
702 assert(volume <= MUSIC_VOLUME_MAX);
703 assert(pSnd->pStreamAud);
704 _pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127
705 }
706
soundSetPriority(MusicEntry * pSnd,byte prio)707 void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) {
708 Common::StackLock lock(_mutex);
709
710 pSnd->priority = prio;
711 pSnd->time = ++_timeCounter;
712 sortPlayList();
713 }
714
soundKill(MusicEntry * pSnd)715 void SciMusic::soundKill(MusicEntry *pSnd) {
716 pSnd->status = kSoundStopped;
717
718 _mutex.lock();
719 remapChannels();
720
721 if (pSnd->pMidiParser) {
722 pSnd->pMidiParser->mainThreadBegin();
723 pSnd->pMidiParser->unloadMusic();
724 pSnd->pMidiParser->mainThreadEnd();
725 delete pSnd->pMidiParser;
726 pSnd->pMidiParser = NULL;
727 }
728
729 _mutex.unlock();
730
731 if (pSnd->isSample) {
732 #ifdef ENABLE_SCI32
733 if (_soundVersion >= SCI_VERSION_2) {
734 g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
735 } else {
736 #endif
737 if (_currentlyPlayingSample == pSnd) {
738 // Forget about this sound, in case it was currently playing
739 _currentlyPlayingSample = NULL;
740 }
741 _pMixer->stopHandle(pSnd->hCurrentAud);
742 #ifdef ENABLE_SCI32
743 }
744 #endif
745 delete pSnd->pStreamAud;
746 pSnd->pStreamAud = NULL;
747 delete pSnd->pLoopStream;
748 pSnd->pLoopStream = 0;
749 pSnd->isSample = false;
750 }
751
752 _mutex.lock();
753 uint sz = _playList.size(), i;
754 // Remove sound from playlist
755 for (i = 0; i < sz; i++) {
756 if (_playList[i] == pSnd) {
757 delete _playList[i]->soundRes;
758 delete _playList[i];
759 _playList.remove_at(i);
760 break;
761 }
762 }
763 _mutex.unlock();
764 }
765
soundPause(MusicEntry * pSnd)766 void SciMusic::soundPause(MusicEntry *pSnd) {
767 // SCI seems not to be pausing samples played back by kDoSound at all
768 // It only stops looping samples (actually doesn't loop them again before they are unpaused)
769 // Examples: Space Quest 1 death by acid drops (pause is called even specifically for the sample, see bug #5097)
770 // Eco Quest 1 during the intro when going to the abort-menu
771 // In both cases sierra sci keeps playing
772 // Leisure Suit Larry 1 doll scene - it seems that pausing here actually just stops
773 // further looping from happening
774 // This is a somewhat bigger change, I'm leaving in the old code in here just in case
775 // I'm currently pausing looped sounds directly, non-looped sounds won't get paused
776 if ((pSnd->pStreamAud) && (!pSnd->pLoopStream))
777 return;
778 pSnd->pauseCounter++;
779 if (pSnd->status != kSoundPlaying)
780 return;
781 _needsResume = true;
782 pSnd->status = kSoundPaused;
783 if (pSnd->pStreamAud) {
784 _pMixer->pauseHandle(pSnd->hCurrentAud, true);
785 } else {
786 if (pSnd->pMidiParser) {
787 Common::StackLock lock(_mutex);
788 pSnd->pMidiParser->mainThreadBegin();
789 pSnd->pMidiParser->pause();
790 pSnd->pMidiParser->mainThreadEnd();
791 remapChannels();
792 }
793 }
794 }
795
soundResume(MusicEntry * pSnd)796 void SciMusic::soundResume(MusicEntry *pSnd) {
797 if (pSnd->pauseCounter > 0)
798 pSnd->pauseCounter--;
799 if (pSnd->pauseCounter != 0)
800 return;
801 if (pSnd->status != kSoundPaused || (_globalPause && !_needsResume))
802 return;
803 _needsResume = (_soundVersion > SCI_VERSION_0_LATE);
804 if (pSnd->pStreamAud) {
805 _pMixer->pauseHandle(pSnd->hCurrentAud, false);
806 pSnd->status = kSoundPlaying;
807 } else {
808 soundPlay(pSnd, true);
809 }
810 }
811
soundToggle(MusicEntry * pSnd,bool pause)812 void SciMusic::soundToggle(MusicEntry *pSnd, bool pause) {
813 #ifdef ENABLE_SCI32
814 if (_soundVersion >= SCI_VERSION_2_1_EARLY && pSnd->isSample) {
815 if (pause) {
816 g_sci->_audio32->pause(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
817 } else {
818 g_sci->_audio32->resume(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
819 }
820
821 return;
822 }
823 #endif
824
825 if (pause)
826 soundPause(pSnd);
827 else
828 soundResume(pSnd);
829 }
830
soundGetMasterVolume()831 uint16 SciMusic::soundGetMasterVolume() {
832 if (ConfMan.getBool("mute")) {
833 // When a game is muted, the master volume is set to zero so that
834 // mute applies to external MIDI devices, but this should not be
835 // communicated to the game as it will cause the UI to be drawn with
836 // the wrong (zero) volume for music
837 return (ConfMan.getInt("music_volume") + 1) * MUSIC_MASTERVOLUME_MAX / Audio::Mixer::kMaxMixerVolume;
838 }
839
840 return _masterVolume;
841 }
842
soundSetMasterVolume(uint16 vol)843 void SciMusic::soundSetMasterVolume(uint16 vol) {
844 _masterVolume = vol;
845
846 Common::StackLock lock(_mutex);
847
848 const MusicList::iterator end = _playList.end();
849 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
850 if ((*i)->pMidiParser)
851 (*i)->pMidiParser->setMasterVolume(vol);
852 }
853 }
854
sendMidiCommand(uint32 cmd)855 void SciMusic::sendMidiCommand(uint32 cmd) {
856 Common::StackLock lock(_mutex);
857 _pMidiDrv->send(cmd);
858 }
859
sendMidiCommand(MusicEntry * pSnd,uint32 cmd)860 void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
861 Common::StackLock lock(_mutex);
862 if (!pSnd->pMidiParser) {
863 // FPFP calls kDoSound SendMidi to mute and unmute its gameMusic2 sound
864 // object but some scenes set this to an audio sample. In Act 2, room
865 // 660 sets this to audio of restaurant customers talking. Walking up
866 // the hotel stairs from room 500 to 235 calls gameMusic2:mute and
867 // triggers this if gameMusic2 hasn't changed. Bug #10952
868 warning("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
869 return;
870 }
871
872 pSnd->pMidiParser->mainThreadBegin();
873 pSnd->pMidiParser->sendFromScriptToDriver(cmd);
874 pSnd->pMidiParser->mainThreadEnd();
875 }
876
printPlayList(Console * con)877 void SciMusic::printPlayList(Console *con) {
878 Common::StackLock lock(_mutex);
879
880 const char *musicStatus[] = { "Stopped", "Initialized", "Paused", "Playing" };
881
882 for (uint32 i = 0; i < _playList.size(); i++) {
883 MusicEntry *song = _playList[i];
884 con->debugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n",
885 i, PRINT_REG(song->soundObj),
886 g_sci->getEngineState()->_segMan->getObjectName(song->soundObj),
887 song->resourceId, musicStatus[song->status],
888 song->pMidiParser ? "MIDI" : "digital audio");
889 }
890 }
891
printSongInfo(reg_t obj,Console * con)892 void SciMusic::printSongInfo(reg_t obj, Console *con) {
893 Common::StackLock lock(_mutex);
894
895 const char *musicStatus[] = { "Stopped", "Initialized", "Paused", "Playing" };
896
897 const MusicList::iterator end = _playList.end();
898 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
899 MusicEntry *song = *i;
900 if (song->soundObj == obj) {
901 con->debugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]);
902 con->debugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop);
903 con->debugPrintf("signal: %d, priority: %d\n", song->signal, song->priority);
904 con->debugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume);
905
906 if (song->pMidiParser) {
907 con->debugPrintf("Type: MIDI\n");
908 if (song->soundRes) {
909 SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId());
910 con->debugPrintf("Channels: %d\n", track->channelCount);
911 }
912 } else if (song->pStreamAud || song->pLoopStream) {
913 con->debugPrintf("Type: digital audio (%s), sound active: %s\n",
914 song->pStreamAud ? "non looping" : "looping",
915 _pMixer->isSoundHandleActive(song->hCurrentAud) ? "yes" : "no");
916 if (song->soundRes) {
917 con->debugPrintf("Sound resource information:\n");
918 SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId());
919 if (track && track->digitalChannelNr != -1) {
920 con->debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
921 track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr);
922 }
923 }
924 }
925
926 return;
927 }
928 }
929
930 con->debugPrintf("Song object not found in playlist");
931 }
932
MusicEntry()933 MusicEntry::MusicEntry() {
934 soundObj = NULL_REG;
935
936 soundRes = 0;
937 resourceId = 0;
938
939 dataInc = 0;
940 ticker = 0;
941 signal = 0;
942 priority = 0;
943 loop = 0;
944 volume = MUSIC_VOLUME_DEFAULT;
945 hold = -1;
946 reverb = -1;
947
948 pauseCounter = 0;
949 sampleLoopCounter = 0;
950
951 fadeTo = 0;
952 fadeStep = 0;
953 fadeTicker = 0;
954 fadeTickerStep = 0;
955 fadeSetVolume = false;
956 fadeCompleted = false;
957 stopAfterFading = false;
958
959 status = kSoundStopped;
960
961 soundType = Audio::Mixer::kMusicSoundType;
962
963 pStreamAud = 0;
964 pLoopStream = 0;
965 pMidiParser = 0;
966 isSample = false;
967
968 for (int i = 0; i < 16; ++i) {
969 _usedChannels[i] = 0xFF;
970 _chan[i]._prio = 127;
971 _chan[i]._voices = 0;
972 _chan[i]._dontRemap = false;
973 _chan[i]._mute = false;
974 }
975 }
976
~MusicEntry()977 MusicEntry::~MusicEntry() {
978 }
979
onTimer()980 void MusicEntry::onTimer() {
981 if (!signal) {
982 if (!signalQueue.empty()) {
983 // no signal set, but signal in queue, set that one
984 signal = signalQueue[0];
985 signalQueue.remove_at(0);
986 }
987 }
988
989 if (status != kSoundPlaying || !loop)
990 return;
991
992 // Fade MIDI and digital sound effects
993 if (fadeStep)
994 doFade();
995
996 // Only process MIDI streams in this thread, not digital sound effects
997 if (pMidiParser) {
998 pMidiParser->onTimer();
999 ticker = (uint16)pMidiParser->getTick();
1000 }
1001 }
1002
doFade()1003 void MusicEntry::doFade() {
1004 if (fadeTicker)
1005 fadeTicker--;
1006 else {
1007 fadeTicker = fadeTickerStep;
1008 volume += fadeStep;
1009 if (((fadeStep > 0) && (volume >= fadeTo)) || ((fadeStep < 0) && (volume <= fadeTo))) {
1010 volume = fadeTo;
1011 fadeStep = 0;
1012 fadeCompleted = true;
1013 }
1014
1015 // Only process MIDI streams in this thread, not digital sound effects
1016 if (pMidiParser) {
1017 pMidiParser->setVolume(volume);
1018 }
1019
1020 fadeSetVolume = true; // set flag so that SoundCommandParser::cmdUpdateCues will set the volume of the stream
1021 }
1022 }
1023
setSignal(int newSignal)1024 void MusicEntry::setSignal(int newSignal) {
1025 // For SCI0, we cache the signals to set, as some songs might
1026 // update their signal faster than kGetEvent is called (which is where
1027 // we manually invoke kDoSoundUpdateCues for SCI0 games). SCI01 and
1028 // newer handle signalling inside kDoSoundUpdateCues. Refer to bug #5218
1029 if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) {
1030 if (!signal) {
1031 signal = newSignal;
1032 } else {
1033 // signal already set and waiting for getting to scripts, queue new one
1034 signalQueue.push_back(newSignal);
1035 }
1036 } else {
1037 // Set the signal directly for newer games, otherwise the sound
1038 // object might be deleted already later on (refer to bug #5243)
1039 signal = newSignal;
1040 }
1041 }
1042
1043
swap(int i,int j)1044 void ChannelRemapping::swap(int i, int j) {
1045 DeviceChannelUsage t1;
1046 int t2;
1047 bool t3;
1048
1049 t1 = _map[i]; _map[i] = _map[j]; _map[j] = t1;
1050 t2 = _prio[i]; _prio[i] = _prio[j]; _prio[j] = t2;
1051 t2 = _voices[i]; _voices[i] = _voices[j]; _voices[j] = t2;
1052 t3 = _dontRemap[i]; _dontRemap[i] = _dontRemap[j]; _dontRemap[j] = t3;
1053 }
1054
evict(int i)1055 void ChannelRemapping::evict(int i) {
1056 _freeVoices += _voices[i];
1057
1058 _map[i]._song = 0;
1059 _map[i]._channel = -1;
1060 _prio[i] = 0;
1061 _voices[i] = 0;
1062 _dontRemap[i] = false;
1063 }
1064
clear()1065 void ChannelRemapping::clear() {
1066 for (int i = 0; i < 16; ++i) {
1067 _map[i]._song = 0;
1068 _map[i]._channel = -1;
1069 _prio[i] = 0;
1070 _voices[i] = 0;
1071 _dontRemap[i] = false;
1072 }
1073 }
1074
operator =(ChannelRemapping & other)1075 ChannelRemapping& ChannelRemapping::operator=(ChannelRemapping& other) {
1076 for (int i = 0; i < 16; ++i) {
1077 _map[i] = other._map[i];
1078 _prio[i] = other._prio[i];
1079 _voices[i] = other._voices[i];
1080 _dontRemap[i] = other._dontRemap[i];
1081 }
1082 _freeVoices = other._freeVoices;
1083
1084 return *this;
1085 }
1086
lowestPrio() const1087 int ChannelRemapping::lowestPrio() const {
1088 int max = 0;
1089 int channel = -1;
1090 for (int i = 0; i < 16; ++i) {
1091 if (_prio[i] > max) {
1092 max = _prio[i];
1093 channel = i;
1094 }
1095 }
1096 return channel;
1097 }
1098
1099
remapChannels(bool mainThread)1100 void SciMusic::remapChannels(bool mainThread) {
1101 if (_soundVersion <= SCI_VERSION_0_LATE)
1102 return;
1103
1104 // NB: This function should only be called with _mutex locked
1105 // Make sure to set the mainThread argument correctly.
1106
1107
1108 ChannelRemapping *map = determineChannelMap();
1109
1110 DeviceChannelUsage currentMap[16];
1111
1112 #ifdef DEBUG_REMAP
1113 debug("Remap results:");
1114 #endif
1115
1116 // Save current map, and then start from an empty map
1117 for (int i = 0; i < 16; ++i) {
1118 currentMap[i] = _channelMap[i];
1119 _channelMap[i]._song = 0;
1120 _channelMap[i]._channel = -1;
1121 }
1122
1123 // Inform MidiParsers of any unmapped channels
1124 const MusicList::iterator end = _playList.end();
1125 int songIndex = -1;
1126 for (MusicList::iterator i = _playList.begin(); i != end; ++i) {
1127 MusicEntry *song = *i;
1128 songIndex++;
1129
1130 if (!song || !song->pMidiParser)
1131 continue;
1132
1133 bool channelMapped[16];
1134 #ifdef DEBUG_REMAP
1135 bool channelUsed[16];
1136 #endif
1137 for (int j = 0; j < 16; ++j) {
1138 channelMapped[j] = false;
1139 #ifdef DEBUG_REMAP
1140 channelUsed[j] = false;
1141 #endif
1142 }
1143
1144 for (int j = 0; j < 16; ++j) {
1145 if (map->_map[j]._song == song) {
1146 int channel = map->_map[j]._channel;
1147 assert(channel >= 0 && channel <= 0x0F);
1148 channelMapped[channel] = true;
1149 }
1150 #ifdef DEBUG_REMAP
1151 if (song->_usedChannels[j] <= 0x0F)
1152 channelUsed[song->_usedChannels[j]] = true;
1153 #endif
1154 }
1155
1156 for (int j = 0; j < 16; ++j) {
1157 if (!channelMapped[j]) {
1158 if (mainThread) song->pMidiParser->mainThreadBegin();
1159 song->pMidiParser->remapChannel(j, -1);
1160 if (mainThread) song->pMidiParser->mainThreadEnd();
1161 #ifdef DEBUG_REMAP
1162 if (channelUsed[j])
1163 debug(" Unmapping song %d, channel %d", songIndex, j);
1164 #endif
1165 }
1166 }
1167 }
1168
1169 // Now reshuffle the channels on the device.
1170
1171 // First, set up any dontRemap channels
1172 for (int i = 0; i < 16; ++i) {
1173
1174 if (!map->_map[i]._song || !map->_map[i]._song->pMidiParser || !map->_dontRemap[i])
1175 continue;
1176
1177 songIndex = -1;
1178 for (MusicList::iterator iter = _playList.begin(); iter != end; ++iter) {
1179 songIndex++;
1180 if (map->_map[i]._song == *iter)
1181 break;
1182 }
1183
1184 _channelMap[i] = map->_map[i];
1185 map->_map[i]._song = 0; // mark as done
1186
1187 // If this channel was not yet mapped to the device, reset it
1188 if (currentMap[i] != _channelMap[i]) {
1189 #ifdef DEBUG_REMAP
1190 debug(" Mapping (dontRemap) song %d, channel %d to device channel %d", songIndex, _channelMap[i]._channel, i);
1191 #endif
1192 if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadBegin();
1193 _channelMap[i]._song->pMidiParser->remapChannel(_channelMap[i]._channel, i);
1194 if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadEnd();
1195 }
1196
1197 }
1198
1199 // Next, we look for channels which were already playing.
1200 // We keep those on the same device channel as before.
1201 for (int i = 0; i < 16; ++i) {
1202
1203 if (!map->_map[i]._song)
1204 continue;
1205
1206 songIndex = -1;
1207 for (MusicList::iterator iter = _playList.begin(); iter != end; ++iter) {
1208 songIndex++;
1209 if (map->_map[i]._song == *iter)
1210 break;
1211 }
1212
1213
1214 for (int j = 0; j < 16; ++j) {
1215 if (map->_map[i] == currentMap[j]) {
1216 // found it
1217 _channelMap[j] = map->_map[i];
1218 map->_map[i]._song = 0; // mark as done
1219 #ifdef DEBUG_REMAP
1220 debug(" Keeping song %d, channel %d on device channel %d", songIndex, _channelMap[j]._channel, j);
1221 #endif
1222 break;
1223 }
1224 }
1225 }
1226
1227 // Then, remap the rest.
1228 for (int i = 0; i < 16; ++i) {
1229
1230 if (!map->_map[i]._song || !map->_map[i]._song->pMidiParser)
1231 continue;
1232
1233 songIndex = -1;
1234 for (MusicList::iterator iter = _playList.begin(); iter != end; ++iter) {
1235 songIndex++;
1236 if (map->_map[i]._song == *iter)
1237 break;
1238 }
1239
1240 for (int j = _driverLastChannel; j >= _driverFirstChannel; --j) {
1241 if (_channelMap[j]._song == 0) {
1242 _channelMap[j] = map->_map[i];
1243 map->_map[i]._song = 0;
1244 #ifdef DEBUG_REMAP
1245 debug(" Mapping song %d, channel %d to device channel %d", songIndex, _channelMap[j]._channel, j);
1246 #endif
1247 if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadBegin();
1248 _channelMap[j]._song->pMidiParser->remapChannel(_channelMap[j]._channel, j);
1249 if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadEnd();
1250 break;
1251 }
1252 }
1253
1254 }
1255
1256 // And finally, stop any empty channels
1257 for (int i = _driverLastChannel; i >= _driverFirstChannel; --i) {
1258 if (!_channelMap[i]._song && currentMap[i]._song)
1259 resetDeviceChannel(i, mainThread);
1260 }
1261
1262 delete map;
1263 }
1264
1265
determineChannelMap()1266 ChannelRemapping *SciMusic::determineChannelMap() {
1267 #ifdef DEBUG_REMAP
1268 debug("Remap: avail chans: %d-%d", _driverFirstChannel, _driverLastChannel);
1269 #endif
1270
1271 ChannelRemapping *map = new ChannelRemapping;
1272 ChannelRemapping backupMap;
1273 map->clear();
1274 map->_freeVoices = _pMidiDrv->getPolyphony();
1275
1276 if (_playList.empty())
1277 return map;
1278
1279 // TODO: set reverb, either from first song, or from global???
1280
1281 MusicList::iterator songIter;
1282 int songIndex = -1;
1283 for (songIter = _playList.begin(); songIter != _playList.end(); ++songIter) {
1284 songIndex++;
1285 MusicEntry *song = *songIter;
1286 if (song->status != kSoundPlaying)
1287 continue;
1288
1289 // If song is digital, skip.
1290 // CHECKME: Is this condition correct?
1291 if (!song->pMidiParser) {
1292 #ifdef DEBUG_REMAP
1293 debug(" Song %d (%p), digital?", songIndex, (void*)song);
1294 #endif
1295 continue;
1296 }
1297
1298
1299 #ifdef DEBUG_REMAP
1300 const char* name = g_sci->getEngineState()->_segMan->getObjectName(song->soundObj);
1301 debug(" Song %d (%p) [%s], prio %d%s", songIndex, (void*)song, name, song->priority, song->playBed ? ", bed" : "");
1302 #endif
1303
1304 // Store backup. If we fail to map this song, we will revert to this.
1305 backupMap = *map;
1306
1307 bool songMapped = true;
1308
1309 for (int i = 0; i < 16; ++i) {
1310 int c = song->_usedChannels[i];
1311 if (c == 0xFF || c == 0xFE || c == 0x0F)
1312 continue;
1313 const MusicEntryChannel &channel = song->_chan[c];
1314 if (channel._dontMap) {
1315 #ifdef DEBUG_REMAP
1316 debug(" Channel %d dontMap, skipping", c);
1317 #endif
1318 continue;
1319 }
1320 if (channel._mute) {
1321 #ifdef DEBUG_REMAP
1322 debug(" Channel %d muted, skipping", c);
1323 #endif
1324 continue;
1325 }
1326
1327 bool dontRemap = channel._dontRemap || song->playBed;
1328
1329 #ifdef DEBUG_REMAP
1330 debug(" Channel %d: prio %d, %d voice%s%s", c, channel._prio, channel._voices, channel._voices == 1 ? "" : "s", dontRemap ? ", dontRemap" : "" );
1331 #endif
1332
1333 DeviceChannelUsage dc = { song, c };
1334
1335 // our target
1336 int devChannel = -1;
1337
1338 if (dontRemap && map->_map[c]._song == 0) {
1339 // unremappable channel, with channel still free
1340 devChannel = c;
1341 }
1342
1343 // try to find a free channel
1344 if (devChannel == -1) {
1345 for (int j = 0; j < 16; ++j) {
1346 if (map->_map[j] == dc) {
1347 // already mapped?! (Can this happen?)
1348 devChannel = j;
1349 break;
1350 }
1351 if (map->_map[j]._song)
1352 continue;
1353
1354 if (j >= _driverFirstChannel && j <= _driverLastChannel)
1355 devChannel = j;
1356 }
1357 }
1358
1359 int prio = channel._prio;
1360 if (prio > 0) {
1361 // prio > 0 means non-essential
1362 prio = (16 - prio) + 16*songIndex;
1363 }
1364
1365 if (devChannel == -1 && prio > 0) {
1366 // no empty channel, but this isn't an essential channel,
1367 // so we just skip it.
1368 #ifdef DEBUG_REMAP
1369 debug(" skipping non-essential");
1370 #endif
1371 continue;
1372 }
1373
1374 // try to empty a previous channel if this is an essential channel
1375 if (devChannel == -1) {
1376 devChannel = map->lowestPrio();
1377 if (devChannel != -1)
1378 map->evict(devChannel);
1379 }
1380
1381 if (devChannel == -1) {
1382 // failed to map this song.
1383 #ifdef DEBUG_REMAP
1384 debug(" no free (or lower priority) channel found");
1385 #endif
1386 songMapped = false;
1387 break;
1388 }
1389
1390 if (map->_map[devChannel] == dc) {
1391 // already mapped?! (Can this happen?)
1392 continue;
1393 }
1394
1395 int neededVoices = channel._voices;
1396 // do we have enough free voices?
1397 if (map->_freeVoices < neededVoices) {
1398 // We only care for essential channels.
1399 // Note: In early SCI1 interpreters, a song started by 'playBed'
1400 // would not be skipped even if some channels couldn't be
1401 // mapped due to voice limits. So, we treat all channels as
1402 // non-essential here for playBed songs.
1403 if (prio > 0 || (song->playBed && _soundVersion <= SCI_VERSION_1_EARLY)) {
1404 #ifdef DEBUG_REMAP
1405 debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices);
1406 #endif
1407 continue;
1408 }
1409 do {
1410 int j = map->lowestPrio();
1411 if (j == -1) {
1412 #ifdef DEBUG_REMAP
1413 debug(" not enough voices; need %d, have %d", neededVoices, map->_freeVoices);
1414 #endif
1415 // failed to free enough voices.
1416 songMapped = false;
1417 break;
1418 }
1419 #ifdef DEBUG_REMAP
1420 debug(" creating room for voices; evict %d", j);
1421 #endif
1422 map->evict(j);
1423 } while (map->_freeVoices < neededVoices);
1424
1425 if (!songMapped) {
1426 // failed to map this song.
1427 break;
1428 }
1429 }
1430
1431 // We have a channel and enough free voices now.
1432 #ifdef DEBUG_REMAP
1433 debug(" trying to map to %d", devChannel);
1434 #endif
1435
1436 map->_map[devChannel] = dc;
1437 map->_voices[devChannel] = neededVoices;
1438 map->_prio[devChannel] = prio;
1439 map->_dontRemap[devChannel] = dontRemap;
1440 map->_freeVoices -= neededVoices;
1441
1442 if (!dontRemap || devChannel == c) {
1443 // If this channel fits here, we're done.
1444 #ifdef DEBUG_REMAP
1445 debug(" OK");
1446 #endif
1447 continue;
1448 }
1449
1450 // If this channel can't be remapped, we need to move it or fail.
1451
1452 if (!map->_dontRemap[c]) {
1453 // Target channel can be remapped, so just swap
1454 map->swap(devChannel, c);
1455 continue;
1456 }
1457 #ifdef DEBUG_REMAP
1458 debug(" but %d is already dontRemap", c);
1459 #endif
1460
1461 if (prio > 0) {
1462 // Channel collision, but this channel is non-essential,
1463 // so drop it.
1464 // TODO: Maybe we should have checked this before making room?
1465 map->evict(devChannel);
1466 continue;
1467 }
1468
1469 if (map->_prio[c] > 0) {
1470 // Channel collision, but the other channel is non-essential,
1471 // so we take its place.
1472 map->evict(c);
1473 map->swap(devChannel, c);
1474 continue;
1475 }
1476
1477 // Otherwise, we have two essential channels claiming the same
1478 // device channel.
1479 songMapped = false;
1480 break;
1481 }
1482
1483 if (!songMapped) {
1484 // We failed to map this song, so unmap all its channels.
1485 #ifdef DEBUG_REMAP
1486 debug(" Failed song");
1487 #endif
1488 *map = backupMap;
1489 }
1490 }
1491
1492 return map;
1493 }
1494
resetDeviceChannel(int devChannel,bool mainThread)1495 void SciMusic::resetDeviceChannel(int devChannel, bool mainThread) {
1496 assert(devChannel >= 0 && devChannel <= 0x0F);
1497
1498 if (mainThread) {
1499 putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off
1500 putMidiCommandInQueue(0x007BB0 | devChannel); // notes off
1501 putMidiCommandInQueue(0x004BB0 | devChannel); // release voices
1502 } else {
1503 _pMidiDrv->send(0x0040B0 | devChannel); // sustain off
1504 _pMidiDrv->send(0x007BB0 | devChannel); // notes off
1505 _pMidiDrv->send(0x004BB0 | devChannel); // release voices
1506 }
1507 }
1508
1509
1510
1511 } // End of namespace Sci
1512