[Scummvm-cvs-logs] CVS: scummvm/sword2/driver animation.cpp,1.51,1.52 animation.h,1.32,1.33 d_sound.cpp,1.137,1.138 d_sound.h,1.61,NONE

Torbjörn Andersson eriktorbjorn at users.sourceforge.net
Fri Jan 28 09:45:57 CET 2005


Update of /cvsroot/scummvm/scummvm/sword2/driver
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18982/driver

Modified Files:
	animation.cpp animation.h d_sound.cpp 
Removed Files:
	d_sound.h 
Log Message:
Began what I hope is the final major restructuring of the BS2 engine.

In this first step, I have moved all opcode functions into functions.cpp,
instead of having them scattered all over the place.

To get things to compile again, I had to rewrite the overly complicated
sound effects handling. It's much simpler now.

The next step will be to move any non-trivial code out of the opcode
functions and into the appropriate object. This, I hope, will make it
easier to create well-separated objects, instead of the current mess.

I also want to tear down the artificial boundary between the main directory
and the "driver" directory. We already have a cross-platform layer; there's
no need to have yet another one. (Actually, the rewriting of the sound
effects code took one first step in this direction.)

At the final stage, I'd like to get rid of the "drivers" directory
completely, but I'll probably need some help with that if I want to
preserve the CVS history of the code.

Things will probably be a bit bumpy along the way, but I seem to have
reached a point of relative stability again, which is why I'm commiting
this now.


Index: animation.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/animation.cpp,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- animation.cpp	17 Jan 2005 10:57:14 -0000	1.51
+++ animation.cpp	28 Jan 2005 16:33:13 -0000	1.52
@@ -28,9 +28,10 @@
 
 #include "sword2/sword2.h"
 #include "sword2/maketext.h"
+#include "sword2/resman.h"
+#include "sword2/sound.h"
 #include "sword2/driver/animation.h"
 #include "sword2/driver/d_draw.h"
-#include "sword2/driver/d_sound.h"
 #include "sword2/driver/menu.h"
 #include "sword2/driver/render.h"
 
@@ -43,7 +44,6 @@
 AnimationState::~AnimationState() {
 }
 
-
 #ifdef BACKEND_8BIT
 
 void AnimationState::setPalette(byte *pal) {
@@ -168,12 +168,63 @@
  * @param musicOut lead-out music
  */
 
-int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], byte *musicOut, uint32 musicOutLen) {
+int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], int32 leadInRes, int32 leadOutRes) {
+	PlayingSoundHandle leadInHandle;
+
 	// This happens if the user quits during the "eye" smacker
 	if (_vm->_quit)
 		return RD_OK;
 
+	if (leadInRes) {
+		byte *leadIn = _vm->_resman->openResource(leadInRes);
+		uint32 leadInLen = _vm->_resman->fetchLen(leadInRes) - sizeof(StandardHeader);
+		StandardHeader *header = (StandardHeader *) leadIn;
+
+		assert(header->fileType == WAV_FILE);
+
+		leadIn += sizeof(StandardHeader);
+
+		_vm->_sound->playFx(&leadInHandle, leadIn, leadInLen, SoundMixer::kMaxChannelVolume, 0, false, SoundMixer::kMusicAudioDataType);
+	}
+
+	byte *leadOut = NULL;
+	uint32 leadOutLen = 0;
+
+	if (leadOutRes) {
+		leadOut = _vm->_resman->openResource(leadOutRes);
+		leadOutLen = _vm->_resman->fetchLen(leadOutRes) - sizeof(StandardHeader);
+		StandardHeader *header = (StandardHeader *) leadOut;
+
+		assert(header->fileType == WAV_FILE);
+
+		leadOut += sizeof(StandardHeader);
+	}
+
 #ifdef USE_MPEG2
+	playMPEG(filename, text, leadOut, leadOutLen);
+#else
+	// No MPEG2? Use the old 'Narration Only' hack
+	playDummy(filename, text, leadOut);
+#endif
+
+	_vm->_mixer->stopHandle(leadInHandle);
+
+	// Wait for the lead-out to stop, if there is any.
+	while (_leadOutHandle.isActive()) {
+		_vm->_graphics->updateDisplay();
+		_vm->_system->delayMillis(30);
+	}
+
+	if (leadInRes)
+		_vm->_resman->closeResource(leadInRes);
+
+	if (leadOutRes)
+		_vm->_resman->closeResource(leadOutRes);
+
+	return RD_OK;
+}
+
+void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen) {
 	uint frameCounter = 0, textCounter = 0;
 	PlayingSoundHandle handle;
 	bool skipCutscene = false, textVisible = false;
@@ -188,8 +239,8 @@
 	if (!anim->init(filename)) {
 		delete anim;
 		// Missing Files? Use the old 'Narration Only' hack
-		playDummy(filename, text, musicOut, musicOutLen);
-		return RD_OK;
+		playDummy(filename, text, leadOut, leadOutLen);
+		return;
 	}
 
 #ifndef BACKEND_8BIT
@@ -249,11 +300,10 @@
 		}
 
 		anim->updateScreen();
-
 		frameCounter++;
 
