aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sound/soundcmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sound/soundcmd.cpp')
-rw-r--r--engines/sci/sound/soundcmd.cpp166
1 files changed, 126 insertions, 40 deletions
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 73e0a23a6a..b9a764c93a 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -21,6 +21,9 @@
*/
#include "common/config-manager.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "sci/resource.h"
#include "sci/sound/audio.h"
#include "sci/sound/music.h"
#include "sci/sound/soundcmd.h"
@@ -44,7 +47,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM
// resource number, but it's totally unrelated to the menu music).
// The GK1 demo (very late SCI1.1) does the same thing
// TODO: Check the QFG4 demo
- _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || ConfMan.getBool("prefer_digitalsfx"));
+ _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1DEMO || ConfMan.getBool("prefer_digitalsfx"));
_music = new SciMusic(_soundVersion, _useDigitalSFX);
_music->init();
@@ -95,12 +98,21 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) {
// user wants the digital version.
if (_useDigitalSFX || !newSound->soundRes) {
int sampleLen;
- newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
- newSound->soundType = Audio::Mixer::kSFXSoundType;
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+ newSound->isSample = g_sci->getResMan()->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId));
+ } else {
+#endif
+ newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
+ newSound->soundType = Audio::Mixer::kSFXSoundType;
+ newSound->isSample = newSound->pStreamAud != nullptr;
+#ifdef ENABLE_SCI32
+ }
+#endif
}
}
- if (!newSound->pStreamAud && newSound->soundRes)
+ if (!newSound->isSample && newSound->soundRes)
_music->soundInitSnd(newSound);
}
@@ -116,6 +128,7 @@ void SoundCommandParser::processInitSound(reg_t obj) {
newSound->resourceId = resourceId;
newSound->soundObj = obj;
newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
+ newSound->overridePriority = false;
if (_soundVersion <= SCI_VERSION_0_LATE)
newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
else
@@ -131,7 +144,7 @@ void SoundCommandParser::processInitSound(reg_t obj) {
_music->pushBackSlot(newSound);
- if (newSound->soundRes || newSound->pStreamAud) {
+ if (newSound->soundRes || newSound->isSample) {
// Notify the engine
if (_soundVersion <= SCI_VERSION_0_LATE)
writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized);
@@ -142,11 +155,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 +197,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);
@@ -198,17 +225,6 @@ void SoundCommandParser::processPlaySound(reg_t obj) {
musicSlot->fadeStep = 0;
}
-reg_t SoundCommandParser::kDoSoundRestore(int argc, reg_t *argv, reg_t acc) {
- // Called after loading, to restore the playlist
- // We don't really use or need this
- return acc;
-}
-
-reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) {
- warning("cmdDummy invoked"); // not supposed to occur
- return acc;
-}
-
reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) {
debugC(kDebugLevelSound, "kDoSound(dispose): %04x:%04x", PRINT_REG(argv[0]));
processDisposeSound(argv[0]);
@@ -297,10 +313,22 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) {
}
reg_t obj = argv[0];
- uint16 value = argc > 1 ? argv[1].toUint16() : 0;
- if (!obj.getSegment()) { // pause the whole playlist
- _music->pauseAll(value);
- } else { // pause a playlist slot
+ const bool shouldPause = argc > 1 ? argv[1].toUint16() : false;
+ if (
+ (_soundVersion < SCI_VERSION_2_1_EARLY && !obj.getSegment()) ||
+ (_soundVersion >= SCI_VERSION_2_1_EARLY && obj.isNull())
+ ) {
+ _music->pauseAll(shouldPause);
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+ if (shouldPause) {
+ g_sci->_audio32->pause(kAllChannels);
+ } else {
+ g_sci->_audio32->resume(kAllChannels);
+ }
+ }
+#endif
+ } else {
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
// This happens quite frequently
@@ -308,7 +336,23 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) {
return acc;
}
- _music->soundToggle(musicSlot, value);
+#ifdef ENABLE_SCI32
+ // NOTE: The original engine also expected a global
+ // "kernel call" flag to be true in order to perform
+ // this action, but the architecture of the ScummVM
+ // implementation is so different that it doesn't
+ // matter here
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
+ const int16 channelIndex = g_sci->_audio32->findChannelById(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj);
+
+ if (shouldPause) {
+ g_sci->_audio32->pause(channelIndex);
+ } else {
+ g_sci->_audio32->resume(channelIndex);
+ }
+ } else
+#endif
+ _music->soundToggle(musicSlot, shouldPause);
}
return acc;
}
@@ -338,7 +382,11 @@ reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc)
int vol = CLIP<int16>(argv[0].toSint16(), 0, MUSIC_MASTERVOLUME_MAX);
vol = vol * Audio::Mixer::kMaxMixerVolume / MUSIC_MASTERVOLUME_MAX;
ConfMan.setInt("music_volume", vol);
- ConfMan.setInt("sfx_volume", vol);
+ // In SCI32, digital audio volume is controlled separately by
+ // kDoAudioVolume
+ if (_soundVersion < SCI_VERSION_2_1_EARLY) {
+ ConfMan.setInt("sfx_volume", vol);
+ }
g_engine->syncSoundSettings();
}
return acc;
@@ -361,6 +409,13 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
int volume = musicSlot->volume;
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
+ g_sci->_audio32->fadeChannel(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16(), argc > 4 ? (bool)argv[4].toSint16() : false);
+ return acc;
+ }
+#endif
+
// If sound is not playing currently, set signal directly
if (musicSlot->status != kSoundPlaying) {
debugC(kDebugLevelSound, "kDoSound(fade): %04x:%04x fading requested, but sound is currently not playing", PRINT_REG(obj));
@@ -449,7 +504,18 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
return;
}
- if (musicSlot->pStreamAud) {
+ if (musicSlot->isSample) {
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+ const int position = g_sci->_audio32->getPosition(g_sci->_audio32->findChannelById(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj));
+
+ if (position == -1) {
+ processStopSound(musicSlot->soundObj, true);
+ }
+
+ return;
+ }
+#endif
// Update digital sound effect slots
uint currentLoopCounter = 0;
@@ -538,7 +604,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);
}
}
@@ -652,6 +718,12 @@ reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) {
value = CLIP<int>(value, 0, MUSIC_VOLUME_MAX);
+#ifdef ENABLE_SCI32
+ // SSCI unconditionally sets volume if it is digital audio
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
+ _music->soundSetVolume(musicSlot, value);
+ }
+#endif
if (musicSlot->volume != value) {
musicSlot->volume = value;
_music->soundSetVolume(musicSlot, value);
@@ -673,23 +745,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;
}
@@ -714,6 +782,15 @@ reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) {
}
return acc;
}
+
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+ if (value != -1) {
+ value = 1;
+ }
+ }
+#endif
+
if (value == -1) {
musicSlot->loop = 0xFFFF;
} else {
@@ -721,6 +798,13 @@ reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) {
}
writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
+
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
+ g_sci->_audio32->setLoop(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, value == -1);
+ }
+#endif
+
return acc;
}
@@ -777,6 +861,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 +871,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) {