[Scummvm-git-logs] scummvm master -> 02a7f331b110dc0a5b5df39a6a89ada45aa96101

csnover csnover at users.noreply.github.com
Mon Jun 19 04:43:34 CEST 2017


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
dc9522eae0 SCI32: Fix Audio32 mix volumes
733eaeb499 SCI32: Minor tweaks to improve code clarity & consistency
d556dcc57b SCI: Switch SCI2 games to use Audio32
87895b97f7 SCI: Fix looping of sounds that are not initialized yet
f3c452c31e SCI32: Forward OLDDPCM8 parameter instead of using an if-else
02a7f331b1 SCI32: Remove Windows platform from GK1 German


Commit: dc9522eae09ea740a5b1458dc1f6ffeff4032532
    https://github.com/scummvm/scummvm/commit/dc9522eae09ea740a5b1458dc1f6ffeff4032532
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:41:48-05:00

Commit Message:
SCI32: Fix Audio32 mix volumes

The previous code for attenuating audio channels was not accurate,
so samples were quieter than they were supposed to be when mixed
together. Robots were also being mixed without attenuation, which
was incorrect.

Changed paths:
    engines/sci/sound/audio32.cpp
    engines/sci/sound/audio32.h


diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index f47002b..753d7d4 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -175,6 +175,35 @@ int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::R
 	return samplesWritten;
 }
 