-		if (frameCounter == leadOutFrame && musicOut)
-			_vm->_sound->playFx(0, musicOutLen, musicOut, 0, 0, RDSE_FXLEADOUT);
+		if (frameCounter == leadOutFrame && leadOut)
+			_vm->_sound->playFx(&_leadOutHandle, leadOut, leadOutLen, SoundMixer::kMaxChannelVolume, 0, false, SoundMixer::kMusicAudioDataType);
 
 		OSystem::Event event;
 		while (_sys->pollEvent(event)) {
@@ -299,10 +349,9 @@
 
 	anim->updateScreen();
 
-	// Wait for the voice to stop playing. This is to make sure
-	// that we don't cut off the speech in mid-sentence, and - even
-	// more importantly - that we don't free the sound buffer while
-	// it's in use.
+	// Wait for the voice to stop playing. This is to make sure that we
+	// don't cut off the speech in mid-sentence, and - even more
+	// importantly - that we don't free the sound buffer while it's in use.
 
 	if (skipCutscene)
 		_snd->stopHandle(handle);
@@ -313,30 +362,12 @@
 	}
 
 	// Clear the screen again
-
 	anim->clearScreen();
 	anim->updateScreen();
 
 	_vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
 
 	delete anim;
-
-	// Wait for the lead-out to stop, if there is any.
-	_vm->_sound->waitForLeadOut();
-
-	// Lead-in and lead-out music are, as far as I can tell, only used for
-	// the animated cut-scenes, so this seems like a good place to close
-	// both of them.
-
-	_vm->_sound->stopFx(-1);
-	_vm->_sound->stopFx(-2);
-
-	return RD_OK;
-#else
-	// No MPEG2? Use the old 'Narration Only' hack
-	playDummy(filename, text, musicOut, musicOutLen);
-	return RD_OK;
-#endif
 }
 
 /**
@@ -344,161 +375,152 @@
  * are missing.
  */
 
