aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/ksound.cpp
diff options
context:
space:
mode:
authorColin Snover2016-03-18 22:55:56 -0500
committerColin Snover2016-06-20 21:02:21 -0500
commit46551fd4b53fc8bf4bbdd3a59aeed56f6f9b53e5 (patch)
tree09a584e4930b9b3e6b9235680cac31028956eccd /engines/sci/engine/ksound.cpp
parent5d3385750ddf68f5347bf51f005c86a8e70283e2 (diff)
downloadscummvm-rg350-46551fd4b53fc8bf4bbdd3a59aeed56f6f9b53e5.tar.gz
scummvm-rg350-46551fd4b53fc8bf4bbdd3a59aeed56f6f9b53e5.tar.bz2
scummvm-rg350-46551fd4b53fc8bf4bbdd3a59aeed56f6f9b53e5.zip
SCI32: Rewrite digital audio engine
This provides a complete implementation of kDoAudio through SCI2.1mid, plus partial implementation of SCI3 features. Digital audio calls shunted through kDoSound have also been updated to go through the SCI32 audio mixer, though these shunts are a bit hacky because the ScummVM implementation of kDoSound does not currently match how SSCI kDoSound is designed. It is probably possible in the future to just replace the SCI1.1 audio code (audio.cpp) with the new SCI32 code, since the major differences seem to be that (1) SCI1.1 only supported one digital audio playback channel (this is configurable already), (2) it had extra commands for CD audio playback and queued sample playback.
Diffstat (limited to 'engines/sci/engine/ksound.cpp')
-rw-r--r--engines/sci/engine/ksound.cpp169
1 files changed, 154 insertions, 15 deletions
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 2b22d6867b..301e4c1b08 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -26,6 +26,9 @@
#include "sci/engine/kernel.h"
#include "sci/engine/vm.h" // for Object
#include "sci/sound/audio.h"
+#ifdef ENABLE_SCI32
+#include "sci/sound/audio32.h"
+#endif
#include "sci/sound/soundcmd.h"
#include "sci/sound/sync.h"
@@ -114,7 +117,8 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
}
/**
- * Used for speech playback and digital soundtracks in CD games
+ * Used for speech playback and digital soundtracks in CD games.
+ * This is the SCI16 version; SCI32 is handled separately.
*/
reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
// JonesCD uses different functions based on the cdaudio.map file
@@ -185,14 +189,6 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
int16 volume = argv[1].toUint16();
volume = CLIP<int16>(volume, 0, AUDIO_VOLUME_MAX);
debugC(kDebugLevelSound, "kDoAudio: set volume to %d", volume);
-#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
- int16 volumePrev = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2;
- volumePrev = CLIP<int16>(volumePrev, 0, AUDIO_VOLUME_MAX);
- mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2);
- return make_reg(0, volumePrev);
- } else
-#endif
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2);
break;
}
@@ -233,12 +229,6 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
if (getSciVersion() <= SCI_VERSION_1_1) {
debugC(kDebugLevelSound, "kDoAudio: CD audio subop");
return kDoCdAudio(s, argc - 1, argv + 1);
-#ifdef ENABLE_SCI32
- } else {
- // TODO: This isn't CD Audio in SCI32 anymore
- warning("kDoAudio: Unhandled case 10, %d extra arguments passed", argc - 1);
- break;
-#endif
}
// 3 new subops in Pharkas CD (including CD demo). kDoAudio in Pharkas sits at seg026:038C
@@ -320,6 +310,155 @@ reg_t kDoSync(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
+reg_t kDoAudio32(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kDoAudioInit(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, 0);
+}
+
+reg_t kDoAudioWaitForPlay(EngineState *s, int argc, reg_t *argv) {
+ return g_sci->_audio32->kernelPlay(false, argc, argv);
+}
+
+reg_t kDoAudioPlay(EngineState *s, int argc, reg_t *argv) {
+ return g_sci->_audio32->kernelPlay(true, argc, argv);
+}
+
+reg_t kDoAudioStop(EngineState *s, int argc, reg_t *argv) {
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 0, argc > 1 ? argv[1] : NULL_REG);
+ return make_reg(0, g_sci->_audio32->stop(channelIndex));
+}
+
+reg_t kDoAudioPause(EngineState *s, int argc, reg_t *argv) {
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 0, argc > 1 ? argv[1] : NULL_REG);
+ return make_reg(0, g_sci->_audio32->pause(channelIndex));
+}
+
+reg_t kDoAudioResume(EngineState *s, int argc, reg_t *argv) {
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 0, argc > 1 ? argv[1] : NULL_REG);
+ return make_reg(0, g_sci->_audio32->resume(channelIndex));
+}
+
+reg_t kDoAudioPosition(EngineState *s, int argc, reg_t *argv) {
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 0, argc > 1 ? argv[1] : NULL_REG);
+ return make_reg(0, g_sci->_audio32->getPosition(channelIndex));
+}
+
+reg_t kDoAudioRate(EngineState *s, int argc, reg_t *argv) {
+ // NOTE: In the original engine this would set the hardware
+ // DSP sampling rate; ScummVM mixer does not need this, so
+ // we only store the value to satisfy engine compatibility.
+
+ if (argc > 0) {
+ const uint16 sampleRate = argv[0].toUint16();
+ if (sampleRate != 0) {
+ g_sci->_audio32->setSampleRate(sampleRate);
+ }
+ }
+
+ return make_reg(0, g_sci->_audio32->getSampleRate());
+}
+
+reg_t kDoAudioVolume(EngineState *s, int argc, reg_t *argv) {
+ const int16 volume = argc > 0 ? argv[0].toSint16() : -1;
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 1, argc > 2 ? argv[2] : NULL_REG);
+
+ if (volume != -1) {
+ g_sci->_audio32->setVolume(channelIndex, volume);
+ }
+
+ return make_reg(0, g_sci->_audio32->getVolume(channelIndex));
+}
+
+reg_t kDoAudioGetCapability(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, 1);
+}
+
+reg_t kDoAudioBitDepth(EngineState *s, int argc, reg_t *argv) {
+ // NOTE: In the original engine this would set the hardware
+ // DSP bit depth; ScummVM mixer does not need this, so
+ // we only store the value to satisfy engine compatibility.
+
+ if (argc > 0) {
+ const uint16 bitDepth = argv[0].toUint16();
+ if (bitDepth != 0) {
+ g_sci->_audio32->setBitDepth(bitDepth);
+ }
+ }
+
+ return make_reg(0, g_sci->_audio32->getBitDepth());
+}
+
+reg_t kDoAudioMixing(EngineState *s, int argc, reg_t *argv) {
+ if (argc > 0) {
+ g_sci->_audio32->setAttenuatedMixing(argv[0].toUint16());
+ }
+
+ return make_reg(0, g_sci->_audio32->getAttenuatedMixing());
+}
+
+reg_t kDoAudioChannels(EngineState *s, int argc, reg_t *argv) {
+ // NOTE: In the original engine this would set the hardware
+ // DSP stereo output; ScummVM mixer does not need this, so
+ // we only store the value to satisfy engine compatibility.
+
+ if (argc > 0) {
+ const int16 numChannels = argv[0].toSint16();
+ if (numChannels != 0) {
+ g_sci->_audio32->setNumOutputChannels(numChannels);
+ }
+ }
+
+ return make_reg(0, g_sci->_audio32->getNumOutputChannels());
+}
+
+reg_t kDoAudioPreload(EngineState *s, int argc, reg_t *argv) {
+ // NOTE: In the original engine this would cause audio
+ // data for new channels to be preloaded to memory when
+ // the channel was initialized; we do not need this, so
+ // we only store the value to satisfy engine compatibility.
+
+ if (argc > 0) {
+ g_sci->_audio32->setPreload(argv[0].toUint16());
+ }
+
+ return make_reg(0, g_sci->_audio32->getPreload());
+}
+
+reg_t kDoAudioFade(EngineState *s, int argc, reg_t *argv) {
+ if (argc < 4) {
+ return make_reg(0, 0);
+ }
+
+ // NOTE: Sierra did a nightmarish hack here, temporarily replacing
+ // the argc of the kernel arguments with 2 and then restoring it
+ // after findChannelByArgs was called.
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(2, argv, 0, argc > 5 ? argv[5] : NULL_REG);
+
+ const int16 volume = argv[1].toSint16();
+ const int16 speed = argv[2].toSint16();
+ const int16 steps = argv[3].toSint16();
+ const bool stopAfterFade = argc > 4 ? (bool)argv[4].toUint16() : false;
+
+ return make_reg(0, g_sci->_audio32->fadeChannel(channelIndex, volume, speed, steps, stopAfterFade));
+}
+
+reg_t kDoAudioHasSignal(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, g_sci->_audio32->hasSignal());
+}
+
+reg_t kDoAudioSetLoop(EngineState *s, int argc, reg_t *argv) {
+ const int16 channelIndex = g_sci->_audio32->findChannelByArgs(argc, argv, 0, argc == 3 ? argv[2] : NULL_REG);
+
+ const bool loop = argv[0].toSint16() != 0 && argv[0].toSint16() != 1;
+
+ g_sci->_audio32->setLoop(channelIndex, loop);
+ return s->r_acc;
+}
reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv) {
// This is used by script 90 of MUMG Deluxe from the main menu to toggle