[Scummvm-cvs-logs] CVS: scummvm/sword2 resman.cpp,1.91,1.92 sound.cpp,1.44,1.45 sound.h,1.8,1.9 sword2.h,1.60,1.61

Torbj?rn Andersson eriktorbjorn at users.sourceforge.net
Sat May 1 03:43:03 CEST 2004


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

Modified Files:
	resman.cpp sound.cpp sound.h sword2.h 
Log Message:
Simplified the handling of sound effects. It's not necessary for the driver
to keep its own copy of the sound data. It could be even further simplified
(I don't really see any reason for having two different sound queues), but
I seem to have reached a point of stability here and I don't want to jinx
it by making further changes yet.


Index: resman.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/resman.cpp,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- resman.cpp	23 Apr 2004 11:36:06 -0000	1.91
+++ resman.cpp	1 May 2004 10:42:16 -0000	1.92
@@ -40,8 +40,9 @@
 //      is located in and the number within the cluster
 
 // If 0, resouces are expelled immediately when they are closed. At the moment
-// this causes the game to crash, which seems like a bug to me. In fact, it
-// could be a clue to the mysterious and infrequent crashes...
+// this causes the sound queue to run out of slots. My only theory is that it's
+// a script that gets reloaded over and over. That'd clear its local variables
+// which I guess may cause it to set up the sounds over and over.
 
 #define CACHE_CLUSTERS 1
 
@@ -768,6 +769,12 @@
 void ResourceManager::killAll(bool wantInfo) {
 	int nuked = 0;
 
+	// We need to clear the FX queue, because otherwise the sound system
+	// will still believe that the sound resources are in memory, and that
+	// it's ok to close them.
+
+	_vm->clearFxQueue();
+
 	for (uint i = 0; i < _totalResFiles; i++) {
 		// Don't nuke the global variables or the player object!
 		if (i == 1 || i == CUR_PLAYER_ID)

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sound.cpp,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- sound.cpp	28 Apr 2004 11:47:19 -0000	1.44
+++ sound.cpp	1 May 2004 10:42:18 -0000	1.45
@@ -38,94 +38,100 @@
 
 namespace Sword2 {
 
+struct FxQueueEntry {
+	uint32 resource;	// resource id of sample
+	byte *data;		// pointer to WAV data
+	uint16 delay;		// cycles to wait before playing (or 'random chance' if FX_RANDOM)
+	uint8 volume;		// 0..16
+	int8 pan;		// -16..16
+	uint8 type;		// FX_SPOT, FX_RANDOM or FX_LOOP
+};
+
+// FIXME: Should be in one of the classes, I guess...
+
+static FxQueueEntry fxQueue[FXQ_LENGTH];
+
 /**
- * Initialise the fxq by clearing all the entries.
+ * Initialise the FX queue by clearing all the entries. This is only used at
+ * the start of the game. Later when we need to clear the queue we must also
+ * stop the sound and close the resource.
  */
 
 void Sword2Engine::initFxQueue(void) {
 	for (int i = 0; i < FXQ_LENGTH; i++)
-		_fxQueue[i].resource = 0;
+		fxQueue[i].resource = 0;
 }
 
 /**
- * Process the fx queue once every game cycle
+ * Stop all sounds, close their resources and clear the FX queue.
+ */
+
+void Sword2Engine::clearFxQueue(void) {
+	for (int i = 0; i < FXQ_LENGTH; i++) {
+		if (fxQueue[i].resource) {
+			_sound->stopFx(i + 1);
+			_resman->closeResource(fxQueue[i].resource);
+			fxQueue[i].resource = 0;
+		}
+	}
+}
+
+/**
+ * Process the FX queue once every game cycle
  */
 
 void Sword2Engine::processFxQueue(void) {
 	for (int i = 0; i < FXQ_LENGTH; i++) {
-		if (!_fxQueue[i].resource)
+		if (!fxQueue[i].resource)
 			continue;
 
-		switch (_fxQueue[i].type) {
+		switch (fxQueue[i].type) {
 		case FX_RANDOM:
 			// 1 in 'delay' chance of this fx occurring
-			if (_rnd.getRandomNumber(_fxQueue[i].delay) == 0)
+			if (_rnd.getRandomNumber(fxQueue[i].delay) == 0)
 				triggerFx(i);
 			break;
 		case FX_SPOT:
-			if (_fxQueue[i].delay)
-				_fxQueue[i].delay--;
+			if (fxQueue[i].delay)
+				fxQueue[i].delay--;
 			else {
 				triggerFx(i);
-				_fxQueue[i].type = FX_SPOT2;
+				fxQueue[i].type = FX_SPOT2;
 			}
 			break;
+		case FX_LOOP:
+			triggerFx(i);
+			fxQueue[i].type = FX_LOOPING;
+			break;
 		case FX_SPOT2:
-			// Once the Fx has finished remove it from the queue.
+			// Once the FX has finished remove it from the queue.
 			if (!_sound->isFxPlaying(i + 1)) {
-				_fxQueue[i].resource = 0;
-				_sound->closeFx(i + 1);
+				_sound->stopFx(i + 1);
+				_resman->closeResource(fxQueue[i].resource);
+				fxQueue[i].resource = 0;
 			}
 			break;
+		case FX_LOOPING:
+			// Once the looped FX has started we can ignore it,
+			// but we can't close it since the WAV data is in use.
+			break;
 		}
 	}
 }
 
-void Sword2Engine::triggerFx(uint8 j) {
-	byte *data;
-	int32 id;
-	uint32 rv;
-
-	id = (uint32) j + 1;	// because 0 is not a valid id
-
-	if (_fxQueue[j].type == FX_SPOT) {
-		// load in the sample
-		data = _resman->openResource(_fxQueue[j].resource);
-		data += sizeof(StandardHeader);
-		// wav data gets copied to sound memory
-		rv = _sound->playFx(id, data, _fxQueue[j].volume, _fxQueue[j].pan, RDSE_FXSPOT);
-		// release the sample
-		_resman->closeResource(_fxQueue[j].resource);
-	} else {
-		// random & looped fx are already loaded into sound memory
-		// by fnPlayFx()
-		// - to be referenced by 'j', so pass NULL data
+void Sword2Engine::triggerFx(uint8 i) {
+	int type;
 
-		if (_fxQueue[j].type == FX_RANDOM) {
-			// Not looped
-			rv = _sound->playFx(id, NULL, _fxQueue[j].volume, _fxQueue[j].pan, RDSE_FXSPOT);
-		} else {
-			// Looped
-			rv = _sound->playFx(id, NULL, _fxQueue[j].volume, _fxQueue[j].pan, RDSE_FXLOOP);
-		}
-	}
+	if (fxQueue[i].type == FX_LOOP)
+		type = RDSE_FXLOOP;
+	else
+		type = RDSE_FXSPOT;
 
+	uint32 rv = _sound->playFx(i + 1, fxQueue[i].data, fxQueue[i].volume, fxQueue[i].pan, type);
 	if (rv)
 		debug(5, "SFX ERROR: playFx() returned %.8x", rv);
 }
 
-/**
- * Stop all looped & random fx and clear the entire queue
- */
-
-void Sword2Engine::clearFxQueue(void) {
-	// stop all fx & remove the samples from sound memory
-	_sound->clearAllFx();
-
-	// clean out the queue
-	initFxQueue();
-}
-
 void Sword2Engine::killMusic(void) {
 	_loopingMusicId = 0;		// clear the 'looping' flag
 	_sound->stopMusic();
@@ -159,15 +165,6 @@
 	//		.
 	//		fnStopFx (fx_water);
 
-	uint8 j = 0;
-	byte *data;
-	uint32 id;
-	uint32 rv;
-
-#ifdef _SWORD2_DEBUG
-	StandardHeader *header;
-#endif
-
 	if (_vm->_wantSfxDebug) {
 		char type[10];
 
@@ -191,76 +188,46 @@
 		debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->fetchObjectName(params[0], buf), params[3], params[4], params[2], type);
 	}
 
-	while (j < FXQ_LENGTH && _vm->_fxQueue[j].resource != 0)
-		j++;
-
-	if (j == FXQ_LENGTH)
-		return IR_CONT;
+	int i;
 
-	_vm->_fxQueue[j].resource = params[0];	// wav resource id
-	_vm->_fxQueue[j].type = params[1];	// FX_SPOT, FX_LOOP or FX_RANDOM
+	// Find a free slot in the FX queue
 
-	if (_vm->_fxQueue[j].type == FX_RANDOM) {
-		// 'delay' param is the intended average no. seconds between
-		// playing this effect
-		_vm->_fxQueue[j].delay = params[2] * 12;
-	} else {
-		// FX_SPOT or FX_LOOP:
-		//  'delay' is no. frames to wait before playing
-		_vm->_fxQueue[j].delay = params[2];
+	for (i = 0; i < FXQ_LENGTH; i++) {
+		if (!fxQueue[i].resource)
+			break;
 	}
 
-	_vm->_fxQueue[j].volume = params[3];	// 0..16
-	_vm->_fxQueue[j].pan = params[4];	// -16..16
-
-	if (_vm->_fxQueue[j].type == FX_SPOT) {
-		// "pre-load" the sample; this gets it into memory
-		data = _vm->_resman->openResource(_vm->_fxQueue[j].resource);
-
-#ifdef _SWORD2_DEBUG
-		header = (StandardHeader *) data;
-		if (header->fileType != WAV_FILE)
-			error("fnPlayFx given invalid resource");
-#endif
-
-		// but then releases it to "age" out if the space is needed
-		_vm->_resman->closeResource(_vm->_fxQueue[j].resource);
-	} else {
-		// random & looped fx
-
-		id = (uint32) j + 1;	// because 0 is not a valid id
-
-		// load in the sample
-		data = _vm->_resman->openResource(_vm->_fxQueue[j].resource);
+	if (i == FXQ_LENGTH) {
+		warning("No free slot in FX queue");
+		return IR_CONT;
+	}
 
-#ifdef _SWORD2_DEBUG
-		header = (StandardHeader *) data;
-		if (header->fileType != WAV_FILE)
-			error("fnPlayFx given invalid resource");
-#endif
+	fxQueue[i].resource = params[0];
+	fxQueue[i].type = params[1];
+	fxQueue[i].delay = params[2];
 
-		data += sizeof(StandardHeader);
+	if (fxQueue[i].type == FX_RANDOM) {
+		// For spot effects and loops the dela is the number of frames
+		// to wait. For random effects, however, it's the average
+		// number of seconds between playing the sound, so we have to
+		// multiply by the frame rate.
+		fxQueue[i].delay *= 12;
+	}
 
-		// copy it to sound memory, using position in queue as 'id'
-		rv = _vm->_sound->openFx(id, data);
+	fxQueue[i].volume = params[3];
+	fxQueue[i].pan = params[4];
 
-		if (rv)
-			debug(5, "SFX ERROR: openFx() returned %.8x", rv);
+	byte *data = _vm->_resman->openResource(params[0]);
+	StandardHeader *header = (StandardHeader *) data;
 
-		// release the sample
-		_vm->_resman->closeResource(_vm->_fxQueue[j].resource);
-	}
+	assert(header->fileType == WAV_FILE);
 
-	if (_vm->_fxQueue[j].type == FX_LOOP) {
-		// play now, rather than in processFxQueue where it was
-		// getting played again & again!
-		_vm->triggerFx(j);
-	}
+	fxQueue[i].data = data + sizeof(StandardHeader);
 
-	// in case we want to call fnStopFx() later, to kill this fx
-	// (mainly for FX_LOOP & FX_RANDOM)
+	// Keep track of the index in the loop so that fnStopFx() can be used
+	// later to kill this sound. Mainly for FX_LOOP and FX_RANDOM.
 
-	_scriptVars[RESULT] = j;
+	_scriptVars[RESULT] = i;
 	return IR_CONT;
 }
 
@@ -270,7 +237,7 @@
 }
 
 /**
- * Alter the volume and pan of a currently playing fx
+ * Alter the volume and pan of a currently playing FX
  */
 
 int32 Logic::fnSetFxVolAndPan(int32 *params) {
@@ -281,14 +248,12 @@
 
 	debug(5, "fnSetFxVolAndPan(%d, %d, %d)", params[0], params[1], params[2]);
 
-	// setFxIdVolumePan(int32 id, uint8 vol, uint8 pan);
-	// driver fx_id is 1 + <pos in queue>
-	_vm->_sound->setFxIdVolumePan(1 + params[0], params[1], params[2]);
+	_vm->_sound->setFxIdVolumePan(params[0] + 1, params[1], params[2]);
 	return IR_CONT;
 }
 
 /**
- * Alter the volume of a currently playing fx
+ * Alter the volume of a currently playing FX
  */
 
 int32 Logic::fnSetFxVol(int32 *params) {
@@ -296,41 +261,33 @@
 	//		  fnPlayFx
 	//		1 new volume (0..16)
 
-	// SetFxIdVolume(int32 id, uint8 vol);
-	_vm->_sound->setFxIdVolume(1 + params[0], params[1]);
+	_vm->_sound->setFxIdVolume(params[0] + 1, params[1]);
 	return IR_CONT;
 }
 
 int32 Logic::fnStopFx(int32 *params) {
 	// params:	0 position in queue
 
-	// This will stop looped & random fx instantly, and remove the fx
-	// from the queue. So although it doesn't stop spot fx, it will
-	// remove them from the queue if they haven't yet played
-
-	uint8 j = (uint8) params[0];
-	uint32 id;
-	uint32 rv;
-
-	if (_vm->_fxQueue[j].type == FX_RANDOM || _vm->_fxQueue[j].type == FX_LOOP) {
-		id = (uint32) j + 1;		// because 0 is not a valid id
+	int32 i = params[0];
+	uint32 rv = _vm->_sound->stopFx(i + 1);
 
-		// stop fx & remove sample from sound memory
-		rv = _vm->_sound->closeFx(id);
+	if (rv)
+		debug(5, "SFX ERROR: closeFx() returned %.8x", rv);
 
-		if (rv)
-			debug(5, "SFX ERROR: closeFx() returned %.8x", rv);
+	// Remove from queue
+	if (fxQueue[i].resource) {
+		_vm->_resman->closeResource(fxQueue[i].resource);
+		fxQueue[i].resource = 0;
 	}
 
-	// remove from queue
-	_vm->_fxQueue[j].resource = 0;
-
 	return IR_CONT;
 }
 
-int32 Logic::fnStopAllFx(int32 *params) {
-	// Stops all looped & random fx and clears the entire queue
+/**
+ * Stops all FX and clears the entire FX queue.
+ */
 
+int32 Logic::fnStopAllFx(int32 *params) {
 	// params:	none
 
 	_vm->clearFxQueue();

Index: sound.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sound.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- sound.h	6 Jan 2004 13:44:17 -0000	1.8
+++ sound.h	1 May 2004 10:42:22 -0000	1.9
@@ -38,10 +38,14 @@
 // fx types
 
 enum {
+	// These three types correspond to types set by the scripts
 	FX_SPOT		= 0,
 	FX_LOOP		= 1,
 	FX_RANDOM	= 2,
-	FX_SPOT2	= 3
+
+	// These are used for FX queue bookkeeping
+	FX_SPOT2	= 3,
+	FX_LOOPING	= 4
 };
 
 } // End of namespace Sword2

Index: sword2.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sword2.h,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- sword2.h	28 Apr 2004 11:47:19 -0000	1.60
+++ sword2.h	1 May 2004 10:42:22 -0000	1.61
@@ -321,16 +321,6 @@
 
 	void setScrolling(void);
 
-	struct FxQueueEntry {
-		uint32 resource;	// resource id of sample
-		uint16 delay;		// cycles to wait before playing (or 'random chance' if FX_RANDOM)
-		uint8 volume;		// 0..16
-		int8 pan;		// -16..16
-		uint8 type;		// FX_SPOT, FX_RANDOM or FX_LOOP
-	};
-
-	FxQueueEntry _fxQueue[FXQ_LENGTH];
-
 	// used to store id of tunes that loop, for save & restore
 	uint32 _loopingMusicId;
 





More information about the Scummvm-git-logs mailing list