-int32 MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte *musicOut, uint32 musicOutLen) {
+void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen) {
+	if (!text)
+		return;
+
 	int frameCounter = 0, textCounter = 0;
-	if (text) {
-		byte oldPal[256 * 4];
-		byte tmpPal[256 * 4];
 
-		_vm->_graphics->clearScene();
+	byte oldPal[256 * 4];
+	byte tmpPal[256 * 4];
 
-		// HACK: Draw instructions
-		//
-		// I'm using the the menu area, because that's unlikely to be
-		// touched by anything else during the cutscene.
+	_vm->_graphics->clearScene();
 
-		memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
+	// HACK: Draw instructions
+	//
+	// I'm using the the menu area, because that's unlikely to be touched
+	// by anything else during the cutscene.
 
-		byte *data;
+	memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
 
-		// Russian version substituted latin characters with cyrillic. That's why
-		// it renders completely unreadable with default message
-		if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) {
-			byte msg[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
-			data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
-		} else {
-			// TODO: Translate message to other languages?
+	byte *data;
+
+	// Russian version substituted latin characters with cyrillic. That's
+	// why it renders completely unreadable with default message
+	if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) {
+		byte msg[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
+		data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
+	} else {
+		// TODO: Translate message to other languages?
 #ifdef USE_MPEG2
-			byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
+		byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
 #else
-			byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 support";
+		byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 support";
 #endif
-			data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
-		}
 
-		FrameHeader *frame = (FrameHeader *) data;
-		SpriteInfo msgSprite;
-		byte *msgSurface;
+		data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
+	}
 
-		msgSprite.x = _vm->_graphics->_screenWide / 2 - frame->width / 2;
-		msgSprite.y = RDMENU_MENUDEEP / 2 - frame->height / 2;
-		msgSprite.w = frame->width;
-		msgSprite.h = frame->height;
-		msgSprite.type = RDSPR_NOCOMPRESSION;
-		msgSprite.data = data + sizeof(FrameHeader);
+	FrameHeader *frame = (FrameHeader *) data;
+	SpriteInfo msgSprite;
+	byte *msgSurface;
 
-		_vm->_graphics->createSurface(&msgSprite, &msgSurface);
-		_vm->_graphics->drawSurface(&msgSprite, msgSurface);
-		_vm->_graphics->deleteSurface(msgSurface);
-		free(data);
+	msgSprite.x = _vm->_graphics->_screenWide / 2 - frame->width / 2;
+	msgSprite.y = RDMENU_MENUDEEP / 2 - frame->height / 2;
+	msgSprite.w = frame->width;
+	msgSprite.h = frame->height;
+	msgSprite.type = RDSPR_NOCOMPRESSION;
+	msgSprite.data = data + sizeof(FrameHeader);
 
-		// In case the cutscene has a long lead-in, start just before
-		// the first line of text.
+	_vm->_graphics->createSurface(&msgSprite, &msgSurface);
+	_vm->_graphics->drawSurface(&msgSprite, msgSurface);
+	_vm->_graphics->deleteSurface(msgSurface);
 
-		frameCounter = text[0]->startFrame - 12;
+	free(data);
 
-		// Fake a palette that will hopefully make the text visible.
-		// In the opening cutscene it seems to use colours 1 (black?)
-		// and 255 (white?).
+	// In case the cutscene has a long lead-in, start just before the first
+	// line of text.
 
-		memcpy(oldPal, _vm->_graphics->_palette, sizeof(oldPal));
-		memset(tmpPal, 0, sizeof(tmpPal));
-		tmpPal[255 * 4 + 0] = 255;
-		tmpPal[255 * 4 + 1] = 255;
-		tmpPal[255 * 4 + 2] = 255;
-		_vm->_graphics->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
+	frameCounter = text[0]->startFrame - 12;
 
-		PlayingSoundHandle handle;
+	// Fake a palette that will hopefully make the text visible. In the
+	// opening cutscene it seems to use colours 1 (black) and 255 (white).
 
-		bool skipCutscene = false;
+	memcpy(oldPal, _vm->_graphics->_palette, sizeof(oldPal));
+	memset(tmpPal, 0, sizeof(tmpPal));
+	tmpPal[255 * 4 + 0] = 255;
+	tmpPal[255 * 4 + 1] = 255;
+	tmpPal[255 * 4 + 2] = 255;
+	_vm->_graphics->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
 
-		uint32 flags = SoundMixer::FLAG_16BITS;
+	PlayingSoundHandle handle;
+
+	bool skipCutscene = false;
+
+	uint32 flags = SoundMixer::FLAG_16BITS;
 
 #ifndef SCUMM_BIG_ENDIAN
-		flags |= SoundMixer::FLAG_LITTLE_ENDIAN;
+	flags |= SoundMixer::FLAG_LITTLE_ENDIAN;
 #endif
 
-		while (1) {
-			if (!text[textCounter])
-				break;
+	while (1) {
+		if (!text[textCounter])
+			break;
 
-			if (frameCounter == text[textCounter]->startFrame) {
-				_vm->_graphics->clearScene();
-				openTextObject(text[textCounter]);
-				drawTextObject(NULL, text[textCounter]);
-				if (text[textCounter]->speech) {
-					_snd->playRaw(&handle, text[textCounter]->speech, text[textCounter]->speechBufferSize, 22050, flags);
-				}
-			}
-			if (frameCounter == text[textCounter]->endFrame) {
-				closeTextObject(text[textCounter]);
-				_vm->_graphics->clearScene();
-				_vm->_graphics->setNeedFullRedraw();
-				textCounter++;
+		if (frameCounter == text[textCounter]->startFrame) {
+			_vm->_graphics->clearScene();
+			openTextObject(text[textCounter]);
+			drawTextObject(NULL, text[textCounter]);
+			if (text[textCounter]->speech) {
+				_snd->playRaw(&handle, text[textCounter]->speech, text[textCounter]->speechBufferSize, 22050, flags);
 			}
+		}
 
-			frameCounter++;
-
-			_vm->_graphics->updateDisplay();
-
-			KeyboardEvent *ke = _vm->keyboardEvent();
+		if (frameCounter == text[textCounter]->endFrame) {
+			closeTextObject(text[textCounter]);
+			_vm->_graphics->clearScene();
+			_vm->_graphics->setNeedFullRedraw();
+			textCounter++;
+		}
 
-			if ((ke && ke->keycode == 27) || _vm->_quit) {
-				_snd->stopHandle(handle);
-				skipCutscene = true;
-				break;
-			}
+		frameCounter++;
+		_vm->_graphics->updateDisplay();
 
-			// Simulate ~12 frames per second. I don't know what
-			// frame rate the original movies had, or even if it
-			// was constant, but this seems to work reasonably.
+		KeyboardEvent *ke = _vm->keyboardEvent();
 
-			_sys->delayMillis(90);
+		if ((ke && ke->keycode == 27) || _vm->_quit) {
+			_snd->stopHandle(handle);
+			skipCutscene = true;
+			break;
 		}
 
-		// Wait for the voice to stop playing. This is to make sure
-		// that we don't cut off the speech in mid-sentence, and - even
-		// more importantly - that we don't free the sound buffer while
-		// it's in use.
-
-		while (handle.isActive()) {
-			_vm->_graphics->updateDisplay(false);
-			_sys->delayMillis(100);
-		}
+		// Simulate ~12 frames per second. I don't know what frame rate
+		// the original movies had, or even if it was constant, but
+		// this seems to work reasonably.
 
-		closeTextObject(text[textCounter]);
+		_sys->delayMillis(90);
+	}
 
-		_vm->_graphics->clearScene();
-		_vm->_graphics->setNeedFullRedraw();
+	// Wait for the voice to stop playing. This is to make sure that we
+	// don't cut off the speech in mid-sentence, and - even more
+	// importantly - that we don't free the sound buffer while it's in use.
 
-		// HACK: Remove the instructions created above
-		Common::Rect r;
+	while (handle.isActive()) {
+		_vm->_graphics->updateDisplay(false);
+		_sys->delayMillis(100);
+	}
 
-		memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
-		r.left = r.top = 0;
-		r.right = _vm->_graphics->_screenWide;
-		r.bottom = MENUDEEP;
-		_vm->_graphics->updateRect(&r);
+	closeTextObject(text[textCounter]);
 
-		// FIXME: For now, only play the lead-out music for cutscenes
-		// that have subtitles.
+	_vm->_graphics->clearScene();
+	_vm->_graphics->setNeedFullRedraw();
 
-		if (!skipCutscene && musicOut) {
-			_vm->_sound->playFx(0, musicOutLen, musicOut, 0, 0, RDSE_FXLEADOUT);
-			_vm->_sound->waitForLeadOut();
-		}
+	// HACK: Remove the instructions created above
+	Common::Rect r;
 
-		_vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
-	}
+	memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
+	r.left = r.top = 0;
+	r.right = _vm->_graphics->_screenWide;
+	r.bottom = MENUDEEP;
+	_vm->_graphics->updateRect(&r);
 
-	// Lead-in and lead-out music are, as far as I can tell, only used for
-	// the animated cut-scenes, so this seems like a good place to close
-	// both of them.
+	// FIXME: For now, only play the lead-out music for cutscenes that have
+	// subtitles.
 
-	_vm->_sound->stopFx(-1);
-	_vm->_sound->stopFx(-2);
+	if (!skipCutscene && leadOut)
+		_vm->_sound->playFx(&_leadOutHandle, leadOut, leadOutLen, SoundMixer::kMaxChannelVolume, 0, false, SoundMixer::kMusicAudioDataType);
 
-	return RD_OK;
+	_vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
 }
 
 } // End of namespace Sword2

Index: animation.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/animation.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- animation.h	17 Jan 2005 10:57:14 -0000	1.32
+++ animation.h	28 Jan 2005 16:33:13 -0000	1.33
@@ -65,17 +65,20 @@
 
 	byte *_textSurface;
 
+	PlayingSoundHandle _leadOutHandle;
+
 	static struct MovieInfo _movies[];
 
 	void openTextObject(MovieTextObject *obj);
 	void closeTextObject(MovieTextObject *obj);
 	void drawTextObject(AnimationState *anim, MovieTextObject *obj);
 
-	int32 playDummy(const char *filename, MovieTextObject *text[], byte *musicOut, uint32 musicOutLen);
+	void playMPEG(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen);
+	void playDummy(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen);
 
 public:
 	MoviePlayer(Sword2Engine *vm);
-	int32 play(const char *filename, MovieTextObject *text[], byte *musicOut, uint32 musicOutLen);
+	int32 play(const char *filename, MovieTextObject *text[], int32 leadInRes, int32 leadOutRes);
 };
 
 } // End of namespace Sword2

