[Scummvm-cvs-logs] SF.net SVN: scummvm:[45000] scummvm/trunk/engines/draci

spalek at users.sourceforge.net spalek at users.sourceforge.net
Tue Oct 13 00:27:23 CEST 2009


Revision: 45000
          http://scummvm.svn.sourceforge.net/scummvm/?rev=45000&view=rev
Author:   spalek
Date:     2009-10-12 22:27:23 +0000 (Mon, 12 Oct 2009)

Log Message:
-----------
Sound effects are now correctly played.

Dubbing is not yet played.

Modified Paths:
--------------
    scummvm/trunk/engines/draci/animation.cpp
    scummvm/trunk/engines/draci/animation.h
    scummvm/trunk/engines/draci/draci.cpp
    scummvm/trunk/engines/draci/draci.h
    scummvm/trunk/engines/draci/game.cpp
    scummvm/trunk/engines/draci/sound.cpp
    scummvm/trunk/engines/draci/sound.h

Modified: scummvm/trunk/engines/draci/animation.cpp
===================================================================
--- scummvm/trunk/engines/draci/animation.cpp	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/animation.cpp	2009-10-12 22:27:23 UTC (rev 45000)
@@ -39,6 +39,7 @@
 	_paused = false;
 	_tick = _vm->_system->getMillis();
 	_currentFrame = 0;
+	_hasChangedFrame = true;
 	_callback = &Animation::doNothing;
 }
 
@@ -97,6 +98,8 @@
 
 			// Fetch new frame and mark it dirty
 			markDirtyRect(surface);
+
+			_hasChangedFrame = true;
 		}
 	}
 
@@ -129,6 +132,15 @@
 		// Draw frame
 		frame->drawReScaled(surface, false, _displacement);
 	}
+
+	const SoundSample *sample = _samples[_currentFrame];
+	if (_hasChangedFrame && sample) {
+		debugC(3, kDraciSoundDebugLevel,
+			"Playing sample on animation %d, frame %d: %d+%d at %dHz",
+			_id, _currentFrame, sample->_offset, sample->_length, sample->_frequency);
+		_vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false);
+	}
+	_hasChangedFrame = false;
 }
 
 void Animation::setID(int id) {
@@ -162,6 +174,9 @@
 void Animation::setPlaying(bool playing) {
 	_tick = _vm->_system->getMillis();
 	_playing = playing;
+
+	// When restarting an animation, allow playing sounds.
+	_hasChangedFrame |= playing;
 }
 
 bool Animation::isPaused() const {

Modified: scummvm/trunk/engines/draci/animation.h
===================================================================
--- scummvm/trunk/engines/draci/animation.h	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/animation.h	2009-10-12 22:27:23 UTC (rev 45000)
@@ -130,6 +130,7 @@
 
 	uint _currentFrame;
 	uint _z;
+	bool _hasChangedFrame;
 
 	Displacement _displacement;
 
@@ -145,7 +146,7 @@
 	 * object doesn't own these pointers, but they are stored in the
 	 * cache.
 	 */
-	Common::List<const SoundSample *> _samples;
+	Common::Array<const SoundSample *> _samples;
 
 	AnimationCallback _callback;
 

Modified: scummvm/trunk/engines/draci/draci.cpp
===================================================================
--- scummvm/trunk/engines/draci/draci.cpp	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/draci.cpp	2009-10-12 22:27:23 UTC (rev 45000)
@@ -62,6 +62,9 @@
 const char *soundsPath = "CD2.SAM";
 const char *dubbingPath = "CD.SAM";
 
+const uint kSoundsFrequency = 13000;
+const uint kDubbingFrequency = 22000;
+
 DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc)
  : Engine(syst) {
 	// Put your engine in a sane state, but do nothing big yet;
@@ -79,6 +82,7 @@
 	Common::addDebugChannel(kDraciArchiverDebugLevel, "archiver", "BAR archiver debug info");
 	Common::addDebugChannel(kDraciLogicDebugLevel, "logic", "Game logic debug info");
 	Common::addDebugChannel(kDraciAnimationDebugLevel, "animation", "Animation debug info");
+	Common::addDebugChannel(kDraciSoundDebugLevel, "sound", "Sound debug info");
 
 	// Don't forget to register your random source
 	g_eventRec.registerRandomSource(_rnd, "draci");
@@ -109,8 +113,9 @@
 	_itemImagesArchive = new BArchive(itemImagesPath);
 	_stringsArchive = new BArchive(stringsPath);
 
-	_soundsArchive = new SoundArchive(soundsPath);
-	_dubbingArchive = new SoundArchive(dubbingPath);
+	_soundsArchive = new SoundArchive(soundsPath, kSoundsFrequency);
+	_dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency);
+	_sound = new Sound(_mixer);
 
 	// Load the game's fonts
 	_smallFont = new Font(kFontSmall);
@@ -298,6 +303,7 @@
 
 	delete _soundsArchive;
 	delete _dubbingArchive;
+	delete _sound;
 
 	// Remove all of our debug levels here
 	Common::clearAllDebugChannels();
@@ -337,7 +343,7 @@
 void DraciEngine::syncSoundSettings() {
 	Engine::syncSoundSettings();
 
-	// TODO: update our volumes
+	_sound->setVolume();
 }
 
 const char *DraciEngine::getSavegameFile(int saveGameIdx) {

Modified: scummvm/trunk/engines/draci/draci.h
===================================================================
--- scummvm/trunk/engines/draci/draci.h	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/draci.h	2009-10-12 22:27:23 UTC (rev 45000)
@@ -66,6 +66,7 @@
 	Game *_game;
 	Script *_script;
 	AnimationManager *_anims;
+	Sound *_sound;
 
 	Font *_smallFont;
 	Font *_bigFont;
@@ -99,7 +100,8 @@
 	kDraciBytecodeDebugLevel  = 1 << 1,
 	kDraciArchiverDebugLevel  = 1 << 2,
 	kDraciLogicDebugLevel     = 1 << 3,
-	kDraciAnimationDebugLevel = 1 << 4
+	kDraciAnimationDebugLevel = 1 << 4,
+	kDraciSoundDebugLevel     = 1 << 5
 };
 
 // Macro to simulate lround() for non-C99 compilers

Modified: scummvm/trunk/engines/draci/game.cpp
===================================================================
--- scummvm/trunk/engines/draci/game.cpp	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/game.cpp	2009-10-12 22:27:23 UTC (rev 45000)
@@ -1157,7 +1157,7 @@
 		uint scaledWidth = animationReader.readUint16LE();
 		uint scaledHeight = animationReader.readUint16LE();
 		byte mirror = animationReader.readByte();
-		uint sample = animationReader.readUint16LE();
+		int sample = animationReader.readUint16LE() - 1;
 		uint freq = animationReader.readUint16LE();
 		uint delay = animationReader.readUint16LE();
 
@@ -1301,6 +1301,11 @@
 	}
 	debugC(1, kDraciLogicDebugLevel, "Entering room %d using gate %d", _newRoom, _newGate);
 
