diff options
Diffstat (limited to 'engines/sci/sound')
-rw-r--r-- | engines/sci/sound/audio.cpp | 17 | ||||
-rw-r--r-- | engines/sci/sound/drivers/adlib.cpp | 53 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 19 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 112 | ||||
-rw-r--r-- | engines/sci/sound/music.h | 14 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.cpp | 46 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.h | 2 |
7 files changed, 178 insertions, 85 deletions
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 8e35d6b055..fb9a3f17b9 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -391,18 +391,13 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('F','O','R','M')) { // AIFF detected Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); + Audio::RewindableAudioStream *rewindStream = Audio::makeAIFFStream(waveStream, DisposeAfterUse::YES); + audioSeekStream = dynamic_cast<Audio::SeekableAudioStream *>(rewindStream); - // Calculate samplelen from AIFF header - int waveSize = 0, waveRate = 0; - byte waveFlags = 0; - bool ret = Audio::loadAIFFFromStream(*waveStream, waveSize, waveRate, waveFlags); - if (!ret) - error("Failed to load AIFF from stream"); - - *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; - - waveStream->seek(0, SEEK_SET); - audioStream = Audio::makeAIFFStream(waveStream, DisposeAfterUse::YES); + if (!audioSeekStream) { + warning("AIFF file is not seekable"); + delete rewindStream; + } } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index fcfda2f532..4f557be95e 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -27,7 +27,7 @@ #include "common/textconsole.h" #include "audio/fmopl.h" -#include "audio/softsynth/emumidi.h" +#include "audio/mididrv.h" #include "sci/resource.h" #include "sci/sound/drivers/mididriver.h" @@ -43,29 +43,30 @@ namespace Sci { // FIXME: We don't seem to be sending the polyphony init data, so disable this for now #define ADLIB_DISABLE_VOICE_MAPPING -class MidiDriver_AdLib : public MidiDriver_Emulated { +class MidiDriver_AdLib : public MidiDriver { public: enum { kVoices = 9, kRhythmKeys = 62 }; - MidiDriver_AdLib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0) { } + MidiDriver_AdLib(Audio::Mixer *mixer) :_playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0), _isOpen(false) { } virtual ~MidiDriver_AdLib() { } // MidiDriver + int open() { return -1; } // Dummy implementation (use openAdLib) int openAdLib(bool isSCI0); void close(); void send(uint32 b); MidiChannel *allocateChannel() { return NULL; } MidiChannel *getPercussionChannel() { return NULL; } + bool isOpen() const { return _isOpen; } + uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; } - // AudioStream - bool isStereo() const { return _stereo; } - int getRate() const { return _mixer->getOutputRate(); } + // MidiDriver + void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc); - // MidiDriver_Emulated - void generateSamples(int16 *buf, int len); + void onTimer(); void setVolume(byte volume); void playSwitch(bool play); @@ -133,6 +134,7 @@ private: bool _stereo; bool _isSCI0; OPL::OPL *_opl; + bool _isOpen; bool _playSwitch; int _masterVolume; Channel _channels[MIDI_CHANNELS]; @@ -140,6 +142,9 @@ private: byte *_rhythmKeyMap; Common::Array<AdLibPatch> _patches; + Common::TimerManager::TimerProc _adlibTimerProc; + void *_adlibTimerParam; + void loadInstrument(const byte *ins); void voiceOn(int voice, int note, int velocity); void voiceOff(int voice); @@ -215,14 +220,12 @@ static const int ym3812_note[13] = { }; int MidiDriver_AdLib::openAdLib(bool isSCI0) { - int rate = _mixer->getOutputRate(); - _stereo = STEREO; debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1")); _isSCI0 = isSCI0; - _opl = OPL::Config::create(isStereo() ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2); + _opl = OPL::Config::create(_stereo ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2); // Try falling back to mono, thus plain OPL2 emualtor, when no Dual OPL2 is available. if (!_opl && _stereo) { @@ -233,22 +236,24 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) { if (!_opl) return -1; - _opl->init(rate); + if (!_opl->init()) { + delete _opl; + _opl = nullptr; + return -1; + } setRegister(0xBD, 0); setRegister(0x08, 0); setRegister(0x01, 0x20); - MidiDriver_Emulated::open(); + _isOpen = true; - _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO); + _opl->start(new Common::Functor0Mem<void, MidiDriver_AdLib>(this, &MidiDriver_AdLib::onTimer)); return 0; } void MidiDriver_AdLib::close() { - _mixer->stopHandle(_mixerSoundHandle); - delete _opl; delete[] _rhythmKeyMap; } @@ -325,10 +330,14 @@ void MidiDriver_AdLib::send(uint32 b) { } } -void MidiDriver_AdLib::generateSamples(int16 *data, int len) { - if (isStereo()) - len <<= 1; - _opl->readBuffer(data, len); +void MidiDriver_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) { + _adlibTimerProc = timerProc; + _adlibTimerParam = timerParam; +} + +void MidiDriver_AdLib::onTimer() { + if (_adlibTimerProc) + (*_adlibTimerProc)(_adlibTimerParam); // Increase the age of the notes for (int i = 0; i < kVoices; i++) { @@ -684,7 +693,7 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe if (!_playSwitch) velocity = 0; - if (isStereo()) { + if (_stereo) { int velLeft = velocity; int velRight = velocity; @@ -734,7 +743,7 @@ void MidiDriver_AdLib::setRegister(int reg, int value, int channels) { _opl->write(0x221, value); } - if (isStereo()) { + if (_stereo) { if (channels & kRightChannel) { _opl->write(0x222, reg); _opl->write(0x223, value); diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index c0b4f3122e..9f0d8d150f 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -360,6 +360,13 @@ void MidiParser_SCI::sendInitCommands() { sendToDriver(0xB0 | i, 0x4B, voiceCount); } } + } else { + for (int i = 0; i < _track->channelCount; ++i) { + byte voiceCount = _track->channels[i].poly; + byte num = _track->channels[i].number; + // TODO: Should we skip the control channel? + sendToDriver(0xB0 | num, 0x4B, voiceCount); + } } } @@ -480,19 +487,25 @@ void MidiParser_SCI::trackState(uint32 b) { s._sustain = (op2 != 0); break; case 0x4B: // voices + if (s._voices != op2) { + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + debugC(2, kDebugLevelSound, "Dynamic voice change (%d to %d)", s._voices, op2); + _music->needsRemap(); + } s._voices = op2; _pSnd->_chan[channel]._voices = op2; // Also sync our MusicEntry break; case 0x4E: // mute // This is channel mute only for sci1. // (It's velocity control for sci0, but we don't need state in sci0) - if (_soundVersion >= SCI_VERSION_1_EARLY) { + if (_soundVersion > SCI_VERSION_1_EARLY) { // FIXME: mute is a level, not a bool, in some SCI versions bool m = op2; if (_pSnd->_chan[channel]._mute != m) { _pSnd->_chan[channel]._mute = m; - // TODO: If muting/unmuting a channel, remap channels. - warning("Mute change without immediate remapping (mainThread = %d)", _mainThreadCalled); + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + _music->needsRemap(); + debugC(2, kDebugLevelSound, "Dynamic mute change (arg = %d, mainThread = %d)", m, _mainThreadCalled); } } break; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 7a6eaf62b4..dca73c3f51 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -144,6 +144,8 @@ void SciMusic::init() { _globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0 _currentlyPlayingSample = NULL; + _timeCounter = 0; + _needsRemap = false; } void SciMusic::miditimerCallback(void *p) { @@ -158,6 +160,11 @@ void SciMusic::onTimer() { // sending out queued commands that were "sent" via main thread sendMidiCommandsFromQueue(); + // remap channels, if requested + if (_needsRemap) + remapChannels(false); + _needsRemap = false; + for (MusicList::iterator i = _playList.begin(); i != end; ++i) (*i)->onTimer(); } @@ -285,8 +292,10 @@ byte SciMusic::getCurrentReverb() { return _pMidiDrv->getReverb(); } +// A larger priority value has higher priority. For equal priority values, +// songs that have been added later have higher priority. static bool musicEntryCompare(const MusicEntry *l, const MusicEntry *r) { - return (l->priority > r->priority); + return (l->priority > r->priority) || (l->priority == r->priority && l->time > r->time); } void SciMusic::sortPlayList() { @@ -317,6 +326,8 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { track = digital; } + pSnd->time = ++_timeCounter; + if (track) { // Play digital sample if (track->digitalChannelNr != -1) { @@ -334,6 +345,8 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->pLoopStream = 0; pSnd->soundType = Audio::Mixer::kSFXSoundType; pSnd->hCurrentAud = Audio::SoundHandle(); + pSnd->playBed = false; + pSnd->overridePriority = false; } else { // play MIDI track Common::StackLock lock(_mutex); @@ -380,6 +393,8 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { int16 prevHold = pSnd->hold; pSnd->loop = 0; pSnd->hold = -1; + pSnd->playBed = false; + pSnd->overridePriority = false; pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); pSnd->reverb = pSnd->pMidiParser->getSongReverb(); @@ -395,6 +410,23 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { void SciMusic::soundPlay(MusicEntry *pSnd) { _mutex.lock(); + if (_soundVersion <= SCI_VERSION_1_EARLY && pSnd->playBed) { + // If pSnd->playBed, and version <= SCI1_EARLY, then kill + // existing sounds with playBed enabled. + + uint playListCount = _playList.size(); + for (uint i = 0; i < playListCount; i++) { + if (_playList[i] != pSnd && _playList[i]->playBed) { + debugC(2, kDebugLevelSound, "Automatically stopping old playBed song from soundPlay"); + MusicEntry *old = _playList[i]; + _mutex.unlock(); + soundStop(old); + _mutex.lock(); + break; + } + } + } + uint playListCount = _playList.size(); uint playListNo = playListCount; MusicEntry *alreadyPlaying = NULL; @@ -408,9 +440,11 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { } if (playListNo == playListCount) { // not found _playList.push_back(pSnd); - sortPlayList(); } + pSnd->time = ++_timeCounter; + sortPlayList(); + _mutex.unlock(); // unlock to perform mixer-related calls if (pSnd->pMidiParser) { @@ -554,6 +588,7 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) { Common::StackLock lock(_mutex); pSnd->priority = prio; + pSnd->time = ++_timeCounter; sortPlayList(); } @@ -905,12 +940,12 @@ int ChannelRemapping::lowestPrio() const { } -void SciMusic::remapChannels() { +void SciMusic::remapChannels(bool mainThread) { if (_soundVersion <= SCI_VERSION_0_LATE) return; - // NB: This function should only be called from the main thread, - // with _mutex locked + // NB: This function should only be called with _mutex locked + // Make sure to set the mainThread argument correctly. ChannelRemapping *map = determineChannelMap(); @@ -963,9 +998,9 @@ void SciMusic::remapChannels() { for (int j = 0; j < 16; ++j) { if (!channelMapped[j]) { - song->pMidiParser->mainThreadBegin(); + if (mainThread) song->pMidiParser->mainThreadBegin(); song->pMidiParser->remapChannel(j, -1); - song->pMidiParser->mainThreadEnd(); + if (mainThread) song->pMidiParser->mainThreadEnd(); #ifdef DEBUG_REMAP if (channelUsed[j]) debug(" Unmapping song %d, channel %d", songIndex, j); @@ -997,9 +1032,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping (dontRemap) song %d, channel %d to device channel %d", songIndex, _channelMap[i]._channel, i); #endif - _channelMap[i]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadBegin(); _channelMap[i]._song->pMidiParser->remapChannel(_channelMap[i]._channel, i); - _channelMap[i]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadEnd(); } } @@ -1052,9 +1087,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping song %d, channel %d to device channel %d", songIndex, _channelMap[j]._channel, j); #endif - _channelMap[j]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadBegin(); _channelMap[j]._song->pMidiParser->remapChannel(_channelMap[j]._channel, j); - _channelMap[j]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadEnd(); break; } } @@ -1062,9 +1097,9 @@ void SciMusic::remapChannels() { } // And finally, stop any empty channels - for (int i = _driverFirstChannel; i <= _driverLastChannel; ++i) { - if (!_channelMap[i]._song) - resetDeviceChannel(i); + for (int i = _driverLastChannel; i >= _driverFirstChannel; --i) { + if (!_channelMap[i]._song && currentMap[i]._song) + resetDeviceChannel(i, mainThread); } delete map; @@ -1105,7 +1140,8 @@ ChannelRemapping *SciMusic::determineChannelMap() { #ifdef DEBUG_REMAP - debug(" Song %d (%p), prio %d", songIndex, (void*)song, song->priority); + const char* name = g_sci->getEngineState()->_segMan->getObjectName(song->soundObj); + debug(" Song %d (%p) [%s], prio %d%s", songIndex, (void*)song, name, song->priority, song->playBed ? ", bed" : ""); #endif // Store backup. If we fail to map this song, we will revert to this. @@ -1118,13 +1154,23 @@ ChannelRemapping *SciMusic::determineChannelMap() { if (c == 0xFF || c == 0xFE || c == 0x0F) continue; const MusicEntryChannel &channel = song->_chan[c]; - if (channel._dontMap) + if (channel._dontMap) { +#ifdef DEBUG_REMAP + debug(" Channel %d dontMap, skipping", c); +#endif continue; - if (channel._mute) + } + if (channel._mute) { +#ifdef DEBUG_REMAP + debug(" Channel %d muted, skipping", c); +#endif continue; + } + + bool dontRemap = channel._dontRemap || song->playBed; #ifdef DEBUG_REMAP - debug(" Channel %d: prio %d, %d voice%s%s", c, channel._prio, channel._voices, channel._voices == 1 ? "" : "s", channel._dontRemap ? ", dontRemap" : "" ); + debug(" Channel %d: prio %d, %d voice%s%s", c, channel._prio, channel._voices, channel._voices == 1 ? "" : "s", dontRemap ? ", dontRemap" : "" ); #endif DeviceChannelUsage dc = { song, c }; @@ -1132,7 +1178,7 @@ ChannelRemapping *SciMusic::determineChannelMap() { // our target int devChannel = -1; - if (channel._dontRemap && map->_map[c]._song == 0) { + if (dontRemap && map->_map[c]._song == 0) { // unremappable channel, with channel still free devChannel = c; } @@ -1192,8 +1238,12 @@ ChannelRemapping *SciMusic::determineChannelMap() { int neededVoices = channel._voices; // do we have enough free voices? if (map->_freeVoices < neededVoices) { - // We only care for essential channels - if (prio > 0) { + // We only care for essential channels. + // Note: In early SCI1 interpreters, a song started by 'playBed' + // would not be skipped even if some channels couldn't be + // mapped due to voice limits. So, we treat all channels as + // non-essential here for playBed songs. + if (prio > 0 || (song->playBed && _soundVersion <= SCI_VERSION_1_EARLY)) { #ifdef DEBUG_REMAP debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices); #endif @@ -1229,10 +1279,10 @@ ChannelRemapping *SciMusic::determineChannelMap() { map->_map[devChannel] = dc; map->_voices[devChannel] = neededVoices; map->_prio[devChannel] = prio; - map->_dontRemap[devChannel] = channel._dontRemap; + map->_dontRemap[devChannel] = dontRemap; map->_freeVoices -= neededVoices; - if (!channel._dontRemap || devChannel == c) { + if (!dontRemap || devChannel == c) { // If this channel fits here, we're done. #ifdef DEBUG_REMAP debug(" OK"); @@ -1285,14 +1335,18 @@ ChannelRemapping *SciMusic::determineChannelMap() { return map; } -void SciMusic::resetDeviceChannel(int devChannel) { - // NB: This function should only be called from the main thread - +void SciMusic::resetDeviceChannel(int devChannel, bool mainThread) { assert(devChannel >= 0 && devChannel <= 0x0F); - putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off - putMidiCommandInQueue(0x007BB0 | devChannel); // notes off - putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + if (mainThread) { + putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off + putMidiCommandInQueue(0x007BB0 | devChannel); // notes off + putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + } else { + _pMidiDrv->send(0x0040B0 | devChannel); // sustain off + _pMidiDrv->send(0x007BB0 | devChannel); // notes off + _pMidiDrv->send(0x004BB0 | devChannel); // release voices + } } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 4e44074630..a610f32d89 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -75,6 +75,8 @@ public: SoundResource *soundRes; uint16 resourceId; + int time; // "tim"estamp to indicate in which order songs have been added + bool isQueued; // for SCI0 only! uint16 dataInc; @@ -85,6 +87,8 @@ public: int16 volume; int16 hold; int8 reverb; + bool playBed; + bool overridePriority; // Use soundObj's priority instead of resource's int16 pauseCounter; uint sampleLoopCounter; @@ -224,6 +228,8 @@ public: byte getCurrentReverb(); + void needsRemap() { _needsRemap = true; } + virtual void saveLoadWithSerializer(Common::Serializer &ser); // Mutex for music code. Used to guard access to the song playlist, to the @@ -245,9 +251,9 @@ protected: bool _useDigitalSFX; // remapping: - void remapChannels(); + void remapChannels(bool mainThread = true); ChannelRemapping *determineChannelMap(); - void resetDeviceChannel(int devChannel); + void resetDeviceChannel(int devChannel, bool mainThread); private: MusicList _playList; @@ -256,6 +262,7 @@ private: MusicEntry *_usedChannel[16]; int8 _channelRemap[16]; int8 _globalReverb; + bool _needsRemap; DeviceChannelUsage _channelMap[16]; @@ -266,6 +273,9 @@ private: int _driverLastChannel; MusicEntry *_currentlyPlayingSample; + + int _timeCounter; // Used to keep track of the order in which MusicEntries + // are added, for priority purposes. }; } // End of namespace Sci diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 73e0a23a6a..ee5903fda2 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -142,11 +142,14 @@ void SoundCommandParser::processInitSound(reg_t obj) { reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x", PRINT_REG(argv[0])); - processPlaySound(argv[0]); + bool playBed = false; + if (argc >= 2 && !argv[1].isNull()) + playBed = true; + processPlaySound(argv[0], playBed); return acc; } -void SoundCommandParser::processPlaySound(reg_t obj) { +void SoundCommandParser::processPlaySound(reg_t obj, bool playBed) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj)); @@ -181,15 +184,26 @@ void SoundCommandParser::processPlaySound(reg_t obj) { } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); - musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + + // Get song priority from either obj or soundRes + byte resourcePriority = 0xFF; + if (musicSlot->soundRes) + resourcePriority = musicSlot->soundRes->getSoundPriority(); + if (!musicSlot->overridePriority && resourcePriority != 0xFF) { + musicSlot->priority = resourcePriority; + } else { + musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + } + // Reset hold when starting a new song. kDoSoundSetHold is always called after // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. musicSlot->hold = -1; + musicSlot->playBed = playBed; if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); - debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), - resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume); + debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d, bed %d", PRINT_REG(obj), + resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume, playBed ? 1 : 0); _music->soundPlay(musicSlot); @@ -538,7 +552,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); - writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); + writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker % 60 / 2); } } @@ -673,23 +687,19 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) } if (value == -1) { - uint16 resourceId = musicSlot->resourceId; + musicSlot->overridePriority = false; + musicSlot->priority = 0; - // Set priority from the song data - Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0); - if (song->data[0] == 0xf0) - _music->soundSetPriority(musicSlot, song->data[1]); - else - warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); + // NB: It seems SSCI doesn't actually reset the priority here. - //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); } else { // Scripted priority + musicSlot->overridePriority = true; - //pSnd->field_15B=1; writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); - //DoSOund(0xF,hobj,w) + + _music->soundSetPriority(musicSlot, value); } return acc; } @@ -777,6 +787,8 @@ void SoundCommandParser::stopAllSounds() { } void SoundCommandParser::startNewSound(int number) { + // NB: This is only used by the debugging console. + Common::StackLock lock(_music->_mutex); // Overwrite the first sound in the playlist @@ -785,7 +797,7 @@ void SoundCommandParser::startNewSound(int number) { processDisposeSound(soundObj); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); processInitSound(soundObj); - processPlaySound(soundObj); + processPlaySound(soundObj, false); } void SoundCommandParser::setMasterVolume(int vol) { diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index 4effda68e4..5bb7cf2cb1 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -63,7 +63,7 @@ public: void printPlayList(Console *con); void printSongInfo(reg_t obj, Console *con); - void processPlaySound(reg_t obj); + void processPlaySound(reg_t obj, bool playBed); void processStopSound(reg_t obj, bool sampleFinishedPlaying); void initSoundResource(MusicEntry *newSound); |