Index: d_sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/d_sound.cpp,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -d -r1.137 -r1.138
--- d_sound.cpp	17 Jan 2005 10:57:14 -0000	1.137
+++ d_sound.cpp	28 Jan 2005 16:33:13 -0000	1.138
@@ -34,8 +34,8 @@
 #include "sound/wave.h"
 #include "sword2/sword2.h"
 #include "sword2/resman.h"
+#include "sword2/sound.h"
 #include "sword2/driver/d_draw.h"
-#include "sword2/driver/d_sound.h"
 
 namespace Sword2 {
 
@@ -138,8 +138,6 @@
 	}
 }
 
-#define BUFFER_SIZE 4096
-
 // ----------------------------------------------------------------------------
 // Custom AudioStream class to handle Broken Sword II's audio compression.
 // ----------------------------------------------------------------------------
@@ -148,32 +146,6 @@
 #define GetCompressedSign(n)       (((n) >> 3) & 1)
 #define GetCompressedAmplitude(n)  ((n) & 7)
 
-class CLUInputStream : public AudioStream {
-private:
-	File *_file;
-	bool _firstTime;
-	uint32 _file_pos;
-	uint32 _end_pos;
-	int16 _outbuf[BUFFER_SIZE];
-	byte _inbuf[BUFFER_SIZE];
-	const int16 *_bufferEnd;
-	const int16 *_pos;
-
-	uint16 _prev;
-
-	void refill();
-	inline bool eosIntern() const;
-public:
-	CLUInputStream(File *file, int size);
-	~CLUInputStream();
-
-	int readBuffer(int16 *buffer, const int numSamples);
-
-	bool endOfData() const	{ return eosIntern(); }
-	bool isStereo() const	{ return false; }
-	int getRate() const	{ return 22050; }
-};
-
 CLUInputStream::CLUInputStream(File *file, int size)
 	: _file(file), _firstTime(true), _bufferEnd(_outbuf + BUFFER_SIZE) {
 
@@ -191,10 +163,6 @@
 	_file->decRef();
 }
 