+	// TODO: maybe wait till all sounds end instead of stopping them.
+	// In any case, make sure all sounds are stopped before we deallocate
+	// their memory by clearing the cache.
+	_vm->_sound->stopAll();
+
 	// Clear archives
 	_vm->_roomsArchive->clearCache();
 	_vm->_spritesArchive->clearCache();

Modified: scummvm/trunk/engines/draci/sound.cpp
===================================================================
--- scummvm/trunk/engines/draci/sound.cpp	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/sound.cpp	2009-10-12 22:27:23 UTC (rev 45000)
@@ -23,6 +23,7 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "common/debug.h"
 #include "common/file.h"
 #include "common/str.h"
@@ -31,6 +32,9 @@
 #include "draci/sound.h"
 #include "draci/draci.h"
 
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
 namespace Draci {
 
 void SoundArchive::openArchive(const Common::String &path) {
@@ -129,9 +133,9 @@
  *
  * Loads individual samples from an archive to memory on demand.
  */
-const SoundSample *SoundArchive::getSample(uint i, uint freq) {
+const SoundSample *SoundArchive::getSample(int i, uint freq) {
 	// Check whether requested file exists
-	if (i >= _sampleCount) {
+	if (i < 0 || i >= (int) _sampleCount) {
 		return NULL;
 	}
 
@@ -150,12 +154,122 @@
 		debugC(3, kDraciArchiverDebugLevel, "Cached sample %d from archive %s",
 			i, _path.c_str());
 	}
-	_samples[i]._frequency = freq;
+	_samples[i]._frequency = freq ? freq : _defaultFreq;
 
 	return _samples + i;
 }
 
-} // End of namespace Draci
+Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer) {
 
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		_handles[i].type = kFreeHandle;
 
+	setVolume();
+}
 
+SndHandle *Sound::getHandle() {
+	for (int i = 0; i < SOUND_HANDLES; i++) {
+		if (_handles[i].type != kFreeHandle && !_mixer->isSoundHandleActive(_handles[i].handle)) {
+			debugC(5, kDraciSoundDebugLevel, "Handle %d has finished playing", i);
+			_handles[i].type = kFreeHandle;
+		}
+	}
+
+	for (int i = 0; i < SOUND_HANDLES; i++) {
+		if (_handles[i].type == kFreeHandle)
+			return &_handles[i];
+	}
+
+	error("Sound::getHandle(): Too many sound handles");
+
+	return NULL;	// for compilers that don't support NORETURN
+}
+
+void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
+				sndHandleType handleType, bool loop) {
+
+	// Don't use FLAG_AUTOFREE, because our caching system deletes samples by itself.
+	byte flags = Audio::Mixer::FLAG_UNSIGNED;
+
+	if (loop)
+		flags |= Audio::Mixer::FLAG_LOOP;
+
+	const Audio::Mixer::SoundType soundType = (handleType == kVoiceHandle) ? 
+				Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType;
+
+	_mixer->playRaw(soundType, handle, buffer._data,
+			buffer._length, buffer._frequency, flags, -1, volume);
+}
+
+void Sound::playSound(const SoundSample *buffer, int volume, bool loop) {
+	if (!buffer)
+		return;
+	SndHandle *handle = getHandle();
+
+	handle->type = kEffectHandle;
+	playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop);
+}
+
+void Sound::pauseSound() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kEffectHandle)
+			_mixer->pauseHandle(_handles[i].handle, true);
+}
+
+void Sound::resumeSound() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kEffectHandle)
+			_mixer->pauseHandle(_handles[i].handle, false);
+}
+
+void Sound::stopSound() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kEffectHandle) {
+			_mixer->stopHandle(_handles[i].handle);
+			_handles[i].type = kFreeHandle;
+		}
+}
+
+void Sound::playVoice(const SoundSample *buffer) {
+	if (!buffer)
+		return;
+	SndHandle *handle = getHandle();
+
+	handle->type = kVoiceHandle;
+	playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false);
+}
+
+void Sound::pauseVoice() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kVoiceHandle)
+			_mixer->pauseHandle(_handles[i].handle, true);
+}
+
+void Sound::resumeVoice() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kVoiceHandle)
+			_mixer->pauseHandle(_handles[i].handle, false);
+}
+
+void Sound::stopVoice() {
+	for (int i = 0; i < SOUND_HANDLES; i++)
+		if (_handles[i].type == kVoiceHandle) {
+			_mixer->stopHandle(_handles[i].handle);
+			_handles[i].type = kFreeHandle;
+		}
+}
+
+void Sound::stopAll() {
+	stopVoice();
+	stopSound();
+}
+
+void Sound::setVolume() {
+	const int soundVolume = ConfMan.getInt("sfx_volume");
+	const int speechVolume = ConfMan.getInt("speech_volume");
+	_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume);
+	_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume);
+	// TODO: make sure this sound settings works
+}
+
+} // End of namespace Draci