+int16 Audio32::getNumChannelsToMix() const {
+	Common::StackLock lock(_mutex);
+	int16 numChannels = 0;
+	for (int16 channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) {
+		const AudioChannel &channel = getChannel(channelIndex);
+		if (channelShouldMix(channel)) {
+			++numChannels;
+		}
+	}
+	return numChannels;
+}
+
+bool Audio32::channelShouldMix(const AudioChannel &channel) const {
+	if (channel.pausedAtTick ||
+		(channel.robot && (_robotAudioPaused || channel.stream->endOfStream()))) {
+
+		return false;
+	}
+
+	if (channel.fadeStartTick) {
+		const uint32 fadeElapsed = g_sci->getTickCount() - channel.fadeStartTick;
+		if (fadeElapsed > channel.fadeDuration && channel.stopChannelOnFade) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
 // In earlier versions of SCI32 engine, audio mixing is
 // split into three different functions.
 //
@@ -227,50 +256,52 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 	// callback.
 	memset(buffer, 0, numSamples * sizeof(Audio::st_sample_t));
 
-	// This emulates the attenuated mixing mode of SSCI
-	// engine, which reduces the volume of the target
-	// buffer when each new channel is mixed in.
-	// Instead of manipulating the content of the target
-	// buffer when mixing (which would either require
-	// modification of RateConverter or an expensive second
-	// pass against the entire target buffer), we just
-	// scale the volume for each channel in advance, with
-	// the earliest (lowest) channel having the highest
-	// amount of attenuation (lowest volume).
-	uint8 attenuationAmount;
-	uint8 attenuationStepAmount;
+	// This emulates the attenuated mixing mode of SSCI engine, which reduces
+	// the volume of the target buffer when each new channel is mixed in.
+	// Instead of manipulating the content of the target buffer when mixing
+	// (which would either require modification of RateConverter or an expensive
+	// second pass against the entire target buffer), we just scale the volume
+	// for each channel in advance, with the earliest (lowest) channel having
+	// the highest amount of attenuation (lowest volume).
+	int8 attenuationAmount;
+	int8 attenuationStepAmount;
 	if (_useModifiedAttenuation) {
-		// channel | divisor
-		//       0 | 0  (>> 0)
-		//       1 | 4  (>> 2)
-		//       2 | 8...
-		attenuationAmount = _numActiveChannels * 2;
+		// Divides samples in target buffer by 4, and samples in source buffer
+		// by 0, when adding each channel to the output buffer.
+		// 1 channel:  0 >>0
+		// 2 channels: 0 >>2, 1 >>0
+		// 3 channels: 0 >>4, 1 >>2, 2 >>0
+		// 4 channels: 0 >>6, 1 >>4, 2 >>2, 3 >>0 ...
+		// Attenuation amounts are shift values.
+		attenuationAmount = (getNumChannelsToMix() - 1) * 2;
 		attenuationStepAmount = 2;
 	} else {
-		// channel | divisor
-		//       0 | 2  (>> 1)
-		//       1 | 4  (>> 2)
-		//       2 | 6...
-		if (!playOnlyMonitoredChannel && _numActiveChannels > 1) {
-			attenuationAmount = _numActiveChannels + 1;
-			attenuationStepAmount = 1;
-		} else {
-			attenuationAmount = 0;
-			attenuationStepAmount = 0;
-		}
+		// Divides samples in both target & source buffers by 2 when adding each
+		// channel to the output buffer.
+		// 1 channel:  0 >>0
+		// 2 channels: 0 >>1, 1 >>1
+		// 3 channels: 0 >>2, 1 >>2, 2 >>1
+		// 4 channels: 0 >>3, 1 >>3, 2 >>2, 3 >>1 ...
+		// Attenuation amounts are shift values.
+		attenuationAmount = getNumChannelsToMix() - 1;
+		attenuationStepAmount = 1;
 	}
 
 	int maxSamplesWritten = 0;
+	bool firstChannelWritten = false;
 
 	for (int16 channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) {
-		attenuationAmount -= attenuationStepAmount;
-
 		const AudioChannel &channel = getChannel(channelIndex);
 
 		if (channel.pausedAtTick || (channel.robot && _robotAudioPaused)) {
 			continue;
 		}
 
+		if (channel.robot && channel.stream->endOfStream()) {
+			stop(channelIndex--);
+			continue;
+		}
+
 		// Channel finished fading and had the
 		// stopChannelOnFade flag set, so no longer exists
 		if (channel.fadeStartTick && processFade(channelIndex)) {
@@ -278,18 +309,6 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 			continue;
 		}
 
-		if (channel.robot) {
-			if (channel.stream->endOfStream()) {
-				stop(channelIndex--);
-			} else {
-				const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, kMaxVolume, kMaxVolume, channel.loop);
-				if (channelSamplesWritten > maxSamplesWritten) {
-					maxSamplesWritten = channelSamplesWritten;
-				}
-			}
-			continue;
-		}
-
 		Audio::st_volume_t leftVolume, rightVolume;
 
 		if (channel.pan == -1 || !isStereo()) {
@@ -303,8 +322,14 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 		}
 
 		if (!playOnlyMonitoredChannel && _attenuatedMixing) {
+			assert(attenuationAmount >= 0);
 			leftVolume >>= attenuationAmount;
 			rightVolume >>= attenuationAmount;
+			if (!_useModifiedAttenuation && !firstChannelWritten) {
+				firstChannelWritten = true;
+			} else {
+				attenuationAmount -= attenuationStepAmount;
+			}
 		}
 
 		if (channelIndex == _monitoredChannelIndex) {
diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h
index 27f7e8f..510fbc1 100644
--- a/engines/sci/sound/audio32.h
+++ b/engines/sci/sound/audio32.h
@@ -190,6 +190,18 @@ public:
 
 private:
 	/**
+	 * Determines the number of channels that will be mixed together during a
+	 * call to readBuffer.
+	 */
+	int16 getNumChannelsToMix() const;
+
+	/**
+	 * Determines whether or not the given audio channel will be mixed into the
+	 * output stream.
+	 */
+	bool channelShouldMix(const AudioChannel &channel) const;
+
+	/**
 	 * Mixes audio from the given source stream into the
 	 * target buffer using the given rate converter.
 	 */


Commit: 733eaeb499bb39f75e7dd218df4c71b06b7e1610
    https://github.com/scummvm/scummvm/commit/733eaeb499bb39f75e7dd218df4c71b06b7e1610
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:42:58-05:00

Commit Message:
SCI32: Minor tweaks to improve code clarity & consistency

Changed paths:
    engines/sci/sound/audio32.cpp


diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 753d7d4..5e75095 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -232,7 +232,7 @@ bool Audio32::channelShouldMix(const AudioChannel &channel) const {
 // completely fill the audio buffer, the functionality of
 // all these original functions is combined here and
 // simplified.
-int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
+int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples) {
 	Common::StackLock lock(_mutex);
 
 	if (_pausedAtTick != 0 || _numActiveChannels == 0) {
@@ -244,7 +244,6 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 	// the same time we need to be able to clear out any
 	// finished channels on a regular basis
 	_inAudioThread = true;
-
 	freeUnusedChannels();
 
 	const bool playOnlyMonitoredChannel = getSciVersion() != SCI_VERSION_3 && _monitoredChannelIndex != -1;
@@ -476,7 +475,7 @@ void Audio32::lockResource(const ResourceId resourceId, const bool lock) {
 
 void Audio32::freeUnusedChannels() {
 	Common::StackLock lock(_mutex);
-	for (int channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) {
+	for (int16 channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) {
 		const AudioChannel &channel = getChannel(channelIndex);
 		if (!channel.robot && channel.stream->endOfStream()) {
 			if (channel.loop) {


Commit: d556dcc57bf50a03d81ab7a1ef59a9e5758465bf
    https://github.com/scummvm/scummvm/commit/d556dcc57bf50a03d81ab7a1ef59a9e5758465bf
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:42:58-05:00

Commit Message:
SCI: Switch SCI2 games to use Audio32

Upon investigation of Sound code across SCI32 games, it was
determined that there are actually (at least) 3 different
revisions, not just a single SCI2.1 version. This patch only
changes the parts of Sound code that are relevant to the correct
use of Audio32.

Fixes Trac#9736, Trac#9756, Trac#9767, Trac#9791.

Changed paths:
    engines/sci/engine/features.cpp
    engines/sci/engine/features.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/savegame.cpp
    engines/sci/resource_audio.cpp
    engines/sci/sci.cpp
    engines/sci/sound/audio32.cpp
    engines/sci/sound/midiparser_sci.cpp
    engines/sci/sound/music.cpp
    engines/sci/sound/soundcmd.cpp


diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 9251ac6..76f3c35 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -143,8 +143,17 @@ SciVersion GameFeatures::detectDoSoundType() {
 			//  SCI0LATE. Although the last SCI0EARLY game (lsl2) uses SCI0LATE resources
 			_doSoundType = g_sci->getResMan()->detectEarlySound() ? SCI_VERSION_0_EARLY : SCI_VERSION_0_LATE;
 #ifdef ENABLE_SCI32
+		} else if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE &&
+				   g_sci->getGameId() != GID_SQ6 &&
+				   // Assuming MGDX uses SCI2.1early sound mode since SQ6 does
+				   // and it was released earlier, but not verified (Phar Lap
+				   // Windows-only release)
+				   g_sci->getGameId() != GID_MOTHERGOOSEHIRES) {
+			_doSoundType = SCI_VERSION_2_1_MIDDLE;
 		} else if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
 			_doSoundType = SCI_VERSION_2_1_EARLY;
+		} else if (getSciVersion() >= SCI_VERSION_2) {
+			_doSoundType = SCI_VERSION_2;
 #endif
 		} else if (SELECTOR(nodePtr) == -1) {
 			// No nodePtr selector, so this game is definitely using newer
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 0861198..4a5b9eb 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -102,11 +102,8 @@ public:
 		case GID_SQ6:
 			return true;
 		case GID_KQ7:
-		case GID_QFG4:
-			// (1) KQ7 1.51 (SCI2.1early) uses the non-standard attenuation, but
+			// KQ7 1.51 (SCI2.1early) uses the non-standard attenuation, but
 			// 2.00b (SCI2.1mid) does not
-			// (2) QFG4 CD is SCI2.1early; QFG4 floppy is SCI2 and does not use
-			// the SCI2.1 audio system
 			return getSciVersion() == SCI_VERSION_2_1_EARLY;
 		default:
 			return false;
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index a0e7ccf..e077668 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -81,7 +81,6 @@ struct SciKernelMapSubEntry {
 #define SIG_SOUNDSCI0      SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE
 #define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY
 #define SIG_SOUNDSCI1LATE  SCI_VERSION_1_LATE, SCI_VERSION_1_LATE
-#define SIG_SOUNDSCI21     SCI_VERSION_2_1_EARLY, SCI_VERSION_3
 
 #define SIGFOR_ALL   0x3f
 #define SIGFOR_DOS   1 << 0
@@ -152,32 +151,27 @@ static const SciKernelMapSubEntry kDoSound_subops[] = {
 	{ SIG_SOUNDSCI1LATE,  19, MAP_CALL(DoSoundGlobalReverb),       NULL,                   NULL },
 	{ SIG_SOUNDSCI1LATE,  20, MAP_CALL(DoSoundUpdate),             NULL,                   NULL },
 #ifdef ENABLE_SCI32
-	{ SIG_SOUNDSCI21,      0, MAP_CALL(DoSoundMasterVolume),       "(i)",                  NULL },
-	{ SIG_SOUNDSCI21,      1, MAP_CALL(DoSoundMute),               "(i)",                  NULL },
-	{ SIG_SOUNDSCI21,      2, MAP_EMPTY(DoSoundRestore),           NULL,                   NULL },
-	{ SIG_SOUNDSCI21,      3, MAP_CALL(DoSoundGetPolyphony),       "",                     NULL },
-	{ SIG_SOUNDSCI21,      4, MAP_CALL(DoSoundGetAudioCapability), "",                     NULL },
-	{ SIG_SOUNDSCI21,      5, MAP_CALL(DoSoundSuspend),            "i",                    NULL },
-	{ SIG_SOUNDSCI21,      6, MAP_CALL(DoSoundInit),               "o",                    NULL },
-	{ SIG_SOUNDSCI21,      7, MAP_CALL(DoSoundDispose),            "o",                    NULL },
-	{ SIG_SOUNDSCI21,      8, MAP_CALL(DoSoundPlay),               "o",                    kDoSoundPlay_workarounds },
-	// ^^ TODO: if this is really the only change between SCI1LATE AND SCI21, we could rename the
-	//     SIG_SOUNDSCI1LATE #define to SIG_SINCE_SOUNDSCI1LATE and make it being SCI1LATE+. Although
-	//     I guess there are many more changes somewhere
-	// TODO: Quest for Glory 4 (SCI2.1) uses the old scheme, we need to detect it accordingly
-	//        signature for SCI21 should be "o"
-	{ SIG_SOUNDSCI21,      9, MAP_CALL(DoSoundStop),               "o",                    NULL },
-	{ SIG_SOUNDSCI21,     10, MAP_CALL(DoSoundPause),              "[o0]i",                NULL },
-	{ SIG_SOUNDSCI21,     11, MAP_CALL(DoSoundFade),               "oiiii",                kDoSoundFade_workarounds },
-	{ SIG_SOUNDSCI21,     12, MAP_CALL(DoSoundSetHold),            "oi",                   NULL },
-	{ SIG_SOUNDSCI21,     13, MAP_EMPTY(DoSoundDummy),             NULL,                   NULL },
-	{ SIG_SOUNDSCI21,     14, MAP_CALL(DoSoundSetVolume),          "oi",                   NULL },
-	{ SIG_SOUNDSCI21,     15, MAP_CALL(DoSoundSetPriority),        "oi",                   NULL },
-	{ SIG_SOUNDSCI21,     16, MAP_CALL(DoSoundSetLoop),            "oi",                   NULL },
-	{ SIG_SOUNDSCI21,     17, MAP_CALL(DoSoundUpdateCues),         "o",                    NULL },
-	{ SIG_SOUNDSCI21,     18, MAP_CALL(DoSoundSendMidi),           "oiiii",                NULL },
-	{ SIG_SOUNDSCI21,     19, MAP_CALL(DoSoundGlobalReverb),       "(i)",                  NULL },
-	{ SIG_SOUNDSCI21,     20, MAP_CALL(DoSoundUpdate),             "o",                    NULL },
+	{ SIG_SCI32,           0, MAP_CALL(DoSoundMasterVolume),       "(i)",                  NULL },
+	{ SIG_SCI32,           1, MAP_CALL(DoSoundMute),               "(i)",                  NULL },
+	{ SIG_SCI32,           2, MAP_EMPTY(DoSoundRestore),           NULL,                   NULL },
+	{ SIG_SCI32,           3, MAP_CALL(DoSoundGetPolyphony),       "",                     NULL },
+	{ SIG_SCI32,           4, MAP_CALL(DoSoundGetAudioCapability), "",                     NULL },
+	{ SIG_SCI32,           5, MAP_CALL(DoSoundSuspend),            "i",                    NULL },
+	{ SIG_SCI32,           6, MAP_CALL(DoSoundInit),               "o",                    NULL },
+	{ SIG_SCI32,           7, MAP_CALL(DoSoundDispose),            "o",                    NULL },
+	{ SIG_SCI32,           8, MAP_CALL(DoSoundPlay),               "o",                    kDoSoundPlay_workarounds },
+	{ SIG_SCI32,           9, MAP_CALL(DoSoundStop),               "o",                    NULL },
+	{ SIG_SCI32,          10, MAP_CALL(DoSoundPause),              "[o0]i",                NULL },
+	{ SIG_SCI32,          11, MAP_CALL(DoSoundFade),               "oiiii",                kDoSoundFade_workarounds },
+	{ SIG_SCI32,          12, MAP_CALL(DoSoundSetHold),            "oi",                   NULL },
+	{ SIG_SCI32,          13, MAP_EMPTY(DoSoundDummy),             NULL,                   NULL },
+	{ SIG_SCI32,          14, MAP_CALL(DoSoundSetVolume),          "oi",                   NULL },
+	{ SIG_SCI32,          15, MAP_CALL(DoSoundSetPriority),        "oi",                   NULL },
+	{ SIG_SCI32,          16, MAP_CALL(DoSoundSetLoop),            "oi",                   NULL },
+	{ SIG_SCI32,          17, MAP_CALL(DoSoundUpdateCues),         "o",                    NULL },
+	{ SIG_SCI32,          18, MAP_CALL(DoSoundSendMidi),           "oiiii",                NULL },
+	{ SIG_SCI32,          19, MAP_CALL(DoSoundGlobalReverb),       "(i)",                  NULL },
+	{ SIG_SCI32,          20, MAP_CALL(DoSoundUpdate),             "o",                    NULL },
 #endif
 	SCI_SUBOPENTRY_TERMINATOR
 };
@@ -233,8 +227,9 @@ static const SciKernelMapSubEntry kDoAudio_subops[] = {
 	{ SIG_SCI32,          10, MAP_CALL(DoAudioBitDepth),           "(i)",                  NULL },
 	{ SIG_SCI32,          11, MAP_DUMMY(DoAudioDistort),           "(i)",                  NULL },
 	{ SIG_SCI32,          12, MAP_CALL(DoAudioMixing),             "(i)",                  NULL },
-	{ SIG_SCI32,          13, MAP_CALL(DoAudioChannels),           "(i)",                  NULL },
-	{ SIG_SCI32,          14, MAP_CALL(DoAudioPreload),            "(i)",                  NULL },
+	{ SIG_SCI2,           13, MAP_EMPTY(DoAudioSetBufferSize),     "i",                    NULL },
+	{ SIG_SINCE_SCI21,    13, MAP_CALL(DoAudioChannels),           "(i)",                  NULL },
+	{ SIG_SINCE_SCI21,    14, MAP_CALL(DoAudioPreload),            "(i)",                  NULL },
 	{ SIG_SINCE_SCI21MID, 15, MAP_CALL(DoAudioFade),               "(iiii)(i)(i)",         NULL },
 	{ SIG_SINCE_SCI21MID, 16, MAP_DUMMY(DoAudioFade36),            "iiiii(iii)(i)",        NULL },
 	{ SIG_SINCE_SCI21MID, 17, MAP_CALL(DoAudioHasSignal),          "",                     NULL },
@@ -670,9 +665,9 @@ static SciKernelMapEntry s_kernelMap[] = {
 	{ MAP_CALL(DisposeList),       SIG_EVERYWHERE,           "l",                     NULL,            NULL },
 	{ MAP_CALL(DisposeScript),     SIG_EVERYWHERE,           "i(i*)",                 NULL,            kDisposeScript_workarounds },
 	{ MAP_CALL(DisposeWindow),     SIG_EVERYWHERE,           "i(i)",                  NULL,            NULL },
-	{ MAP_CALL(DoAudio),           SCI_VERSION_NONE, SCI_VERSION_2, SIGFOR_ALL, "i(.*)", NULL,         NULL }, // subop
+	{ MAP_CALL(DoAudio),           SIG_SCI16, SIGFOR_ALL,    "i(.*)",                 NULL,            NULL }, // subop
 #ifdef ENABLE_SCI32
-	{ "DoAudio", kDoAudio32,       SIG_SINCE_SCI21, SIGFOR_ALL, "(.*)",               kDoAudio_subops, NULL },
+	{ "DoAudio", kDoAudio32,       SIG_SCI32, SIGFOR_ALL,    "(.*)",                  kDoAudio_subops, NULL },
 #endif
 	{ MAP_CALL(DoAvoider),         SIG_EVERYWHERE,           "o(i)",                  NULL,            NULL },
 	{ MAP_CALL(DoBresen),          SIG_EVERYWHERE,           "o",                     NULL,            NULL },
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index e0f9ec3..995d731 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -435,10 +435,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
 		g_sci->_gfxPalette32->saveLoadWithSerializer(s);
 		g_sci->_gfxRemap32->saveLoadWithSerializer(s);
 		g_sci->_gfxCursor32->saveLoadWithSerializer(s);
-		// TODO: SCI2 should be using Audio32 too, but is not yet.
-		if (g_sci->_audio32) {
-			g_sci->_audio32->saveLoadWithSerializer(s);
-		}
+		g_sci->_audio32->saveLoadWithSerializer(s);
 		g_sci->_video32->saveLoadWithSerializer(s);
 	} else
 #endif
@@ -714,10 +711,10 @@ void SoundCommandParser::reconstructPlayList() {
 		initSoundResource(entry);
 
 #ifdef ENABLE_SCI32
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY && entry->isSample) {
+		if (_soundVersion >= SCI_VERSION_2 && entry->isSample) {
 			const reg_t &soundObj = entry->soundObj;
 
-			if ((int)readSelectorValue(_segMan, soundObj, SELECTOR(loop)) != -1 &&
+			if (readSelectorValue(_segMan, soundObj, SELECTOR(loop)) == 0xFFFF &&
 				readSelector(_segMan, soundObj, SELECTOR(handle)) != NULL_REG) {
 
 				writeSelector(_segMan, soundObj, SELECTOR(handle), NULL_REG);
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 7766ed6..92761ca 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -651,9 +651,7 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
 
 	Channel *channel, *sampleChannel;
 
-	switch (_soundVersion) {
-	case SCI_VERSION_0_EARLY:
-	case SCI_VERSION_0_LATE:
+	if (_soundVersion <= SCI_VERSION_0_LATE) {
 		// SCI0 only has a header of 0x11/0x21 byte length and the actual midi track follows afterwards
 		_trackCount = 1;
 		_tracks = new Track[_trackCount];
@@ -693,11 +691,7 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
 			_tracks->digitalSampleEnd = 0;
 			sampleChannel->data += 44; // Skip over header
 		}
-		break;
-
-	case SCI_VERSION_1_EARLY:
-	case SCI_VERSION_1_LATE:
-	case SCI_VERSION_2_1_EARLY: {
+	} else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) {
 		SciSpan<const byte> data = *resource;
 		// Count # of tracks
 		_trackCount = 0;
@@ -799,11 +793,8 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
 			}
 			++data; // Skipping 0xFF that closes channels list
 		}
-		break;
-	}
-
-	default:
-		error("SoundResource: SCI version %d is unsupported", _soundVersion);
+	} else {
+		error("SoundResource: SCI version %s is unsupported", getSciVersionDesc(_soundVersion));
 	}
 }
 
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index f200bf6..a84f50e 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -315,7 +315,7 @@ Common::Error SciEngine::run() {
 	_guestAdditions = new GuestAdditions(_gamestate, _features, _kernel);
 	_eventMan = new EventManager(_resMan->detectFontExtended());
 #ifdef ENABLE_SCI32
-	if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
+	if (getSciVersion() >= SCI_VERSION_2) {
 		_audio32 = new Audio32(_resMan);
 	} else
 #endif
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 5e75095..cfbab8b 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -114,7 +114,9 @@ Audio32::Audio32(ResourceManager *resMan) :
 	_monitoredBufferSize(0),
 	_numMonitoredSamples(0) {
 
-	if (getSciVersion() < SCI_VERSION_3) {
+	if (getSciVersion() < SCI_VERSION_2_1_EARLY) {
+		_channels.resize(10);
+	} else if (getSciVersion() < SCI_VERSION_3) {
 		_channels.resize(5);
 	} else {
 		_channels.resize(8);
@@ -311,7 +313,22 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
 		Audio::st_volume_t leftVolume, rightVolume;
 
 		if (channel.pan == -1 || !isStereo()) {
-			leftVolume = rightVolume = channel.volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume;
+			int volume = channel.volume;
+			if (getSciVersion() == SCI_VERSION_2) {
+				// NOTE: In SSCI, audio is decompressed into a temporary
+				// buffer, then the samples in that buffer are looped over,
+				// shifting each sample right 3, 2, or 1 bits to reduce the
+				// volume.
+				if (volume > 0 && volume <= 42) {
+					volume = 15;
+				} else if (volume > 42 && volume <= 84) {
+					volume = 31;
+				} else if (volume > 84 && volume < kMaxVolume) {
+					volume = 63;
+				}
+			}
+
+			leftVolume = rightVolume = volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume;
 		} else {
 			// TODO: This should match the SCI3 algorithm,
 			// which seems to halve the volume of each
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index a25ce28..bdd0d1b 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -752,18 +752,12 @@ bool MidiParser_SCI::processEvent(const EventInfo &info, bool fireEvents) {
 			case kUpdateCue:
 				if (!_jumpingToTick) {
 					int inc;
-					switch (_soundVersion) {
-					case SCI_VERSION_0_EARLY:
-					case SCI_VERSION_0_LATE:
+					if (_soundVersion <= SCI_VERSION_0_LATE) {
 						inc = info.basic.param2;
-						break;
-					case SCI_VERSION_1_EARLY:
-					case SCI_VERSION_1_LATE:
-					case SCI_VERSION_2_1_EARLY:
+					} else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) {
 						inc = 1;
-						break;
-					default:
-						error("unsupported _soundVersion");
+					} else {
+						error("Unsupported _soundVersion %s", getSciVersionDesc(_soundVersion));
 					}
 					_pSnd->dataInc += inc;
 					debugC(4, kDebugLevelSound, "datainc %04x", inc);
@@ -895,22 +889,14 @@ void MidiParser_SCI::allNotesOff() {
 void MidiParser_SCI::setMasterVolume(byte masterVolume) {
 	assert(masterVolume <= MUSIC_MASTERVOLUME_MAX);
 	_masterVolume = masterVolume;
-	switch (_soundVersion) {
-	case SCI_VERSION_0_EARLY:
-	case SCI_VERSION_0_LATE:
+	if (_soundVersion <= SCI_VERSION_0_LATE) {
 		// update driver master volume
 		setVolume(_volume);
-		break;
-
-	case SCI_VERSION_1_EARLY:
-	case SCI_VERSION_1_LATE:
-	case SCI_VERSION_2_1_EARLY:
+	} else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) {
 		// directly set master volume (global volume is merged with channel volumes)
 		((MidiPlayer *)_driver)->setVolume(masterVolume);
-		break;
-
-	default:
-		error("MidiParser_SCI::setVolume: Unsupported soundVersion");
+	} else {
+		error("MidiParser_SCI::setVolume: Unsupported soundVersion %s", getSciVersionDesc(_soundVersion));
 	}
 }
 
@@ -918,26 +904,17 @@ void MidiParser_SCI::setVolume(byte volume) {
 	assert(volume <= MUSIC_VOLUME_MAX);
 	_volume = volume;
 
-	switch (_soundVersion) {
-	case SCI_VERSION_0_EARLY:
-	case SCI_VERSION_0_LATE: {
+	if (_soundVersion <= SCI_VERSION_0_LATE) {
 		// SCI0 adlib driver doesn't support channel volumes, so we need to go this way
 		int16 globalVolume = _volume * _masterVolume / MUSIC_VOLUME_MAX;
 		((MidiPlayer *)_driver)->setVolume(globalVolume);
-		break;
-	}
-
-	case SCI_VERSION_1_EARLY:
-	case SCI_VERSION_1_LATE:
-	case SCI_VERSION_2_1_EARLY:
+	} else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) {
 		// Send previous channel volumes again to actually update the volume
 		for (int i = 0; i < 15; i++)
 			if (_channelRemap[i] != -1)
 				sendToDriver(0xB0 + i, 7, _channelVolume[i]);
-		break;
-
-	default:
-		error("MidiParser_SCI::setVolume: Unsupported soundVersion");
+	} else {
+		error("MidiParser_SCI::setVolume: Unsupported soundVersion %s", getSciVersionDesc(_soundVersion));
 	}
 }
 
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 987983a..ae89ee8 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -215,7 +215,7 @@ void SciMusic::pauseAll(bool pause) {
 #ifdef ENABLE_SCI32
 		// The entire DAC will have been paused by the caller;
 		// do not pause the individual samples too
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY && (*i)->isSample) {
+		if (_soundVersion >= SCI_VERSION_2 && (*i)->isSample) {
 			continue;
 		}
 #endif
@@ -483,7 +483,11 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
 
 	if (pSnd->isSample) {
 #ifdef ENABLE_SCI32
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+		if (_soundVersion >= SCI_VERSION_2) {
+			// TODO: Sound number, loop state, and volume come from soundObj
+			// in SSCI. Getting them from MusicEntry could cause a bug if the
+			// soundObj was updated by a game script and not copied back to
+			// MusicEntry.
 			g_sci->_audio32->restart(ResourceId(kResourceTypeAudio, pSnd->resourceId), true, pSnd->loop != 0 && pSnd->loop != 1, pSnd->volume, pSnd->soundObj, false);
 			return;
 		} else
@@ -567,7 +571,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
 		pSnd->isQueued = false;
 	if (pSnd->isSample) {
 #ifdef ENABLE_SCI32
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+		if (_soundVersion >= SCI_VERSION_2) {
 			g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
 		} else {
 #endif
@@ -642,7 +646,7 @@ void SciMusic::soundKill(MusicEntry *pSnd) {
 
 	if (pSnd->isSample) {
 #ifdef ENABLE_SCI32
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+		if (_soundVersion >= SCI_VERSION_2) {
 			g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj);
 		} else {
 #endif
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 07e01fb..f7cb6cd 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -48,7 +48,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_GK1DEMO || ConfMan.getBool("prefer_digitalsfx"));
+	_useDigitalSFX = (_soundVersion >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1DEMO || ConfMan.getBool("prefer_digitalsfx"));
 
 	_music = new SciMusic(_soundVersion, _useDigitalSFX);
 	_music->init();
@@ -100,8 +100,8 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) {
 		if (_useDigitalSFX || !newSound->soundRes) {
 			int sampleLen;
 #ifdef ENABLE_SCI32
-			if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
-				newSound->isSample = g_sci->getResMan()->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId));
+			if (_soundVersion >= SCI_VERSION_2) {
+				newSound->isSample = g_sci->getResMan()->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId)) != nullptr;
 			} else {
 #endif
 				newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
@@ -316,8 +316,8 @@ reg_t SoundCommandParser::kDoSoundPause(EngineState *s, int argc, reg_t *argv) {
 	reg_t obj = argv[0];
 	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())
+		(_soundVersion < SCI_VERSION_2 && !obj.getSegment()) ||
+		(_soundVersion >= SCI_VERSION_2 && obj.isNull())
 	) {
 		_music->pauseAll(shouldPause);
 #ifdef ENABLE_SCI32
@@ -501,7 +501,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
 
 	if (musicSlot->isSample) {
 #ifdef ENABLE_SCI32
-		if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
+		if (_soundVersion >= SCI_VERSION_2) {
 			const int position = g_sci->_audio32->getPosition(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj);
 
 			if (position == -1) {
@@ -717,9 +717,8 @@ reg_t SoundCommandParser::kDoSoundSetVolume(EngineState *s, int argc, reg_t *arg
 	// SSCI unconditionally sets volume if it is digital audio
 	if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
 		_music->soundSetVolume(musicSlot, value);
-	}
+	} else
 #endif
-
 	if (musicSlot->volume != value) {
 		musicSlot->volume = value;
 		_music->soundSetVolume(musicSlot, value);
@@ -783,27 +782,15 @@ reg_t SoundCommandParser::kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv)
 		return s->r_acc;
 	}
 
-#ifdef ENABLE_SCI32
-	if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
-		if (value != -1) {
-			value = 1;
-		}
-	}
-#endif
-
-	if (value == -1) {
-		musicSlot->loop = 0xFFFF;
-	} else {
-		musicSlot->loop = 1; // actually plays the music once
-	}
-
-	writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
+	const uint16 loopCount = value == -1 ? 0xFFFF : 1;
+	writeSelectorValue(_segMan, obj, SELECTOR(loop), loopCount);
 
 #ifdef ENABLE_SCI32
-	if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
+	if (_soundVersion >= SCI_VERSION_2_1_MIDDLE && musicSlot->isSample) {
 		g_sci->_audio32->setLoop(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, value == -1);
-	}
+	} else
 #endif
+		musicSlot->loop = loopCount;
 
 	return s->r_acc;
 }


Commit: 87895b97f76488d531c50c05a25aaabc4d73aaf3
    https://github.com/scummvm/scummvm/commit/87895b97f76488d531c50c05a25aaabc4d73aaf3
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:42:58-05:00

Commit Message:
SCI: Fix looping of sounds that are not initialized yet

This fixes at least the character selection screen in QFG4CD,
where the sound for the torches is supposed to loop, but wasn't
because kDoSoundSetLoop would bail out before setting the loop
property on the soundObj.

Changed paths:
    engines/sci/sound/soundcmd.cpp


diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index f7cb6cd..280015f 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -767,6 +767,9 @@ reg_t SoundCommandParser::kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv)
 
 	debugC(kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value);
 
+	const uint16 loopCount = value == -1 ? 0xFFFF : 1;
+	writeSelectorValue(_segMan, obj, SELECTOR(loop), loopCount);
+
 	MusicEntry *musicSlot = _music->getSlot(obj);
 	if (!musicSlot) {
 		// Apparently, it's perfectly normal for a game to call cmdSetSoundLoop
@@ -782,9 +785,6 @@ reg_t SoundCommandParser::kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv)
 		return s->r_acc;
 	}
 
-	const uint16 loopCount = value == -1 ? 0xFFFF : 1;
-	writeSelectorValue(_segMan, obj, SELECTOR(loop), loopCount);
-
 #ifdef ENABLE_SCI32
 	if (_soundVersion >= SCI_VERSION_2_1_MIDDLE && musicSlot->isSample) {
 		g_sci->_audio32->setLoop(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, value == -1);


Commit: f3c452c31efe6b5e140b2178654d107bc0e7ef2e
    https://github.com/scummvm/scummvm/commit/f3c452c31efe6b5e140b2178654d107bc0e7ef2e
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:42:59-05:00

Commit Message:
SCI32: Forward OLDDPCM8 parameter instead of using an if-else

Thanks @OmerMor for pointing out this improvement.

Changed paths:
    engines/sci/sound/decoders/sol.cpp


diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp
index 290898f..d060fae 100644
--- a/engines/sci/sound/decoders/sol.cpp
+++ b/engines/sci/sound/decoders/sol.cpp
@@ -202,10 +202,8 @@ int SOLStream<STEREO, S16BIT, OLDDPCM8>::readBuffer(int16 *buffer, const int num
 	} else {
 		if (STEREO) {
 			deDPCM8Stereo(buffer, *_stream, bytesToRead, _dpcmCarry8.l, _dpcmCarry8.r);
-		} else if (OLDDPCM8) {
-			deDPCM8Mono<true>(buffer, *_stream, bytesToRead, _dpcmCarry8.l);
 		} else {
-			deDPCM8Mono<false>(buffer, *_stream, bytesToRead, _dpcmCarry8.l);
+			deDPCM8Mono<OLDDPCM8>(buffer, *_stream, bytesToRead, _dpcmCarry8.l);
 		}
 	}
 


Commit: 02a7f331b110dc0a5b5df39a6a89ada45aa96101
    https://github.com/scummvm/scummvm/commit/02a7f331b110dc0a5b5df39a6a89ada45aa96101
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-06-18T21:42:59-05:00

Commit Message:
SCI32: Remove Windows platform from GK1 German

This entry was added by a batch change operation in
f7a72c897a9657320ccd6a32873b364f77412e98, but the German version
of GK1 does not support Windows.

Changed paths:
    engines/sci/detection_tables.h


diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 4924a64..1ba3af4 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -809,14 +809,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
 		AD_LISTEND},
 		Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_GK1_CD },
 
-	// Gabriel Knight - German Windows CD (from Tobis87)
-	// SCI interpreter version 2.000.000
-	{"gk1", "CD", {
-		{"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392},
-		{"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497},
-		AD_LISTEND},
-		Common::DE_DEU, Common::kPlatformWindows, ADGF_CD | ADGF_TESTING, GUIO_GK1_CD },
-
 	// Gabriel Knight - Spanish Windows CD (from jvprat)
 	// Executable scanning reports "2.000.000", VERSION file reports "1.000.000, April 13, 1995"
 	{"gk1", "CD", {





More information about the Scummvm-git-logs mailing list