-inline bool CLUInputStream::eosIntern() const {
-	return _pos >= _bufferEnd;
-}
-
 int CLUInputStream::readBuffer(int16 *buffer, const int numSamples) {
 	int samples = 0;
 	while (samples < numSamples && !eosIntern()) {
@@ -260,44 +228,6 @@
 // The length of a fade-in/out, in milliseconds.
 #define FADE_LENGTH 3000
 
-class MusicInputStream : public AudioStream {
-private:
-	int _cd;
-	uint32 _musicId;
-	AudioStream *_decoder;
-	int16 _buffer[BUFFER_SIZE];
-	const int16 *_bufferEnd;
-	const int16 *_pos;
-	bool _remove;
-	uint32 _numSamples;
-	uint32 _samplesLeft;
-	bool _looping;
-	int32 _fading;
-	int32 _fadeSamples;
-	bool _paused;
-
-	void refill();
-	inline bool eosIntern() const;
-public:
-	MusicInputStream(int cd, uint32 musicId, bool looping);
-	~MusicInputStream();
-
-	int readBuffer(int16 *buffer, const int numSamples);
-
-	bool endOfData() const	{ return eosIntern(); }
-	bool isStereo() const	{ return _decoder->isStereo(); }
-	int getRate() const	{ return _decoder->getRate(); }
-
-	void fadeUp();
-	void fadeDown();
-
-	bool isReady()		{ return _decoder != NULL; }
-	int32 isFading()	{ return _fading; }
-
-	bool readyToRemove();
-	int32 getTimeRemaining();
-};
-
 MusicInputStream::MusicInputStream(int cd, uint32 musicId, bool looping)
 	: _cd(cd), _musicId(musicId), _bufferEnd(_buffer + BUFFER_SIZE),
 	  _remove(false), _looping(looping), _fading(0) {
@@ -316,12 +246,6 @@
 	delete _decoder;
 }
 
-inline bool MusicInputStream::eosIntern() const {
-	if (_looping)
-		return false;
-	return _remove || _pos >= _bufferEnd;
-}
-
 int MusicInputStream::readBuffer(int16 *buffer, const int numSamples) {
 	if (!_decoder)
 		return 0;
@@ -462,58 +386,13 @@
 // Main sound class
 // ----------------------------------------------------------------------------
 
-Sound::Sound(Sword2Engine *vm) {
-	_vm = vm;
-	_mutex = _vm->_system->createMutex();
-
-	memset(_fx, 0, sizeof(_fx));
-
-	_soundOn = true;
-
-	_speechPaused = false;
-	_speechMuted = false;
-
-	_fxPaused = false;
-	_fxMuted = false;
-
-	_musicPaused = false;
-	_musicMuted = false;
-
-	_mixBuffer = NULL;
-	_mixBufferLen = 0;
-
-	for (int i = 0; i < MAXMUS; i++)
-		_music[i] = NULL;
-
-	_vm->_mixer->setupPremix(this, SoundMixer::kMusicAudioDataType);
-}
-
-Sound::~Sound() {
-	int i;
-
-	_vm->_mixer->setupPremix(0);
-
-	for (i = 0; i < MAXMUS; i++)
-		delete _music[i];
-
-	free(_mixBuffer);
-
-	for (i = 0; i < MAXFX; i++)
-		stopFxHandle(i);
-
-	stopSpeech();
-
-	if (_mutex)
-		_vm->_system->deleteMutex(_mutex);
-}
-
 // AudioStream API
 
 int Sound::readBuffer(int16 *buffer, const int numSamples) {
 	Common::StackLock lock(_mutex);
 	int i;
 
-	if (!_soundOn || _musicPaused)
+	if (_musicPaused)
 		return 0;
 
 	for (i = 0; i < MAXMUS; i++) {
@@ -560,60 +439,18 @@
 bool Sound::endOfData() const { return !fpMus.isOpen(); }
 int Sound::getRate() const { return 22050; }
 
-
-/**
- * This function creates the pan table.
- */
-
-void Sound::buildPanTable(bool reverse) {
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		_panTable[i] = -127 + i * 8;
-		_panTable[i + 17] = (i + 1) * 8 - 1;
-	}
-
-	_panTable[16] = 0;
-
-	if (reverse) {
-		for (i = 0; i < 33; i++)
-			_panTable[i] = -_panTable[i];
-	}
-}
-
 // ----------------------------------------------------------------------------
 // MUSIC
 // ----------------------------------------------------------------------------
 
 /**
- * Mutes/Unmutes the music.
- * @param mute If mute is false, restore the volume to the last set master
- * level. Otherwise the music is muted (volume 0).
- */
-
-void Sound::muteMusic(bool mute) {
-	_musicMuted = mute;
-}
-
-/**
- * @return the music's mute state, true if mute, false if not mute
- */
-
-bool Sound::isMusicMute(void) {
-	return _musicMuted;
-}
-
-/**
  * Stops the music dead in its tracks. Any music that is currently being
  * streamed is paused.
  */
 
-void Sound::pauseMusic(void) {
+void Sound::pauseMusic() {
 	Common::StackLock lock(_mutex);
 
-	if (!_soundOn)
-		return;
-
 	_musicPaused = true;
 }
 
@@ -621,12 +458,9 @@
  * Restarts the music from where it was stopped.
  */
 
-void Sound::unpauseMusic(void) {
+void Sound::unpauseMusic() {
 	Common::StackLock lock(_mutex);
 
-	if (!_soundOn)
-		return;
-
 	_musicPaused = false;
 }
 
@@ -634,35 +468,30 @@
  * Fades out and stops the music.
  */
 
-void Sound::stopMusic(void) {
+void Sound::stopMusic() {
 	Common::StackLock lock(_mutex);
 
+	_loopingMusicId = 0;
+
 	for (int i = 0; i < MAXMUS; i++)
 		if (_music[i])
 			_music[i]->fadeDown();
 }
 
-void Sound::waitForLeadOut(void) {
-	int i = getFxIndex(-1);
-
-	if (i == MAXFX)
-		return;
-
-	while (_fx[i]._handle.isActive()) {
-		_vm->_graphics->updateDisplay();
-		_vm->_system->delayMillis(30);
-	}
-}
-
 /**
  * Streams music from a cluster file.
  * @param musicId the id of the music to stream
  * @param looping true if the music is to loop back to the start
  * @return RD_OK or an error code
  */
-int32 Sound::streamCompMusic(uint32 musicId, bool looping) {
+int32 Sound::streamCompMusic(uint32 musicId, bool loop) {
 	Common::StackLock lock(_mutex);
 
+	if (loop)
+		_loopingMusicId = musicId;
+	else
+		_loopingMusicId = 0;
+
 	int primary = -1;
 	int secondary = -1;
 
@@ -716,7 +545,7 @@
 	if (secondary != -1)
 		_music[secondary]->fadeDown();
 
-	_music[primary] = new MusicInputStream(_vm->_resman->whichCd(), musicId, looping);
+	_music[primary] = new MusicInputStream(_vm->_resman->whichCd(), musicId, loop);
 
 	if (!_music[primary]->isReady()) {
 		delete _music[primary];
@@ -763,14 +592,6 @@
 }
 
 /**
- * @return the speech's mute state, true if mute, false if not mute
- */
-
-bool Sound::isSpeechMute(void) {
-	return _speechMuted;
-}
-
-/**
  * Stops the speech dead in its tracks.
  */
 
@@ -792,14 +613,12 @@
  * Stops the speech from playing.
  */
 
-int32 Sound::stopSpeech(void) {
-	if (!_soundOn)
-		return RD_OK;
-  
+int32 Sound::stopSpeech() {
 	if (_soundHandleSpeech.isActive()) {
 		_vm->_mixer->stopHandle(_soundHandleSpeech);
 		return RD_OK;
 	}
+
 	return RDERR_SPEECHNOTPLAYING;
 }
 
@@ -807,7 +626,7 @@
  * @return Either RDSE_SAMPLEPLAYING or RDSE_SAMPLEFINISHED
  */
 
-int32 Sound::getSpeechStatus(void) {
+int32 Sound::getSpeechStatus() {
 	return _soundHandleSpeech.isActive() ? RDSE_SAMPLEPLAYING : RDSE_SAMPLEFINISHED;
 }
 
@@ -815,7 +634,7 @@
  * Returns either RDSE_QUIET or RDSE_SPEAKING
  */
 
-int32 Sound::amISpeaking(void) {
+int32 Sound::amISpeaking() {
 	if (!_speechMuted && !_speechPaused && _soundHandleSpeech.isActive())
 		return RDSE_SPEAKING;
 
@@ -826,15 +645,15 @@
  * This function loads and decompresses a list of speech from a cluster, but
  * does not play it. This is used for cutscene voice-overs, presumably to
  * avoid having to read from more than one file on the CD during playback.
- * @param speechid the text line id used to reference the speech
+ * @param speechId the text line id used to reference the speech
  * @param buf a pointer to the buffer that will be allocated for the sound
  */
 
-uint32 Sound::preFetchCompSpeech(uint32 speechid, uint16 **buf) {
+uint32 Sound::preFetchCompSpeech(uint32 speechId, uint16 **buf) {
 	File fp;
 	uint32 numSamples;
 
-	AudioStream *input = getAudioStream(&fp, "speech", _vm->_resman->whichCd(), speechid, &numSamples);
+	AudioStream *input = getAudioStream(&fp, "speech", _vm->_resman->whichCd(), speechId, &numSamples);
 
 	*buf = NULL;
 
@@ -860,12 +679,12 @@
 /**
  * This function loads, decompresses and plays a line of speech. An error
  * occurs if speech is already playing.
- * @param speechid the text line id used to reference the speech
+ * @param speechId the text line id used to reference the speech
  * @param vol volume, 0 (minimum) to 16 (maximum)
  * @param pan panning, -16 (full left) to 16 (full right)
  */
 
-int32 Sound::playCompSpeech(uint32 speechid, uint8 vol, int8 pan) {
+int32 Sound::playCompSpeech(uint32 speechId, uint8 vol, int8 pan) {
 	if (_speechMuted)
 		return RD_OK;
 
@@ -873,7 +692,7 @@
 		return RDERR_SPEECHPLAYING;
 
 	File *fp = new File;
-	AudioStream *input = getAudioStream(fp, "speech", _vm->_resman->whichCd(), speechid, NULL);
+	AudioStream *input = getAudioStream(fp, "speech", _vm->_resman->whichCd(), speechId, NULL);
 
 	// Make the AudioStream object the sole owner of the file so that it
 	// will die along with the AudioStream when the speech has finished.
@@ -885,7 +704,10 @@
 	// Modify the volume according to the master volume
 
 	byte volume = _speechMuted ? 0 : vol * SoundMixer::kMaxChannelVolume / 16;
-	int8 p = _panTable[pan + 16];
+	int8 p = (pan * 127) / 16;
+
+	if (isReverseStereo())
+		p = -p;
 
 	// Start the speech playing
 	_vm->_mixer->playInputStream(SoundMixer::kSpeechAudioDataType, &_soundHandleSpeech, input, -1, volume, p);
@@ -897,19 +719,6 @@
 // ----------------------------------------------------------------------------
 
 /**
- * @return the index of the sound effect with the ID passed in.
- */
-
-int32 Sound::getFxIndex(int32 id) {
-	for (int i = 0; i < MAXFX; i++) {
-		if (_fx[i]._id == id)
-			return i;
-	}
-
-	return MAXFX;
-}
-
-/**
  * Mutes/Unmutes the sound effects.
  * @param mute If mute is false, restore the volume to the last set master
  * level. Otherwise the sound effects are muted (volume 0).
@@ -919,241 +728,62 @@
 	_fxMuted = mute;
 
 	// Now update the volume of any fxs playing
-	for (int i = 0; i < MAXFX; i++) {
-		if (_fx[i]._id) {
-			byte volume = mute ? 0 : _fx[i]._volume * SoundMixer::kMaxChannelVolume / 16;
-
-			_vm->_mixer->setChannelVolume(_fx[i]._handle, volume);
+	for (int i = 0; i < FXQ_LENGTH; i++) {
+		if (_fxQueue[i].resource) {
+			_vm->_mixer->setChannelVolume(_fxQueue[i].handle, mute ? 0 : _fxQueue[i].volume);
 		}
 	}
 }
 
 /**
- * @return the sound effects's mute state, true if mute, false if not mute
- */
-
-bool Sound::isFxMute(void) {
-	return _fxMuted;
-}
-
-/**
  * Sets the volume and pan of the sample which is currently playing
  * @param id the id of the sample
  * @param vol volume
  * @param pan panning
  */
 
-int32 Sound::setFxIdVolumePan(int32 id, uint8 vol, int8 pan) {
-	int32 i = getFxIndex(id);
-
-	if (i == MAXFX)
-		return RDERR_FXNOTOPEN;
-
-	if (vol > 14)
-		vol = 14;
-
-	_fx[i]._volume = vol;
-
-	if (!_fxMuted) {
-		_vm->_mixer->setChannelVolume(_fx[i]._handle, _fx[i]._volume * SoundMixer::kMaxChannelVolume / 16);
-		_vm->_mixer->setChannelBalance(_fx[i]._handle, _panTable[pan + 16]);
-	}
-
-	return RD_OK;
-}
-
-int32 Sound::setFxIdVolume(int32 id, uint8 vol) {
-	int32 i = getFxIndex(id);
-
-	if (i == MAXFX)
+int32 Sound::setFxIdVolumePan(int32 i, int vol, int pan) {
+	if (!_fxQueue[i].resource)
 		return RDERR_FXNOTOPEN;
 
-	_fx[i]._volume = vol;
-
-	if (!_fxMuted)
-		_vm->_mixer->setChannelVolume(_fx[i]._handle, vol * SoundMixer::kMaxChannelVolume / 16);
-
-	return RD_OK;
-}
+	if (vol > 16)
+		vol = 16;
 
+	_fxQueue[i].volume = (vol * SoundMixer::kMaxChannelVolume) / 16;
 
-void Sound::pauseFx(void) {
-	if (_fxPaused)
-		return;
+	if (pan != -1)
+		_fxQueue[i].pan = (pan * 127) / 16;
 
-	for (int i = 0; i < MAXFX; i++) {
-		if (_fx[i]._id) {
-			_vm->_mixer->pauseHandle(_fx[i]._handle, true);
-			_fx[i]._paused = true;
-		} else
-			_fx[i]._paused = false;
+	if (!_fxMuted && _fxQueue[i].handle.isActive()) {
+		_vm->_mixer->setChannelVolume(_fxQueue[i].handle, _fxQueue[i].volume);
+		if (pan != -1)
+			_vm->_mixer->setChannelBalance(_fxQueue[i].handle, _fxQueue[i].pan);
 	}
 
-	_fxPaused = true;
+	return RD_OK;
 }
 
-void Sound::pauseFxForSequence(void) {
+void Sound::pauseFx() {
 	if (_fxPaused)
 		return;
 
-	for (int i = 0; i < MAXFX; i++) {
-		if (_fx[i]._id && _fx[i]._id != -2) {
-			_vm->_mixer->pauseHandle(_fx[i]._handle, true);
-			_fx[i]._paused = true;
-		} else
-			_fx[i]._paused = false;
+	for (int i = 0; i < FXQ_LENGTH; i++) {
+		if (_fxQueue[i].resource)
+			_vm->_mixer->pauseHandle(_fxQueue[i].handle, true);
 	}
 
 	_fxPaused = true;
 }
 
-void Sound::unpauseFx(void) {
+void Sound::unpauseFx() {
 	if (!_fxPaused)
 		return;
 
-	for (int i = 0; i < MAXFX; i++)
-		if (_fx[i]._paused && _fx[i]._id)
-			_vm->_mixer->pauseHandle(_fx[i]._handle, false);
+	for (int i = 0; i < FXQ_LENGTH; i++)
+		if (_fxQueue[i].resource)
+			_vm->_mixer->pauseHandle(_fxQueue[i].handle, false);
 
 	_fxPaused = false;
 }
 
-bool Sound::isFxPlaying(int32 id) {
-	int i;
-
-	i = getFxIndex(id);
-	if (i == MAXFX)
-		return false;
-
-	return _fx[i]._handle.isActive();
-}
-
-/**
- * This function closes a sound effect which has been previously opened for
- * playing. Sound effects must be closed when they are finished with, otherwise
- * you will run out of sound effect buffers.
- * @param id the id of the sound to close
- */
-
-int32 Sound::stopFx(int32 id) {
-	int i;
-
-	if (!_soundOn)
-		return RD_OK;
-
-	i = getFxIndex(id);
-
-	if (i == MAXFX)
-		return RDERR_FXNOTOPEN;
-
-	stopFxHandle(i);
-	return RD_OK;
-}
-
-/**
- * This function plays a sound effect. If the effect has already been opened
- * then 'data' should be NULL, and the sound effect will simply be obtained
- * from the id passed in. If the effect has not been opened, then the WAV data
- * should be passed in 'data'. The sound effect will be closed when it has
- * finished playing.
- * @param id the sound id
- * @param data either NULL or the WAV data
- * @param vol volume, 0 (minimum) to 16 (maximum)
- * @param pan panning, -16 (full left) to 16 (full right)
- * @param type either RDSE_FXSPOT or RDSE_FXLOOP
- * @warning Zero is not a valid id
- */
-
-int32 Sound::playFx(int32 id, uint32 len, byte *data, uint8 vol, int8 pan, uint8 type) {
-	if (!_soundOn)
-		return RD_OK;
-
-	byte volume = _fxMuted ? 0 : vol * SoundMixer::kMaxChannelVolume / 16;
-	SoundMixer::SoundType soundType = SoundMixer::kSFXAudioDataType;
-
-	// All lead-ins and lead-outs I've heard are music, so we use
-	// the music volume setting for them.
-
-	if (type == RDSE_FXLEADIN || type == RDSE_FXLEADOUT) {
-		id = (type == RDSE_FXLEADIN) ? -2 : -1;
-		volume = _musicMuted ? 0 : SoundMixer::kMaxChannelVolume;
-		soundType = SoundMixer::kMusicAudioDataType;
-	}
-
-	Common::MemoryReadStream stream(data, len);
-	int rate, size;
-	byte flags;
-
-	if (!loadWAVFromStream(stream, size, rate, flags)) {
-		warning("playFx: Not a valid WAV file");
-		return RDERR_INVALIDWAV;
-	}
-
-	int32 fxi = getFxIndex(id);
-
-	if (fxi == MAXFX) {
-		// Find a free slot
-		fxi = getFxIndex(0);
-
-		if (fxi == MAXFX) {
-			warning("openFx: Running out of sound slots");
-
-			// There aren't any free sound handles available. This
-			// usually shouldn't happen, but if it does we expire
-			// the first sound effect that isn't currently playing.
-
-			for (fxi = 0; fxi < MAXFX; fxi++)
-				if (!_fx[fxi]._handle.isActive())
-					break;
-
-			// Still no dice? I give up!
-
-			if (fxi == MAXFX) {
-				warning("openFx: No free sound slots");
-				return RDERR_NOFREEBUFFERS;
-			}
-		}
-
-		_fx[fxi]._id = id;
-	}
-
-	if (_fx[fxi]._handle.isActive())
-		return RDERR_FXALREADYOPEN;
-
-	if (type == RDSE_FXLOOP)
-		flags |= SoundMixer::FLAG_LOOP;
-	else 
-		flags &= ~SoundMixer::FLAG_LOOP;
-
-	_fx[fxi]._volume = vol;
-
-	int8 p = _panTable[pan + 16];
-
-	_vm->_mixer->playRaw(&_fx[fxi]._handle, data + stream.pos(), size, rate, flags, -1, volume, p, 0, 0, soundType);
-
-	return RD_OK;
-}
-
-void Sound::stopFxHandle(int i) {
-	if (_fx[i]._id) {
-		_vm->_mixer->stopHandle(_fx[i]._handle);
-		_fx[i]._id = 0;
-		_fx[i]._paused = false;
-	}
-}
-
-/**
- * This function clears all of the sound effects which are currently open or
- * playing, irrespective of type.
- */
-
-void Sound::clearAllFx(void) {
-	if (!_soundOn)
-		return;
-
-	for (int i = 0; i < MAXFX; i++)
-		if (_fx[i]._id && _fx[i]._id != -1 && _fx[i]._id != -2)
-			stopFxHandle(i);
-}
-
 } // End of namespace Sword2

--- d_sound.h DELETED ---





More information about the Scummvm-git-logs mailing list