aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2004-05-01 10:42:23 +0000
committerTorbjörn Andersson2004-05-01 10:42:23 +0000
commitbc77ba431a7ccfc9a961df5fa8f1531e2f72fd44 (patch)
treeb6b7ebc379d756ae3f869c314666fbdf09b94b87
parente830d35a21fda5e28bcc290b37a922dbf4114224 (diff)
downloadscummvm-rg350-bc77ba431a7ccfc9a961df5fa8f1531e2f72fd44.tar.gz
scummvm-rg350-bc77ba431a7ccfc9a961df5fa8f1531e2f72fd44.tar.bz2
scummvm-rg350-bc77ba431a7ccfc9a961df5fa8f1531e2f72fd44.zip
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. svn-id: r13705
-rw-r--r--NEWS3
-rw-r--r--sword2/driver/animation.cpp8
-rw-r--r--sword2/driver/d_sound.cpp144
-rw-r--r--sword2/driver/d_sound.h7
-rw-r--r--sword2/resman.cpp11
-rw-r--r--sword2/sound.cpp245
-rw-r--r--sword2/sound.h6
-rw-r--r--sword2/sword2.h10
8 files changed, 173 insertions, 261 deletions
diff --git a/NEWS b/NEWS
index b269269ceb..ab2aabfdfc 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,8 @@ For a more comprehensive changelog for the latest experimental CVS code, see:
- ??? [TODO: Somebody of the Sword1 team please fill this in]
Sword2:
- - Simplified the memory/resource management.
+ - Simplified the memory/resource management...
+ - ...which led to simplified sound effects handling
- Various minor bugfixes.
BASS
diff --git a/sword2/driver/animation.cpp b/sword2/driver/animation.cpp
index 53dad119f5..b7d177ed84 100644
--- a/sword2/driver/animation.cpp
+++ b/sword2/driver/animation.cpp
@@ -326,8 +326,8 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], byte *mus
// the animated cut-scenes, so this seems like a good place to close
// both of them.
- _vm->_sound->closeFx(-1);
- _vm->_sound->closeFx(-2);
+ _vm->_sound->stopFx(-1);
+ _vm->_sound->stopFx(-2);
return RD_OK;
#else
@@ -478,8 +478,8 @@ int32 MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
// the animated cut-scenes, so this seems like a good place to close
// both of them.
- _vm->_sound->closeFx(-1);
- _vm->_sound->closeFx(-2);
+ _vm->_sound->stopFx(-1);
+ _vm->_sound->stopFx(-2);
return RD_OK;
}
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp
index e6b547fdae..b5cf40d9c2 100644
--- a/sword2/driver/d_sound.cpp
+++ b/sword2/driver/d_sound.cpp
@@ -1029,77 +1029,13 @@ bool Sound::isFxPlaying(int32 id) {
}
/**
- * This function opens a sound effect ready for playing. A unique id should be
- * passed in so that each effect can be referenced individually.
- * @param id the unique sound id
- * @param data the WAV data
- * @warning Zero is not a valid id
- */
-
-int32 Sound::openFx(int32 id, byte *data) {
- if (!_soundOn)
- return RD_OK;
-
- if (id == 0)
- return RDERR_INVALIDID;
-
- if (getFxIndex(id) != MAXFX)
- return RDERR_FXALREADYOPEN;
-
- // Find a free slot
- int32 fxi = getFxIndex(0);
-
- if (fxi == MAXFX) {
- warning("openFx: Running out of sound slots");
-
- // There isn't any free sound handle 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;
- _fx[fxi]._flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_LITTLE_ENDIAN;
-
- WavInfo wavInfo;
-
- if (!getWavInfo(data, &wavInfo)) {
- warning("openFx: Not a valida WAV file");
- return RDERR_INVALIDWAV;
- }
-
- if (wavInfo.channels == 2)
- _fx[fxi]._flags |= SoundMixer::FLAG_STEREO;
-
- _fx[fxi]._rate = wavInfo.rate;
- _fx[fxi]._bufSize = wavInfo.samples;
-
- // Fill the speech buffer with data
- free(_fx[fxi]._buf);
- _fx[fxi]._buf = (uint16 *) malloc(_fx[fxi]._bufSize);
- memcpy(_fx[fxi]._buf, wavInfo.data, _fx[fxi]._bufSize);
-
- return RD_OK;
-}
-
-/**
* 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::closeFx(int32 id) {
+int32 Sound::stopFx(int32 id) {
int i;
if (!_soundOn)
@@ -1133,43 +1069,69 @@ int32 Sound::playFx(int32 id, byte *data, uint8 vol, int8 pan, uint8 type) {
return RD_OK;
byte volume = _fxMuted ? 0 : vol * _fxVol;
- int8 p = _panTable[pan + 16];
- int32 i, hr;
- if (data) {
- // All lead-ins and lead-outs I've heard are music, so we use
- // the music volume setting for them.
+ // 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 : _musicVolTable[_musicVol];
- }
+ if (type == RDSE_FXLEADIN || type == RDSE_FXLEADOUT) {
+ id = (type == RDSE_FXLEADIN) ? -2 : -1;
+ volume = _musicMuted ? 0 : _musicVolTable[_musicVol];
+ }
+
+ WavInfo wavInfo;
- hr = openFx(id, data);
- if (hr != RD_OK)
- return hr;
+ if (!getWavInfo(data, &wavInfo)) {
+ warning("playFx: Not a valid WAV file");
+ return RDERR_INVALIDWAV;
}
- i = getFxIndex(id);
+ int32 fxi = getFxIndex(id);
- if (i == MAXFX) {
- if (data) {
- warning("playFx(%d, %d, %d, %d) - Not found", id, vol, pan, type);
- return RDERR_FXFUCKED;
- } else {
- warning("playFx(%d, %d, %d, %d) - Not open", id, vol, pan, type);
- return RDERR_FXNOTOPEN;
+ 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;
+
+ uint32 flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_LITTLE_ENDIAN;
+
+ if (wavInfo.channels == 2)
+ flags |= SoundMixer::FLAG_STEREO;
+
+
if (type == RDSE_FXLOOP)
- _fx[i]._flags |= SoundMixer::FLAG_LOOP;
+ flags |= SoundMixer::FLAG_LOOP;
else
- _fx[i]._flags &= ~SoundMixer::FLAG_LOOP;
+ flags &= ~SoundMixer::FLAG_LOOP;
- _fx[i]._volume = vol;
+ _fx[fxi]._volume = vol;
+
+ int8 p = _panTable[pan + 16];
- _vm->_mixer->playRaw(&_fx[i]._handle, _fx[i]._buf, _fx[i]._bufSize, _fx[i]._rate, _fx[i]._flags, -1, volume, p);
+ _vm->_mixer->playRaw(&_fx[fxi]._handle, wavInfo.data, wavInfo.samples, wavInfo.rate, flags, -1, volume, p);
return RD_OK;
}
@@ -1177,12 +1139,8 @@ int32 Sound::playFx(int32 id, byte *data, uint8 vol, int8 pan, uint8 type) {
void Sound::stopFxHandle(int i) {
if (_fx[i]._id) {
_vm->_mixer->stopHandle(_fx[i]._handle);
- free(_fx[i]._buf);
_fx[i]._id = 0;
_fx[i]._paused = false;
- _fx[i]._flags = 0;
- _fx[i]._bufSize = 0;
- _fx[i]._buf = NULL;
}
}
diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h
index 19a3458510..ef10dd79e4 100644
--- a/sword2/driver/d_sound.h
+++ b/sword2/driver/d_sound.h
@@ -44,10 +44,6 @@ struct FxHandle {
int32 _id;
bool _paused;
int8 _volume;
- uint16 _rate;
- uint32 _flags;
- uint16 *_buf;
- int32 _bufSize;
PlayingSoundHandle _handle;
};
@@ -157,9 +153,8 @@ public:
void pauseFxForSequence(void);
void unpauseFx(void);
bool isFxPlaying(int32 id);
- int32 openFx(int32 id, uint8 *data);
- int32 closeFx(int32 id);
int32 playFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type);
+ int32 stopFx(int32 id);
void clearAllFx(void);
};
diff --git a/sword2/resman.cpp b/sword2/resman.cpp
index 245f9819dd..c9c424b482 100644
--- a/sword2/resman.cpp
+++ b/sword2/resman.cpp
@@ -40,8 +40,9 @@ namespace Sword2 {
// 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::removeAll(void) {
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)
diff --git a/sword2/sound.cpp b/sword2/sound.cpp
index 7d8c4b157e..28c4218d78 100644
--- a/sword2/sound.cpp
+++ b/sword2/sound.cpp
@@ -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;
+}
+
+/**
+ * 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
+ * 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;
+void Sword2Engine::triggerFx(uint8 i) {
+ int type;
- 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
-
- 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 @@ int32 Logic::fnPlayFx(int32 *params) {
// .
// 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 @@ int32 Logic::fnPlayFx(int32 *params) {
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++;
+ int i;
- if (j == FXQ_LENGTH)
- return IR_CONT;
+ // Find a free slot in the FX queue
- _vm->_fxQueue[j].resource = params[0]; // wav resource id
- _vm->_fxQueue[j].type = params[1]; // FX_SPOT, FX_LOOP or FX_RANDOM
-
- 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 @@ int32 Logic::fnSoundFetch(int32 *params) {
}
/**
- * 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 @@ int32 Logic::fnSetFxVolAndPan(int32 *params) {
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 @@ int32 Logic::fnSetFxVol(int32 *params) {
// 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();
diff --git a/sword2/sound.h b/sword2/sound.h
index 13ece67851..6c7baabe24 100644
--- a/sword2/sound.h
+++ b/sword2/sound.h
@@ -38,10 +38,14 @@ namespace Sword2 {
// 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
diff --git a/sword2/sword2.h b/sword2/sword2.h
index 2d621622e7..588dd72106 100644
--- a/sword2/sword2.h
+++ b/sword2/sword2.h
@@ -321,16 +321,6 @@ public:
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;