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 "sherlock/sherlock.h"
24 #include "sherlock/sound.h"
25 #include "common/config-manager.h"
26 #include "audio/audiostream.h"
27 #include "common/algorithm.h"
28 #include "audio/mixer.h"
29 #include "audio/decoders/raw.h"
30 #include "audio/decoders/aiff.h"
31 #include "audio/decoders/wave.h"
32 
33 namespace Sherlock {
34 
35 static const int8 creativeADPCM_ScaleMap[64] = {
36 	0,  1,  2,  3,  4,  5,  6,  7,  0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,
37 	1,  3,  5,  7,  9, 11, 13, 15, -1,  -3,  -5,  -7,  -9, -11, -13, -15,
38 	2,  6, 10, 14, 18, 22, 26, 30, -2,  -6, -10, -14, -18, -22, -26, -30,
39 	4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
40 };
41 
42 static const uint8 creativeADPCM_AdjustMap[64] = {
43 	0, 0, 0, 0, 0, 16, 16, 16,
44 	0, 0, 0, 0, 0, 16, 16, 16,
45 	240, 0, 0, 0, 0, 16, 16, 16,
46 	240, 0, 0, 0, 0, 16, 16, 16,
47 	240, 0, 0, 0, 0, 16, 16, 16,
48 	240, 0, 0, 0, 0, 16, 16, 16,
49 	240, 0, 0, 0, 0,  0,  0,  0,
50 	240, 0, 0, 0, 0,  0,  0,  0
51 };
52 
53 /*----------------------------------------------------------------*/
54 
Sound(SherlockEngine * vm,Audio::Mixer * mixer)55 Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
56 	_digitized = false;
57 	_voices = 0;
58 	_soundPlaying = false;
59 	_speechPlaying = false;
60 	_curPriority = 0;
61 	_soundVolume = ConfMan.hasKey("sfx_volume") ? ConfMan.getInt("sfx_volume") : 255;
62 	_soundOn = ConfMan.hasKey("mute") ? !ConfMan.getBool("mute") : true;
63 	_speechOn = ConfMan.hasKey("speech_mute") ? !ConfMan.getBool("speech_mute") : true;
64 
65 	if (IS_3DO) {
66 		// 3DO: we don't need to prepare anything for sound
67 		return;
68 	}
69 
70 	_vm->_res->addToCache("MUSIC.LIB");
71 	if (!_vm->_interactiveFl)
72 		_vm->_res->addToCache("TITLE.SND");
73 	else {
74 		_vm->_res->addToCache("MUSIC.LIB");
75 
76 		if (IS_ROSE_TATTOO) {
77 			_vm->_res->addToCache("SOUND.LIB");
78 		} else {
79 			_vm->_res->addToCache("SND.SND");
80 
81 			if (!_vm->isDemo()) {
82 				_vm->_res->addToCache("TITLE.SND");
83 				_vm->_res->addToCache("EPILOGUE.SND");
84 			}
85 		}
86 	}
87 }
88 
syncSoundSettings()89 void Sound::syncSoundSettings() {
90 	_digitized = !ConfMan.getBool("mute");
91 	_speechOn = !ConfMan.getBool("mute") && !ConfMan.getBool("speech_mute");
92 	_voices = _digitized ? 1 : 0;
93 }
94 
loadSound(const Common::String & name,int priority)95 void Sound::loadSound(const Common::String &name, int priority) {
96 	// No implementation required in ScummVM
97 	//warning("loadSound");
98 }
99 
decodeSample(byte sample,byte & reference,int16 & scale)100 byte Sound::decodeSample(byte sample, byte &reference, int16 &scale) {
101 	int16 samp = sample + scale;
102 	int16 ref = 0;
103 
104 	// clip bad ADPCM-4 sample
105 	samp = CLIP<int16>(samp, 0, 63);
106 
107 	ref = reference + creativeADPCM_ScaleMap[samp];
108 	if (ref > 0xff) {
109 		reference = 0xff;
110 	} else {
111 		if (ref < 0x00) {
112 			reference = 0;
113 		} else {
114 			reference = (uint8)(ref & 0xff);
115 		}
116 	}
117 
118 	scale = (scale + creativeADPCM_AdjustMap[samp]) & 0xff;
119 	return reference;
120 }
121 
playSound(const Common::String & name,WaitType waitType,int priority,const char * libraryFilename)122 bool Sound::playSound(const Common::String &name, WaitType waitType, int priority, const char *libraryFilename) {
123 	// Scalpel has only a single sound handle, so it must be stopped before starting a new sound
124 	if (IS_SERRATED_SCALPEL)
125 		stopSound();
126 
127 	Common::String filename = formFilename(name);
128 
129 	Audio::SoundHandle &soundHandle = (IS_SERRATED_SCALPEL) ? _scalpelEffectsHandle : getFreeSoundHandle();
130 	if (!playSoundResource(filename, libraryFilename, Audio::Mixer::kSFXSoundType, soundHandle))
131 		error("Could not find sound resource - %s", filename.c_str());
132 
133 	_soundPlaying = true;
134 	_curPriority = priority;
135 
136 	if (waitType == WAIT_RETURN_IMMEDIATELY) {
137 		return true;
138 	}
139 
140 	bool retval = true;
141 	do {
142 		_vm->_events->pollEvents();
143 		g_system->delayMillis(10);
144 		if ((waitType == WAIT_KBD_OR_FINISH) && _vm->_events->kbHit()) {
145 			retval = false;
146 			break;
147 		}
148 	} while (!_vm->shouldQuit() && _mixer->isSoundHandleActive(soundHandle));
149 
150 	_soundPlaying = false;
151 	_mixer->stopHandle(soundHandle);
152 
153 	return retval;
154 }
155 
formFilename(const Common::String & name)156 Common::String Sound::formFilename(const Common::String &name) {
157 	Common::String filename = name;
158 
159 	if (!filename.contains('.')) {
160 		if (!IS_3DO) {
161 			if (IS_SERRATED_SCALPEL) {
162 				filename += ".SND";
163 			} else {
164 				filename += ".WAV";
165 			}
166 		} else {
167 			// 3DO uses .aiff extension
168 			filename += ".AIFF";
169 			if (!filename.contains('/')) {
170 				// if no directory was given, use the room sounds directory
171 				filename = "rooms/sounds/" + filename;
172 			}
173 		}
174 	}
175 
176 	return filename;
177 }
178 
playAiff(const Common::String & name,int volume,bool loop)179 void Sound::playAiff(const Common::String &name, int volume, bool loop) {
180 	Common::File *file = new Common::File();
181 	if (!file->open(name)) {
182 		delete file;
183 		return;
184 	}
185 	Audio::AudioStream *stream;
186 	Audio::RewindableAudioStream *audioStream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
187 	if (loop) {
188 		Audio::AudioStream *loopingStream = Audio::makeLoopingAudioStream(audioStream, 0);
189 		stream = loopingStream;
190 	} else {
191 		stream = audioStream;
192 	}
193 	stopAiff();
194 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_aiffHandle, stream, -1, volume);
195 }
196 
stopAiff()197 void Sound::stopAiff() {
198 	if (_mixer->isSoundHandleActive(_aiffHandle)) {
199 		_mixer->stopHandle(_aiffHandle);
200 	}
201 }
202 
playLoadedSound(int bufNum,WaitType waitType)203 void Sound::playLoadedSound(int bufNum, WaitType waitType) {
204 	if (IS_SERRATED_SCALPEL) {
205 		if (_mixer->isSoundHandleActive(_scalpelEffectsHandle) && (_curPriority > _vm->_scene->_sounds[bufNum]._priority))
206 			return;
207 
208 		stopSound();
209 	}
210 
211 	playSound(_vm->_scene->_sounds[bufNum]._name, waitType, _vm->_scene->_sounds[bufNum]._priority);
212 }
213 
freeLoadedSounds()214 void Sound::freeLoadedSounds() {
215 	// As sounds are played with DisposeAfterUse::YES, stopping the sounds also
216 	// frees them
217 	stopSound();
218 }
219 
stopSound()220 void Sound::stopSound() {
221 	if (IS_SERRATED_SCALPEL) {
222 		_mixer->stopHandle(_scalpelEffectsHandle);
223 	} else {
224 		for (int i = 0; i < MAX_MIXER_CHANNELS; i++)
225 			_mixer->stopHandle(_tattooEffectsHandle[i]);
226 	}
227 }
228 
freeDigiSound()229 void Sound::freeDigiSound() {
230 	_soundPlaying = false;
231 }
232 
getFreeSoundHandle()233 Audio::SoundHandle &Sound::getFreeSoundHandle() {
234 	for (int i = 0; i < MAX_MIXER_CHANNELS; i++) {
235 		if (!_mixer->isSoundHandleActive(_tattooEffectsHandle[i]))
236 			return _tattooEffectsHandle[i];
237 	}
238 
239 	error("getFreeSoundHandle: No sound handle found");
240 }
241 
setVolume(int volume)242 void Sound::setVolume(int volume) {
243 	_soundVolume = volume;
244 	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
245 	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume);
246 	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
247 }
248 
playSpeech(const Common::String & name)249 void Sound::playSpeech(const Common::String &name) {
250 	Resources &res = *_vm->_res;
251 	Scene &scene = *_vm->_scene;
252 
253 	// Stop any previously playing speech
254 	stopSpeech();
255 
256 	if (IS_SERRATED_SCALPEL) {
257 		Common::String filename = formFilename(name);
258 		if (playSoundResource(filename, Common::String(), Audio::Mixer::kSFXSoundType, _speechHandle))
259 			_speechPlaying = true;
260 	} else {
261 		// Figure out which speech library to use
262 		Common::String libraryName = Common::String::format("speech%02d.lib", scene._currentScene);
263 		if ((!scumm_strnicmp(name.c_str(), "SLVE12S", 7)) || (!scumm_strnicmp(name.c_str(), "WATS12X", 7))
264 				|| (!scumm_strnicmp(name.c_str(), "HOLM12X", 7)))
265 			libraryName = "SPEECH12.LIB";
266 
267 		// If the speech library file doesn't even exist, then we can't play anything
268 		Common::File f;
269 		if (!f.exists(libraryName))
270 			return;
271 
272 		// Ensure the given library is in the cache
273 		res.addToCache(libraryName);
274 
275 		if (playSoundResource(name, libraryName, Audio::Mixer::kSpeechSoundType, _speechHandle))
276 			_speechPlaying = true;
277 	}
278 }
279 
stopSpeech()280 void Sound::stopSpeech() {
281 	_mixer->stopHandle(_speechHandle);
282 	_speechPlaying = false;
283 }
284 
isSpeechPlaying()285 bool Sound::isSpeechPlaying() {
286 	_speechPlaying = _mixer->isSoundHandleActive(_speechHandle);
287 	return _speechPlaying;
288 }
289 
playSoundResource(const Common::String & name,const Common::String & libFilename,Audio::Mixer::SoundType soundType,Audio::SoundHandle & handle)290 bool Sound::playSoundResource(const Common::String &name, const Common::String &libFilename,
291 		Audio::Mixer::SoundType soundType, Audio::SoundHandle &handle) {
292 	Resources &res = *_vm->_res;
293 	Common::SeekableReadStream *stream = libFilename.empty() ? res.load(name) : res.load(name, libFilename, true);
294 	if (!stream)
295 		return false;
296 
297 	Audio::AudioStream *audioStream;
298 	if (IS_ROSE_TATTOO && soundType == Audio::Mixer::kSpeechSoundType) {
299 		audioStream = Audio::makeRawStream(stream, 11025, Audio::FLAG_UNSIGNED);
300 	} else if (IS_3DO) {
301 		// 3DO: AIFF file
302 		audioStream = Audio::makeAIFFStream(stream, DisposeAfterUse::YES);
303 	} else if (IS_SERRATED_SCALPEL) {
304 		stream->skip(2);
305 		int size = stream->readUint32BE();
306 		int rate = stream->readUint16BE();
307 		byte *data = (byte *)malloc(size);
308 		byte *ptr = data;
309 		stream->read(ptr, size);
310 		delete stream;
311 
312 		assert(size > 2);
313 
314 		byte *decoded = (byte *)malloc((size - 1) * 2);
315 
316 		// WORKAROUND: The doorbell and fog horn at Lord Brumwell's mansion
317 		// sounds really strange at 1100 Hz. The game isn't heavy on sounds,
318 		// but other sound effects seem to be mostly at 11000 Hz, and that
319 		// sounds about right here since it matches the 3DO version.
320 
321 		if ((name == "JFCHIME.SND" || name == "JFFOG.SND") && rate == 1100) {
322 			rate = 11000;
323 		}
324 
325 		// Holmes uses Creative ADPCM 4-bit data
326 		int counter = 0;
327 		byte reference = ptr[0];
328 		int16 scale = 0;
329 
330 		for (int i = 1; i < size; i++) {
331 			decoded[counter++] = decodeSample((ptr[i] >> 4) & 0x0f, reference, scale);
332 			decoded[counter++] = decodeSample((ptr[i] >> 0) & 0x0f, reference, scale);
333 		}
334 
335 		free(data);
336 
337 		audioStream = Audio::makeRawStream(decoded, (size - 2) * 2, rate, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
338 	} else {
339 		audioStream = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
340 	}
341 
342 	if (!audioStream)
343 		return false;
344 
345 	_mixer->playStream(soundType, &handle, audioStream, -1, Audio::Mixer::kMaxChannelVolume);
346 	return true;
347 }
348 
349 } // End of namespace Sherlock
350 
351