Modified: scummvm/trunk/engines/draci/sound.h
===================================================================
--- scummvm/trunk/engines/draci/sound.h	2009-10-12 22:23:27 UTC (rev 44999)
+++ scummvm/trunk/engines/draci/sound.h	2009-10-12 22:27:23 UTC (rev 45000)
@@ -28,6 +28,7 @@
 
 #include "common/str.h"
 #include "common/file.h"
+#include "sound/mixer.h"
 
 namespace Draci {
 
@@ -48,10 +49,8 @@
 
 class SoundArchive {
 public:
-	SoundArchive() : _path(), _samples(NULL), _sampleCount(0), _opened(false), _f(NULL) {}
-
-	SoundArchive(const Common::String &path) :
-	_path(), _samples(NULL), _sampleCount(0), _opened(false), _f(NULL) {
+	SoundArchive(const Common::String &path, uint defaultFreq) :
+	_path(), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) {
 		openArchive(path);
 	}
 
@@ -69,16 +68,64 @@
 
 	void clearCache();
 
-	const SoundSample *getSample(uint i, uint freq);
+	const SoundSample *getSample(int i, uint freq);
 
 private:
 	Common::String _path;    ///< Path to file
 	SoundSample *_samples;          ///< Internal array of files
 	uint _sampleCount;         ///< Number of files in archive
+	uint _defaultFreq;	///< The default sampling frequency of the archived samples
 	bool _opened;            ///< True if the archive is opened, false otherwise
 	Common::File *_f;	///< Opened file
 };
 
+#define SOUND_HANDLES 10
+
+enum sndHandleType {
+	kFreeHandle,
+	kEffectHandle,
+	kVoiceHandle
+};
+
+struct SndHandle {
+	Audio::SoundHandle handle;
+	sndHandleType type;
+};
+
+// Taken from engines/saga/sound.h and simplified (in particular, removed
+// decompression until we support compressed files too).
+class Sound {
+public:
+
+	Sound(Audio::Mixer *mixer);
+	~Sound() {}
+
+	void playSound(const SoundSample *buffer, int volume, bool loop);
+	void pauseSound();
+	void resumeSound();
+	void stopSound();
+
+	void playVoice(const SoundSample *buffer);
+	void pauseVoice();
+	void resumeVoice();
+	void stopVoice();
+
+	void stopAll();
+
+	void setVolume();
+
+ private:
+
+	void playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
+				sndHandleType handleType, bool loop);
+
+	SndHandle *getHandle();
+
+	Audio::Mixer *_mixer;
+
+	SndHandle _handles[SOUND_HANDLES];
+};
+
 } // End of namespace Draci
 
 #endif // DRACI_SOUND_H


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list