diff options
author | Torbjörn Andersson | 2003-09-21 14:26:25 +0000 |
---|---|---|
committer | Torbjörn Andersson | 2003-09-21 14:26:25 +0000 |
commit | bfa5c6173408854ee32e8da581cd67b82671b217 (patch) | |
tree | dc9a0c9ce16f99e6743a25e9104e1c542b606005 /sword2 | |
parent | 078e1ee7996d1e33200ef354cff31773770cc489 (diff) | |
download | scummvm-rg350-bfa5c6173408854ee32e8da581cd67b82671b217.tar.gz scummvm-rg350-bfa5c6173408854ee32e8da581cd67b82671b217.tar.bz2 scummvm-rg350-bfa5c6173408854ee32e8da581cd67b82671b217.zip |
Some cleanup - lots more needed!
svn-id: r10348
Diffstat (limited to 'sword2')
-rw-r--r-- | sword2/driver/d_sound.cpp | 620 | ||||
-rw-r--r-- | sword2/driver/d_sound.h | 70 | ||||
-rw-r--r-- | sword2/sound.cpp | 6 |
3 files changed, 286 insertions, 410 deletions
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp index 06d353aabc..0941654313 100644 --- a/sword2/driver/d_sound.cpp +++ b/sword2/driver/d_sound.cpp @@ -153,12 +153,13 @@ #include "stdafx.h" #include "driver96.h" -#include "rdwin.h" // for hwnd. #include "d_sound.h" #include "../sword2.h" #include "common/timer.h" #include "sound/mixer.h" +// FIXME: Remove code duplication + // Decompression macros #define GetCompressedShift(byte) ((byte) >> 4) #define GetCompressedSign(byte) (((byte) >> 3) & 1) @@ -169,41 +170,21 @@ int32 panTable[33] = { 0, 7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127 }; -/* -int32 panTable[33] = { - -10000, - -1500, -1400, -1300, -1200, - -1100, -1000, -900, -800, - -700, -600, -500, -400, - -300, -200, -100, 0, - 100, 200, 300, 400, - 500, 600, 700, 800, - 900, 1000, 1100, 1200, - 1300, 1400, 1500, 10000 -}; -int32 volTable[241] = { --10000, -3925, -3852, -3781, -3710, -3642, -3574, -3508, -3443, -3379, -3316, -3255, -3194, -3135, -3077, -3020, -2964, -2909, -2855, -2802, -2750, -2699, -2649, -2600, -2551, -2504, -2458, -2412, -2367, -2323, -2280, -2238, -2197, -2156, -2116, -2077, -2038, -2000, -1963, -1927, -1891, -1856, -1821, -1788, -1755, -1722, -1690, -1659, -1628, -1598, -1568, -1539, -1510, -1482, -1455, -1428, -1401, -1375, -1350, -1325, --1300, -1290, -1279, -1269, -1259, -1249, -1239, -1229, -1219, -1209, -1199, -1190, -1180, -1171, -1161, -1152, -1142, -1133, -1124, -1115, -1106, -1097, -1088, -1080, -1071, -1062, -1054, -1045, -1037, -1028, -1020, -1012, -1004, -996, -988, -980, -972, -964, -956, -949, -941, -933, -926, -918, -911, -904, -896, -889, -882, -875, -868, -861, -854, -847, -840, -833, -827, -820, -813, -807, --800, -791, -782, -773, -764, -755, -747, -738, -730, -721, -713, -705, -697, -689, -681, -673, -665, -658, -650, -643, -635, -628, -621, -613, -606, -599, -593, -586, -579, -572, -566, -559, -553, -546, -540, -534, -528, -522, -516, -510, -504, -498, -492, -487, -481, -476, -470, -465, -459, -454, -449, -444, -439, -434, -429, -424, -419, -414, -409, -404, --400, -362, -328, -297, -269, -244, -221, -200, -181, -164, -148, -134, -122, -110, -100, -90, -82, -74, -67, -61, -55, -50, -45, -41, -37, -33, -30, -27, -25, -22, -20, -18, -16, -15, -13, -12, -11, -10, -9, -8, -7, -6, -6, -5, -5, -4, -4, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0 -}; -*/ int32 musicVolTable[17] = { 0, 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255 }; -/* -int32 musicVolTable[17] = { - -10000, - -5000, -3000, -2500, -2250, - -2000, -1750, -1500, -1250, - -1000, -750, -500, -350, - -200, -100, -50, 0 -}; -*/ + +// FIXME: Is this really a good way? The music occasionally pops, and I have +// a feeling it could be that the stream is emptied faster than we are filling +// it. Maybe we should set up a premix function instead, but then we'd have to +// do rate conversion and mixing here. +// +// Maybe it'd be useful if audio streams could have their own callbacks to fill +// them with data? void sword2_sound_handler(void *refCon) { - Sword2Sound *sound = (Sword2Sound *)refCon; + Sword2Sound *sound = (Sword2Sound *) refCon; sound->FxServer(); } @@ -220,30 +201,16 @@ Sword2Sound::Sword2Sound(SoundMixer *mixer) { fxMuted = 0; compressedMusic = 0; - volMusic[0] = 16; - volMusic[1] = 16; + musicVol = 16; + musicMuted = 0; bufferSizeMusic = 4410; _mixer = mixer; - - memset(fxId, 0, sizeof(fxId)); - memset(fxiPaused, 0, sizeof(fxiPaused)); - memset(fxRate, 0, sizeof(fxRate)); - - memset(musStreaming, 0, sizeof(musStreaming)); - memset(musicPaused, 0, sizeof(musicPaused)); - memset(musFading, 0, sizeof(musFading)); - memset(musLooping, 0, sizeof(musLooping)); - memset(musFilePos, 0, sizeof(musFilePos)); - memset(musEnd, 0, sizeof(musEnd)); - memset(musLastSample, 0, sizeof(musLastSample)); - memset(musId, 0, sizeof(musId)); - memset(soundHandleMusic, 0, sizeof(soundHandleMusic)); - memset(soundHandleFx, 0, sizeof(soundHandleFx)); + + memset(fx, 0, sizeof(fx)); + memset(music, 0, sizeof(music)); + soundHandleSpeech = 0; - memset(bufferFx, 0, sizeof(bufferFx)); - memset(flagsFx, 0, sizeof(flagsFx)); - memset(bufferSizeFx, 0, sizeof(bufferSizeFx)); soundOn = 1; g_engine->_timer->installProcedure(sword2_sound_handler, 100000, this); @@ -278,30 +245,19 @@ int32 Sword2Sound::ReverseStereo(void) { // -------------------------------------------------------------------------- int32 Sword2Sound::GetFxIndex(int32 id) { - int32 i = 0; + int32 i; - while (i < MAXFX) { - if (fxId[i] == id) + for (i = 0; i < MAXFX; i++) { + if (fx[i]._id == id) break; - i++; } return i; } int32 Sword2Sound::IsFxOpen(int32 id) { - int32 i = 0; - - while (i < MAXFX) { - if (fxId[i] == id) - break; - i++; - } - - if (i == MAXFX) - return 1; - else - return 0; + // FIXME: This seems backwards to me, but changing it breaks sound. + return GetFxIndex(id) == MAXFX; } // -------------------------------------------------------------------------- @@ -316,12 +272,12 @@ void Sword2Sound::FxServer(void) { if (!soundOn) return; - if (musicPaused[0] + musicPaused[1] == 0) { + if (!music[0]._paused && !music[1]._paused) { if (compressedMusic == 1) UpdateCompSampleStreaming(); } - if (!musStreaming[0] && !musStreaming[1] && fpMus.isOpen()) + if (!music[0]._streaming && !music[1]._streaming && fpMus.isOpen()) fpMus.close(); // FIXME: Doing this sort of things from a separate thread seems like @@ -336,15 +292,15 @@ void Sword2Sound::FxServer(void) { if (fxPaused) { for (i = 0; i < MAXFX; i++) { - if ((fxId[i] == (int32) 0xfffffffe) || (fxId[i] == (int32) 0xffffffff)) { - if (!soundHandleFx[i]) { - fxId[i] = 0; - if (bufferFx[i] != NULL) { - free(bufferFx[i]); - bufferFx[i] = NULL; + if ((fx[i]._id == (int32) 0xfffffffe) || (fx[i]._id == (int32) 0xffffffff)) { + if (!fx[i]._handle) { + fx[i]._id = 0; + if (fx[i]._buf != NULL) { + free(fx[i]._buf); + fx[i]._buf = NULL; } - bufferSizeFx[i] = 0; - flagsFx[i] = 0; + fx[i]._bufSize = 0; + fx[i]._flags = 0; } } } @@ -352,15 +308,15 @@ void Sword2Sound::FxServer(void) { } for (i = 0; i < MAXFX; i++) { - if (fxId[i]) { - if (!soundHandleFx[i]) { - fxId[i] = 0; - if (bufferFx[i] != NULL) { - free(bufferFx[i]); - bufferFx[i] = NULL; + if (fx[i]._id) { + if (!fx[i]._handle) { + fx[i]._id = 0; + if (fx[i]._buf != NULL) { + free(fx[i]._buf); + fx[i]._buf = NULL; } - bufferSizeFx[i] = 0; - flagsFx[i] = 0; + fx[i]._bufSize = 0; + fx[i]._flags = 0; } } } @@ -554,16 +510,12 @@ int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 v free(data8); // Modify the volume according to the master volume - byte volume; - int8 p; - if (speechMuted) { - volume = 0; - } else { - volume = vol * speechVol; - } - p = panTable[pan + 16]; + + byte volume = speechMuted ? 0 : vol * speechVol; + int8 p = panTable[pan + 16]; // Start the speech playing + speechPaused = 1; uint32 flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE; @@ -575,12 +527,14 @@ int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 v data16[j] = SWAP_BYTES_16(data16[j]); #endif - _mixer->playRaw(&soundHandleSpeech, data16, bufferSize, 22050, flags, -1, volume, pan); + _mixer->playRaw(&soundHandleSpeech, data16, bufferSize, 22050, flags, -1, volume, p); speechStatus = 1; } - DipMusic(); + // FIXME: See comment in UpdateCompSampleStreaming() + // DipMusic(); + return RD_OK; } @@ -625,11 +579,9 @@ void Sword2Sound::MuteSpeech(uint8 mute) { speechMuted = mute; if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) { - if (mute) { - g_engine->_mixer->setChannelVolume(soundHandleSpeech, 0); - } else { - g_engine->_mixer->setChannelVolume(soundHandleSpeech, 16 * speechVol); - } + byte volume = mute ? 0 : 16 * speechVol; + + g_engine->_mixer->setChannelVolume(soundHandleSpeech, volume); } } @@ -667,16 +619,14 @@ int32 Sword2Sound::OpenFx(int32 id, uint8 *data) { // Check that the fx is not already open for (i = 0; i < MAXFX; i++) { - if (fxId[i] == id) + if (fx[i]._id == id) return RDERR_FXALREADYOPEN; } // Now choose a free slot for the fx - fxi = 0; - while (fxi < MAXFX) { - if (fxId[fxi] == 0) + for (fxi = 0; fxi < MAXFX; fxi++) { + if (fx[fxi]._id == 0) break; - fxi++; } if (fxi == MAXFX) { @@ -689,53 +639,56 @@ int32 Sword2Sound::OpenFx(int32 id, uint8 *data) { // // Anyway, it'd be nicer - in theory - to expire the // least recently used slot. + // + // This used to be done by the "garbage collector" in + // FxServer(). - fxi = 0; - while (fxi < MAXFX) { - if (!soundHandleFx[fxi]) + for (fxi = 0; fxi < MAXFX; fxi++) { + if (!fx[fxi]._handle) break; - fxi++; } // Still no dice? I give up! - if (fxi == MAXFX) + if (fxi == MAXFX) { + warning("OpenFx: No free sound slots"); return RDERR_NOFREEBUFFERS; + } } // Set the sample size - search for the size of the data. i = 0; while (i < 100) { if (*data == 'd') { - data32 = (uint32*)data; + data32 = (uint32 *) data; if (READ_UINT32(data32) == MKID('data')) break; } - i += 1; + i++; data++; } if (!data32) return RDERR_INVALIDWAV; - bufferSizeFx[fxi] = READ_LE_UINT32(data32 + 1); + fx[fxi]._bufSize = READ_LE_UINT32(data32 + 1); // Fill the speech buffer with data - if (bufferFx[fxi] != NULL) - free(bufferFx[fxi]); - bufferFx[fxi] = (uint16 *) malloc(bufferSizeFx[fxi]); - memcpy(bufferFx[fxi], (uint8 *) (data32 + 2), bufferSizeFx[fxi]); - flagsFx[fxi] = SoundMixer::FLAG_16BITS; + if (fx[fxi]._buf != NULL) + free(fx[fxi]._buf); + fx[fxi]._buf = (uint16 *) malloc(fx[fxi]._bufSize); + memcpy(fx[fxi]._buf, (uint8 *) (data32 + 2), fx[fxi]._bufSize); + fx[fxi]._flags = SoundMixer::FLAG_16BITS; if (FROM_LE_16(wav->channels) == 2) - flagsFx[fxi] |= SoundMixer::FLAG_STEREO; + fx[fxi]._flags |= SoundMixer::FLAG_STEREO; - fxRate[fxi] = FROM_LE_16(wav->samplesPerSec); + fx[fxi]._rate = FROM_LE_16(wav->samplesPerSec); // Until the mixer supports LE samples natively, we need to // convert our LE ones to BE - for (int32 j = 0; j < (bufferSizeFx[fxi] / 2); j++) - bufferFx[fxi][j] = SWAP_BYTES_16(bufferFx[fxi][j]); + for (int32 j = 0; j < fx[fxi]._bufSize / 2; j++) + fx[fxi]._buf[j] = SWAP_BYTES_16(fx[fxi]._buf[j]); - fxId[fxi] = id; + fx[fxi]._id = id; } return RD_OK; } @@ -758,16 +711,13 @@ int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type warning("PlayFx(%d, %d, %d, %d) - Not open", id, vol, pan, type); return RDERR_FXNOTOPEN; } - flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + fx[i]._flags &= ~SoundMixer::FLAG_LOOP; - byte volume; // Start the sound effect playing - if (musicMuted) { - volume = 0; - } else { - volume = musicVolTable[volMusic[0]]; - } - g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], fxRate[i], flagsFx[i], -1, volume, 0); + + byte volume = musicMuted ? 0 : musicVolTable[musicVol]; + + g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, 0); } else { i = GetFxIndex(id); if (i == MAXFX) { @@ -775,23 +725,18 @@ int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type return RDERR_FXNOTOPEN; } if (loop == 1) - flagsFx[i] |= SoundMixer::FLAG_LOOP; + fx[i]._flags |= SoundMixer::FLAG_LOOP; else - flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + fx[i]._flags &= ~SoundMixer::FLAG_LOOP; - fxVolume[i] = vol; + fx[i]._volume = vol; - byte volume; - int8 p; // Start the sound effect playing - if (fxMuted) { - volume = 0; - } else { - volume = vol * fxVol; - } - p = panTable[pan + 16]; - g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], fxRate[i], flagsFx[i], -1, volume, p); + byte volume = fxMuted ? 0 : vol * fxVol; + int8 p = panTable[pan + 16]; + + g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, p); } } else { if (type == RDSE_FXLEADIN) { @@ -805,15 +750,11 @@ int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type warning("PlayFx(%d, %d, %d, %d) - Not found", id, vol, pan, type); return RDERR_FXFUCKED; } - flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + fx[i]._flags &= ~SoundMixer::FLAG_LOOP; - byte volume; - if (musicMuted) { - volume = 0; - } else { - volume = musicVolTable[volMusic[0]]; - } - g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], fxRate[i], flagsFx[i], -1, volume, 0); + byte volume = musicMuted ? 0 : musicVolTable[musicVol]; + + g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, 0); } else { hr = OpenFx(id, data); if (hr != RD_OK) { @@ -826,21 +767,17 @@ int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type return RDERR_FXFUCKED; } if (loop == 1) - flagsFx[i] |= SoundMixer::FLAG_LOOP; + fx[i]._flags |= SoundMixer::FLAG_LOOP; else - flagsFx[i] &= ~SoundMixer::FLAG_LOOP; - fxVolume[i] = vol; + fx[i]._flags &= ~SoundMixer::FLAG_LOOP; + fx[i]._volume = vol; - byte volume; - int8 p; // Start the sound effect playing - if (fxMuted) { - volume = 0; - } else { - volume = vol * fxVol; - } - p = panTable[pan + 16]; - g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], fxRate[i], flagsFx[i], -1, volume, p); + + byte volume = fxMuted ? 0 : vol * fxVol; + int8 p = panTable[pan + 16]; + + g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, p); } } } @@ -852,47 +789,45 @@ int32 Sword2Sound::SetFxVolumePan(int32 id, uint8 vol, int8 pan) { if (i == MAXFX) return RDERR_FXNOTOPEN; - fxVolume[i] = vol; + fx[i]._volume = vol; if (!fxMuted) { - g_engine->_mixer->setChannelVolume(soundHandleFx[i], vol * fxVol); - g_engine->_mixer->setChannelPan(soundHandleFx[i], panTable[pan + 16]); + g_engine->_mixer->setChannelVolume(fx[i]._handle, vol * fxVol); + g_engine->_mixer->setChannelPan(fx[i]._handle, panTable[pan + 16]); } return RD_OK; } int32 Sword2Sound::SetFxIdVolume(int32 id, uint8 vol) { int32 i = GetFxIndex(id); + if (i == MAXFX) return RDERR_FXNOTOPEN; - fxVolume[i] = vol; - if (!fxMuted) { - g_engine->_mixer->setChannelVolume(soundHandleFx[i], vol * fxVol); - } + fx[i]._volume = vol; + if (!fxMuted) + g_engine->_mixer->setChannelVolume(fx[i]._handle, vol * fxVol); + return RD_OK; } int32 Sword2Sound::ClearAllFx(void) { - int i; - if (!soundOn) return(RD_OK); - i = 0; - while (i < MAXFX) { - if (fxId[i] && fxId[i] != (int32) 0xfffffffe && fxId[i] != (int32) 0xffffffff) { - g_engine->_mixer->stopHandle(soundHandleFx[i]); - fxId[i] = 0; - fxiPaused[i] = 0; - if (bufferFx[i] != NULL) { - free(bufferFx[i]); - bufferFx[i] = NULL; + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._id && fx[i]._id != (int32) 0xfffffffe && fx[i]._id != (int32) 0xffffffff) { + g_engine->_mixer->stopHandle(fx[i]._handle); + fx[i]._id = 0; + fx[i]._paused = false; + if (fx[i]._buf != NULL) { + free(fx[i]._buf); + fx[i]._buf = NULL; } - bufferSizeFx[i] = 0; - flagsFx[i] = 0; + fx[i]._bufSize = 0; + fx[i]._flags = 0; } - i++; } + return RD_OK; } @@ -904,64 +839,61 @@ int32 Sword2Sound::CloseFx(int32 id) { i = GetFxIndex(id); if (i < MAXFX) { - g_engine->_mixer->stopHandle(soundHandleFx[i]); - fxId[i] = 0; - fxiPaused[i] = 0; - if (bufferFx[i] != NULL) { - free(bufferFx[i]); - bufferFx[i] = NULL; + g_engine->_mixer->stopHandle(fx[i]._handle); + fx[i]._id = 0; + fx[i]._paused = false; + if (fx[i]._buf != NULL) { + free(fx[i]._buf); + fx[i]._buf = NULL; } - bufferSizeFx[i] = 0; - flagsFx[i] = 0; + fx[i]._bufSize = 0; + fx[i]._flags = 0; } + return RD_OK; } int32 Sword2Sound::PauseFx(void) { - int i; - if (!fxPaused) { - for (i = 0; i < MAXFX; i++) { - if (fxId[i]) { - g_engine->_mixer->pauseHandle(soundHandleFx[i], true); - fxiPaused[i] = 1; - } else { - fxiPaused[i] = 0; - } + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._id) { + g_engine->_mixer->pauseHandle(fx[i]._handle, true); + fx[i]._paused = true; + } else + fx[i]._paused = false; } fxPaused = 1; } + return RD_OK; } int32 Sword2Sound::PauseFxForSequence(void) { - int i; - if (!fxPaused) { - for (i = 0; i<MAXFX; i++) { - if (fxId[i] && fxId[i] != (int32) 0xfffffffe) { - g_engine->_mixer->pauseHandle(soundHandleFx[i], true); - fxiPaused[i] = 1; + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._id && fx[i]._id != (int32) 0xfffffffe) { + g_engine->_mixer->pauseHandle(fx[i]._handle, true); + fx[i]._paused = true; } else { - fxiPaused[i] = 0; + fx[i]._paused = false; } } fxPaused = 1; } + return RD_OK; } int32 Sword2Sound::UnpauseFx(void) { - int i; - if (fxPaused) { - for (i = 0; i < MAXFX; i++) { - if (fxiPaused[i] && fxId[i]) { - g_engine->_mixer->pauseHandle(soundHandleFx[i], false); + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._paused && fx[i]._id) { + g_engine->_mixer->pauseHandle(fx[i]._handle, false); } } fxPaused = 0; } + return RD_OK; } @@ -970,30 +902,24 @@ uint8 Sword2Sound::GetFxVolume() { } void Sword2Sound::SetFxVolume(uint8 volume) { - int32 fxi; fxVol = volume; // Now update the volume of any fxs playing - for (fxi = 0; fxi < MAXFX; fxi++) { - if (fxId[fxi] && !fxMuted) { - g_engine->_mixer->setChannelVolume(soundHandleFx[fxi], fxVolume[fxi] * fxVol); - } + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._id && !fxMuted) + g_engine->_mixer->setChannelVolume(fx[i]._handle, fx[i]._volume * fxVol); } } void Sword2Sound::MuteFx(uint8 mute) { - int32 fxi; - fxMuted = mute; // Now update the volume of any fxs playing - for (fxi = 0; fxi < MAXFX; fxi++) { - if (fxId[fxi]) { - if (mute) { - g_engine->_mixer->setChannelVolume(soundHandleFx[fxi], 0); - } else { - g_engine->_mixer->setChannelVolume(soundHandleFx[fxi], fxVolume[fxi] * fxVol); - } + for (int i = 0; i < MAXFX; i++) { + if (fx[i]._id) { + byte volume = mute ? 0 : fx[i]._volume * fxVol; + + g_engine->_mixer->setChannelVolume(fx[i]._handle, volume); } } } @@ -1002,16 +928,15 @@ uint8 Sword2Sound::IsFxMute(void) { return fxMuted; } -int32 Sword2Sound::StreamCompMusic(const char *filename, uint32 musicId, int32 looping) { +int32 Sword2Sound::StreamCompMusic(const char *filename, uint32 musicId, bool looping) { StackLock lock(_mutex); return StreamCompMusicFromLock(filename, musicId, looping); } -int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, int32 looping) { +int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, bool looping) { int32 primaryStream = -1; int32 secondaryStream = -1; int32 i; - int32 v0, v1; uint16 *data16; uint8 *data8; @@ -1020,22 +945,22 @@ int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, // If both music streams are playing, that should mean one of them is // fading out. Pick that one. - if (musStreaming[0] && musStreaming[1]) { - if (musFading[0]) + if (music[0]._streaming && music[1]._streaming) { + if (music[0]._fading) primaryStream = 0; else primaryStream = 1; - musFading[primaryStream] = 0; - g_engine->_mixer->stopHandle(soundHandleMusic[primaryStream]); - musStreaming[primaryStream] = 0; + music[primaryStream]._fading = false; + g_engine->_mixer->stopHandle(music[primaryStream]._handle); + music[primaryStream]._streaming = false; } // Pick the available music stream. If no music is playing it doesn't // matter which we use, so pick the first one. - if (musStreaming[0] || musStreaming[1]) { - if (musStreaming[0]) { + if (music[0]._streaming || music[1]._streaming) { + if (music[0]._streaming) { primaryStream = 1; secondaryStream = 0; } else { @@ -1045,11 +970,11 @@ int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, } else primaryStream = 0; - strcpy(musFilename[primaryStream], filename); + strcpy(music[primaryStream]._fileName, filename); // Save looping info and tune id - musLooping[primaryStream] = looping; - musId[primaryStream] = musicId; + music[primaryStream]._looping = looping; + music[primaryStream]._id = musicId; // Don't start streaming if the volume is off. if (IsMusicMute()) @@ -1064,28 +989,26 @@ int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, return RDERR_INVALIDFILENAME; // Start other music stream fading out - if (secondaryStream != -1 && !musFading[secondaryStream]) - musFading[secondaryStream] = -16; + if (secondaryStream != -1 && !music[secondaryStream]._fading) + music[secondaryStream]._fading = -16; fpMus.seek((musicId + 1) * 8, SEEK_SET); - musFilePos[primaryStream] = fpMus.readUint32LE(); - musEnd[primaryStream] = fpMus.readUint32LE(); + music[primaryStream]._filePos = fpMus.readUint32LE(); + music[primaryStream]._fileEnd = fpMus.readUint32LE(); - if (!musEnd[primaryStream] || !musFilePos[primaryStream]) { + if (!music[primaryStream]._filePos || !music[primaryStream]._fileEnd) return RDERR_INVALIDID; - } // Calculate the file position of the end of the music - musEnd[primaryStream] += musFilePos[primaryStream]; + music[primaryStream]._fileEnd += music[primaryStream]._filePos; // Create a temporary buffer data8 = (uint8 *) malloc(bufferSizeMusic / 2); - if (!data8) { + if (!data8) return RDERR_OUTOFMEMORY; - } // Seek to start of the compressed music - fpMus.seek(musFilePos[primaryStream], SEEK_SET); + fpMus.seek(music[primaryStream]._filePos, SEEK_SET); // Read the compressed data in to the buffer if ((int32) fpMus.read(data8, bufferSizeMusic / 2) != bufferSizeMusic / 2) { @@ -1094,10 +1017,7 @@ int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, } // Store the current position in the file for future streaming - musFilePos[primaryStream] = fpMus.pos(); - - // FIXME: We used this decompression function in several places, so - // it really should be a separate function. + music[primaryStream]._filePos = fpMus.pos(); // decompress the music into the music buffer. data16 = (uint16 *) malloc(bufferSizeMusic); @@ -1115,99 +1035,60 @@ int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, // Store the value of the last sample ready for next batch of // decompression - musLastSample[primaryStream] = data16[i - 1]; + music[primaryStream]._lastSample = data16[i - 1]; // Free the compressed sound buffer free(data8); // Modify the volume according to the master volume and music mute // state - if (musicMuted) - v0 = v1 = 0; - else { - v0 = volMusic[0]; - v1 = volMusic[1]; - } - byte volume; - int8 pan; - - if (v0 > v1) { - volume = musicVolTable[v0]; - pan = (musicVolTable[v1 * 16 / v0] / 2) - 127; - } else if (v1 > v0) { - volume = musicVolTable[v1]; - pan = (musicVolTable[v0 * 16 / v1] / 2) + 127; - } else { - volume = musicVolTable[v1]; - pan = 0; - } + byte volume = musicMuted ? 0 : musicVolTable[musicVol]; #ifndef SCUMM_BIG_ENDIAN // FIXME: Until the mixer supports LE samples natively, we need to // convert our LE ones to BE - for (i = 0; i < (bufferSizeMusic / 2); i++) { + for (i = 0; i < bufferSizeMusic / 2; i++) data16[i] = SWAP_BYTES_16(data16[i]); - } #endif - g_engine->_mixer->newStream(&soundHandleMusic[primaryStream], data16, - bufferSizeMusic, 22050, SoundMixer::FLAG_16BITS, 100000, volume, pan); + g_engine->_mixer->newStream(&music[primaryStream]._handle, data16, + bufferSizeMusic, 22050, SoundMixer::FLAG_16BITS, 100000, volume, 0); free(data16); // Recorder some last variables - musStreaming[primaryStream] = 1; + music[primaryStream]._streaming = true; return RD_OK; } void Sword2Sound::UpdateCompSampleStreaming(void) { - uint32 i,j; - int32 v0, v1; - int32 len; + uint32 i,j; + int32 len; uint16 *data16; - uint8 *data8; - int fade; + uint8 *data8; + int fade; for (i = 0; i < MAXMUS; i++) { - if (!musStreaming[i]) + if (!music[i]._streaming) continue; // If the music is fading, adjust the volume for it. - if (musFading[i] < 0) { - if (++musFading[i] == 0) { - g_engine->_mixer->stopHandle(soundHandleMusic[i]); - musStreaming[i] = 0; - musLooping[i] = 0; + if (music[i]._fading < 0) { + if (++music[i]._fading == 0) { + g_engine->_mixer->stopHandle(music[i]._handle); + music[i]._streaming = false; + music[i]._looping = false; continue; } // Modify the volume according to the master volume // and music mute state - if (musicMuted) - v0 = v1 = 0; - else { - v0 = (volMusic[0] * (0 - musFading[i]) / 16); - v1 = (volMusic[1] * (0 - musFading[i]) / 16); - } - byte volume; - int8 pan; + byte volume = musicMuted ? 0 : musicVolTable[musicVol * (0 - music[i]._fading ) / 16]; - if (v0 > v1) { - volume = musicVolTable[v0]; - pan = (musicVolTable[v1 * 16 / v0] / 2) - 127; - } - if (v1 > v0) { - volume = musicVolTable[v1]; - pan = (musicVolTable[v0 * 16 / v1] / 2) + 127; - } else { - volume = musicVolTable[v1]; - pan = 0; - } - g_engine->_mixer->setChannelVolume(soundHandleMusic[i], volume); - g_engine->_mixer->setChannelPan(soundHandleMusic[i], pan); + g_engine->_mixer->setChannelVolume(music[i]._handle, volume); } // Re-fill the audio buffer. @@ -1217,10 +1098,10 @@ void Sword2Sound::UpdateCompSampleStreaming(void) { // Reduce length if it requires reading past the end of the // music - if (musFilePos[i] + len >= musEnd[i]) { + if (music[i]._filePos + len >= music[i]._fileEnd) { // End of music reached so we'll need to fade and // repeat - len = musEnd[i] - musFilePos[i]; + len = music[i]._fileEnd - music[i]._filePos; fade = 1; } else fade = 0; @@ -1229,30 +1110,30 @@ void Sword2Sound::UpdateCompSampleStreaming(void) { data8 = (uint8 *) malloc(len / 2); // Allocate a compressed data buffer if (data8 == NULL) { - g_engine->_mixer->stopHandle(soundHandleMusic[i]); - musStreaming[i] = 0; - musLooping[i] = 0; + g_engine->_mixer->stopHandle(music[i]._handle); + music[i]._streaming = false; + music[i]._looping = false; continue; } // Seek to update position of compressed music when // neccassary (probably never occurs) - if ((int32) fpMus.pos() != musFilePos[i]) - fpMus.seek(musFilePos[i], SEEK_SET); + if ((int32) fpMus.pos() != music[i]._filePos) + fpMus.seek(music[i]._filePos, SEEK_SET); // Read the compressed data in to the buffer if ((int32) fpMus.read(data8, len / 2) != len / 2) { - g_engine->_mixer->stopHandle(soundHandleMusic[i]); + g_engine->_mixer->stopHandle(music[i]._handle); free(data8); - musStreaming[i] = 0; - musLooping[i] = 0; + music[i]._streaming = false; + music[i]._looping = false; continue; } // Update the current position in the file for future // streaming - musFilePos[i] = fpMus.pos(); + music[i]._filePos = fpMus.pos(); // decompress the music into the music buffer. data16 = (uint16 *) malloc(len); @@ -1260,21 +1141,18 @@ void Sword2Sound::UpdateCompSampleStreaming(void) { // Decompress the first byte using the last // decompressed sample if (GetCompressedSign(data8[0])) - data16[0] = musLastSample[i] - (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); + data16[0] = music[i]._lastSample - (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); else - data16[0] = musLastSample[i] + (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); - - j = 1; + data16[0] = music[i]._lastSample + (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); - while (j < (uint32) len / 2) { + for (j = 1; j < (uint32) len / 2; j++) { if (GetCompressedSign(data8[j])) data16[j] = data16[j - 1] - (GetCompressedAmplitude(data8[j]) << GetCompressedShift(data8[j])); else data16[j] = data16[j - 1] + (GetCompressedAmplitude(data8[j]) << GetCompressedShift(data8[j])); - j++; } - musLastSample[i] = data16[j - 1]; + music[i]._lastSample = data16[j - 1]; #ifndef SCUMM_BIG_ENDIAN // Until the mixer supports LE samples natively, we @@ -1287,7 +1165,7 @@ void Sword2Sound::UpdateCompSampleStreaming(void) { if (len & 1) len--; - g_engine->_mixer->appendStream(soundHandleMusic[i], data16, len); + g_engine->_mixer->appendStream(music[i]._handle, data16, len); free(data16); free(data8); @@ -1295,19 +1173,23 @@ void Sword2Sound::UpdateCompSampleStreaming(void) { // End of the music so we need to start fading and start the // music again + if (fade) { - g_engine->_mixer->stopHandle(soundHandleMusic[i]); + g_engine->_mixer->stopHandle(music[i]._handle); // FIXME: The original code faded the music here, but // to do that we need to start before we reach the end // of the file. + // + // On the other hand, do we want to fade out the end + // of the music? // Fade the old music // musFading[i] = -16; // Loop if neccassary - if (musLooping[i]) - StreamCompMusicFromLock(musFilename[i], musId[i], musLooping[i]); + if (music[i]._looping) + StreamCompMusicFromLock(music[i]._fileName, music[i]._id, music[i]._looping); } } @@ -1397,43 +1279,35 @@ int32 Sword2Sound::DipMusic() { int32 Sword2Sound::MusicTimeRemaining() { StackLock lock(_mutex); - int i; - - for (i = 0; i < MAXMUS && !musStreaming[i]; i++) { - // this is meant to be empty! (James19aug97) + for (int i = 0; i < MAXMUS; i++) { + if (music[i]._streaming && !music[i]._fading) + return (music[i]._fileEnd - music[i]._filePos) / 22050; } - if (i == MAXMUS) - return 0; - - return (musEnd[i] - musFilePos[i]) / 22050; + return 0; } void Sword2Sound::StopMusic(void) { StackLock lock(_mutex); - int i; - - for (i = 0; i < MAXMUS; i++) { - if (musStreaming[i]) - musFading[i] = -16; + for (int i = 0; i < MAXMUS; i++) { + if (music[i]._streaming) + music[i]._fading = -16; else - musLooping[i] = 0; + music[i]._looping = false; } } int32 Sword2Sound::PauseMusic(void) { StackLock lock(_mutex); - int i; - if (soundOn) { - for (i = 0; i < 2; i++) { - if (musStreaming[i]) { - musicPaused[i] = TRUE; - g_engine->_mixer->pauseHandle(soundHandleMusic[i], true); + for (int i = 0; i < MAXMUS; i++) { + if (music[i]._streaming) { + music[i]._paused = true; + g_engine->_mixer->pauseHandle(music[i]._handle, true); } else { - musicPaused[i] = FALSE; + music[i]._paused = false; } } } @@ -1443,13 +1317,11 @@ int32 Sword2Sound::PauseMusic(void) { int32 Sword2Sound::UnpauseMusic(void) { StackLock lock(_mutex); - int i; - if (soundOn) { - for (i = 0; i < 2; i++) { - if (musicPaused[i]) { - g_engine->_mixer->pauseHandle(soundHandleMusic[i], false); - musicPaused[i] = FALSE; + for (int i = 0; i < MAXMUS; i++) { + if (music[i]._paused) { + g_engine->_mixer->pauseHandle(music[i]._handle, false); + music[i]._paused = false; } } } @@ -1459,39 +1331,33 @@ int32 Sword2Sound::UnpauseMusic(void) { void Sword2Sound::SetMusicVolume(uint8 volume) { StackLock lock(_mutex); - int i; + musicVol = volume; - for (i = 0; i < MAXMUS; i++) { - volMusic[i] = volume; - if (musStreaming[i] && !musFading[i] && !musicMuted) { - g_engine->_mixer->setChannelVolume(soundHandleMusic[i], musicVolTable[volume]); - } + for (int i = 0; i < MAXMUS; i++) { + if (music[i]._streaming && !music[i]._fading && !musicMuted) + g_engine->_mixer->setChannelVolume(music[i]._handle, musicVolTable[volume]); } } uint8 Sword2Sound::GetMusicVolume() { - return (uint8) volMusic[0]; + return musicVol; } void Sword2Sound::MuteMusic(uint8 mute) { StackLock lock(_mutex); - int i; - musicMuted = mute; - for (i = 0; i < MAXMUS; i++) { + for (int i = 0; i < MAXMUS; i++) { if (!mute) { - if (!musStreaming[i] && musLooping[i]) - StreamCompMusicFromLock(musFilename[i], musId[i], musLooping[i]); + if (!music[i]._streaming && music[i]._looping) + StreamCompMusicFromLock(music[i]._fileName, music[i]._id, music[i]._looping); } - if (musStreaming[i] && !musFading[i]) { - if (mute) { - g_engine->_mixer->setChannelVolume(soundHandleMusic[i], musicVolTable[0]); - } else { - g_engine->_mixer->setChannelVolume(soundHandleMusic[i], musicVolTable[volMusic[i]]); - } + if (music[i]._streaming && !music[i]._fading) { + byte volume = mute ? 0 : musicVolTable[musicVol]; + + g_engine->_mixer->setChannelVolume(music[i]._handle, volume); } } } diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h index 42c18466e2..a32ddc59f8 100644 --- a/sword2/driver/d_sound.h +++ b/sword2/driver/d_sound.h @@ -43,6 +43,30 @@ extern void sword2_sound_handler(void *refCon); +typedef struct { + int32 _id; + bool _paused; + int8 _volume; + uint16 _rate; + uint32 _flags; + uint16 *_buf; + int32 _bufSize; + PlayingSoundHandle _handle; +} fxHandle; + +typedef struct { + uint32 _id; + char _fileName[256]; + bool _streaming; + bool _paused; + bool _looping; + int16 _fading; + int32 _filePos; + int32 _fileEnd; + int16 _lastSample; + PlayingSoundHandle _handle; +} musicHandle; + class Sword2Sound { public: Sword2Sound(SoundMixer *mixer); @@ -66,8 +90,7 @@ class Sword2Sound { int32 UnpauseFx(void); int32 PauseMusic(void); int32 UnpauseMusic(void); - int32 StreamMusic(uint8 *filename, int32 looping); - int32 StreamCompMusic(const char *filename, uint32 musicId, int32 looping); + int32 StreamCompMusic(const char *filename, uint32 musicId, bool looping); int32 MusicTimeRemaining(); int32 ReverseStereo(void); uint8 GetFxVolume(void); @@ -76,32 +99,32 @@ class Sword2Sound { uint8 IsMusicMute(void); uint8 IsFxMute(void); uint8 IsSpeechMute(void); - void StopMusic(void); - void SetFxVolume(uint8 vol); - void SetSpeechVolume(uint8 vol); - void SetMusicVolume(uint8 vol); - void MuteMusic(uint8 mute); - void MuteFx(uint8 mute); - void MuteSpeech(uint8 mute); + void StopMusic(void); + void SetFxVolume(uint8 vol); + void SetSpeechVolume(uint8 vol); + void SetMusicVolume(uint8 vol); + void MuteMusic(uint8 mute); + void MuteFx(uint8 mute); + void MuteSpeech(uint8 mute); int32 IsFxOpen(int32 id); int32 SetFxVolumePan(int32 id, uint8 vol, int8 pan); int32 SetFxIdVolume(int32 id, uint8 vol); void UpdateCompSampleStreaming(void); SoundMixer *_mixer; private: - int32 StreamCompMusicFromLock(const char *filename, uint32 musicId, int32 looping); + int32 StreamCompMusicFromLock(const char *filename, uint32 musicId, bool looping); int32 GetFxIndex(int32 id); int32 DipMusic(); OSystem::MutexRef _mutex; - int32 fxId[MAXFX]; - uint8 fxiPaused[MAXFX]; - uint8 fxVolume[MAXFX]; - uint16 fxRate[MAXFX]; - uint32 flagsFx[MAXFX]; - uint16 *bufferFx[MAXFX]; - int32 bufferSizeFx[MAXFX]; + fxHandle fx[MAXFX]; + musicHandle music[MAXMUS]; + + // We used to have two music volumes - one for each channel - + // but they were always set to the same value. + + uint8 musicVol; uint8 soundOn; uint8 speechStatus; @@ -113,22 +136,9 @@ class Sword2Sound { uint8 fxMuted; uint8 compressedMusic; - int16 musStreaming[MAXMUS]; - int16 musicPaused[MAXMUS]; - int16 musFading[MAXMUS]; - int16 musLooping[MAXMUS]; - - PlayingSoundHandle soundHandleFx[MAXFX]; - PlayingSoundHandle soundHandleMusic[MAXMUS]; PlayingSoundHandle soundHandleSpeech; File fpMus; int bufferSizeMusic; - char musFilename[MAXMUS][256]; - int32 musFilePos[MAXMUS]; - int32 musEnd[MAXMUS]; - int16 musLastSample[MAXMUS]; - uint32 musId[MAXMUS]; - uint32 volMusic[2]; uint8 musicMuted; }; diff --git a/sword2/sound.cpp b/sword2/sound.cpp index 7928ffc9b3..3582b3ed70 100644 --- a/sword2/sound.cpp +++ b/sword2/sound.cpp @@ -374,19 +374,19 @@ int32 FN_play_music(int32 *params) { // updated by James on 10apr97 // 1 loop flag (0 or 1) char filename[128]; - uint32 loopFlag; + bool loopFlag; uint32 rv; // Zdebug("FN_play_music(%d)", params[0]); if (params[1] == FX_LOOP) { - loopFlag = RDSE_FXLOOP; + loopFlag = true; // keep a note of the id, for restarting after an // interruption to gameplay looping_music_id = params[0]; } else { - loopFlag = RDSE_FXSPOT; + loopFlag = false; // don't need to restart this tune after control panel or // restore |