diff options
author | Paweł Kołodziejski | 2003-08-30 18:06:08 +0000 |
---|---|---|
committer | Paweł Kołodziejski | 2003-08-30 18:06:08 +0000 |
commit | a2dad74da12f4d4bd63f79e86d0226c07e16dcc9 (patch) | |
tree | 4e3cecef76dcac2467755f8b4e92889a44420988 | |
parent | 890c5cde042ce1fa1cce0c55e6ef7976dc2bbb9a (diff) | |
download | scummvm-rg350-a2dad74da12f4d4bd63f79e86d0226c07e16dcc9.tar.gz scummvm-rg350-a2dad74da12f4d4bd63f79e86d0226c07e16dcc9.tar.bz2 scummvm-rg350-a2dad74da12f4d4bd63f79e86d0226c07e16dcc9.zip |
added sfx support, increased speech support, and music code(streaming works fine but you don't hear anything) newStream, and appendStream doesn't work but playRaw works for music
svn-id: r9923
-rw-r--r-- | sword2/credits.h | 2 | ||||
-rw-r--r-- | sword2/driver/d_sound.cpp | 2464 | ||||
-rw-r--r-- | sword2/driver/d_sound.h | 26 | ||||
-rw-r--r-- | sword2/driver/driver96.h | 44 | ||||
-rw-r--r-- | sword2/driver/rdwin.cpp | 6 | ||||
-rw-r--r-- | sword2/sound.cpp | 2 | ||||
-rw-r--r-- | sword2/sword2.cpp | 6 |
7 files changed, 782 insertions, 1768 deletions
diff --git a/sword2/credits.h b/sword2/credits.h index 26337c81c6..efb7a27095 100644 --- a/sword2/credits.h +++ b/sword2/credits.h @@ -23,6 +23,6 @@ #include "driver/driver96.h" // int32 __declspec( dllexport ) Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus); -int32 Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus); +//int32 Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus); #endif diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp index 15c8744704..2b9b8ab99f 100644 --- a/sword2/driver/d_sound.cpp +++ b/sword2/driver/d_sound.cpp @@ -25,170 +25,6 @@ // // Summary : This module holds the driver interface to direct sound. // -// Version Date By Description -// ------- --------- --- ----------------------------------------------- -// 1.0 03-Dec-96 PRP The sound buffer can be created, with the -// format defined by the game engine, and speech -// can be played. -// -// 1.1 05-Dec-96 PRP Sound effects now done. -// -// 1.2 19-Dec-96 PRP Added volume and pan to speech and sound -// effects. Also, added type to sound effects -// so that they can be looped. Implemented -// a CloseAllFx function which will clear out -// all sound effects. -// -// 1.3 20-Dec-96 PRP Fixed a bug in the function which clears -// spot effects when they have finished playing. -// -// 1.4 02-Jan-97 PRP Fixed a bug in ClearAllFx which was trying -// to close the speech. -// -// 1.5 08-Apr-97 PRP Added ... to the -// InitialiseSound function. -// -// 1.6 09-Apr-97 PRP Added functions to steam music from CD. -// -// 1.7 29-May-97 PSJ Added functions to save and restore the state -// of the sound drivers. -// -// 1.8 04-Jun-97 PRP Added bodge to PlayFx routine which registers -// a sound effect to remove itself from the list -// if it is the tune to leave a sequence. -// -// 1.9 06-Jun-97 PSJ Expanded volTable from 17 to 241 entries. -// Added an fx and a speech master volume level. -// Added SetFxVolume and GetFxVolume for fx master -// volume. Added SetSpeechVolume and GetSpeechVolume -// for speech master volume. -// -// 1.10 09-Jun-97 PSJ Added SetMusicVolume and GetMusicVolume. -// -// 1.11 09-Jun-97 PSJ Fixed bug in SetSpeechVolume. -// -// 1.12 10-Jun-97 PSJ Added MuteMusic, MuteSpeech, MuteFx, IsMusicMute, -// IsFxMute and IsSpeechMute. -// -// 1.13 12-Jun-97 PSJ Added PlayCompSpeech to play compressed speech -// from a speech cluster. -// -// 1.14 19-Jun-97 PSJ Added StreamCompMusic and UpdateCompSampleStreaming -// to play compressed music from a music cluster. -// Added StopMusic to fade out any music playing. -// -// 1.15 24-Jun-97 PSJ Changed PlayCompSpeech to physically check for -// playing samples rather than using the assuming the -// speechStatus flag is correct. -// -// 1.16 24-Jun-97 PSJ Fixed bug it SetSpeechVolume. -// -// 1.17 26-Jun-97 PSJ Added AmISpeaking() for lip syncing. -// -// 1.18 26-Jun-97 PSJ Tweaked the nose of the dread, killer AmISpeaking -// function. -// -// 1.19 26-Jun-97 PSJ Added PauseSpeech and UnpauseSpeech. -// -// 1.20 26-Jun-97 PSJ Fixed a bug in the muteSpeech routine. -// -// 1.21 26-Jun-97 PSJ Fixed a bug in the AmISpeaking routine. -// -// 1.22 26-Jun-97 PSJ PlayCompSpeech loads and pauses the speech -// ready to be played by UnpauseSpeech. -// -// 1.23 01-Jul-97 PSJ Fixed GetSpeechStatus to work when speech is paused -// -// 1.24 03-Jul-97 PSJ Stopped PlayCompSpeech clicking at the end of samples. -// -// 1.25 10-Jul-97 PSJ Reduced music volume by 1/4 when playing speech -// -// 1.26 10-Jul-97 PSJ GetMusicVolume return safeMusicVol if it is set. -// -// 1.27 15-Jul-97 PRP Added functions to pause and unpause the sound effects. -// -// 1.28 15-Jul-97 PRP Fixed PauseFx -// -// 1.29 16-Jul-97 PSJ Added GetCompSpeechSize and PreFetchCompSpeech -// -// 1.30 16-Jul-97 PRP Fixed setting of sound fx volume. -// -// 1.31 18-Jul-97 PRP Added speech expansion to get samples to sound the same. -// -// 1.32 18-Jul-97 PRP Hopefully fixed expansion algorithm. -// -// 1.33 18-Jul-97 JEL Fixed UnpauseFx() -// -// 1.34 18-Jul-97 JEL Fixed PlayCompSpeech() -// -// 1.35 18-Jul-97 JEL Removed speech volume enhancing (now to be done in speech compressor) -// -// 1.36 21-Jul-97 PRP Added new type of sound effect which is the music lead in. -// Also, added function to pause the sound effects -// just for sequences. -// -// 1.37 21-Jul-97 PRP Modified ClearAllFx so that it doesn't kick out -// lead in and lead out music for smacker sequences. -// -// 1.38 21-Jul-97 PRP Tried to fix the bug where the second lead in -// music will not play due to a duplicate id. -// -// 1.39 21-Jul-97 PRP Finally fixed the bug to kick out lead in music -// fx when they have finished. -// -// 1.40 25-Jul-97 JEL Fixed crashing when music paused & unpaused repeatedly -// -// 1.41 28-Jul-97 PRP Checked to see if fx are looping as well as playing! -// -// 1.42 30-Jul-97 PSJ Added Music dipping. -// -// 1.43 30-Jul-97 PSJ Added MusicTimeRemaining. -// -// 1.44 31-Jul-97 PSJ Adjusted MusicTimeRemaining to include music left in buffer. -// -// 1.45 06-Aug-97 PSJ Updated Get and Set scroll SoundStatus. -// -// 1.46 12-Aug-97 PSJ Added ReverseStereo(void) -// -// 1.47 13-Aug-97 PSJ Updated DipMusic so it fades up after speech has finished. -// -// 1.48 13-Aug-97 PRP Added IsFxOpen(). -// -// 1.49 15-Aug-97 PRP Added SetFxVolumePan(). -// -// 1.50 15-Aug-97 PRP Added SetFxIdVolume() -// -// 1.51 15-Aug-97 PSJ Fixed bug in PlayCompMusic(); -// -// 1.52 19-Aug-97 JEL Fixed bug in MusicTimeRemaining() -// -// WE'VE SCREWED UP THE NUMBERING! -// -// 1.59 19-Aug-97 JEL Fixed bug in MusicTimeRemaining(), ;) -// -// 1.60 19-Aug-97 PSJ Updated DipMusic so it fades music a bit more. -// -// 1.61 21-Aug-97 PSJ Updated StreamCompMusic so if both streams are in use, -// the fading stream is stopped and the new tune started. -// -// 1.62 21-Aug-97 PSJ Updated StreamCompMusic so if the music is unmuted, -// the last tune is restarted if it was looping. -// -// 1.63 22-Aug-97 PSJ Update PlayFx to handle smacker leadouts. -// -// 1.64 27-Aug-97 PSJ Update PlayFx to record an fx's local volume, -// So SetFxVolume can update playing fx's with the -// correct volume. -// -// 1.65 27-Aug-97 PSJ Stopped CloseFX from closing invalid fx's. -// -// 1.66 01-Sep-97 PRP Cleared the fxPaused flag when closing fx. -// -// 1.67 01-Sep-97 PRP Fixed the fact that SetFxVolume was still -// being done even if the fx were muted. -// -// 1.68 01-Sep-97 PRP Set zero sound to -10000 -// // Functions // --------- // @@ -205,15 +41,6 @@ // // -------------------------------------------------------------------------- // -// int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan) -// -// This function plays the wav file passed into it as speech. An error occurs -// if speech is already playing, or directSound comes accross problems. The -// volume is 0 for zero volume and 16 for maximum volume. The pan position -// is -16 for full left, 0 for central and 16 for full right. -// -// -------------------------------------------------------------------------- -// // int32 PlayCompSpeech(const char *filename, uint32 id, uint8 vol, int8 pan) // // This function loads, decompresses and plays the wav 'id' from the cluster @@ -296,15 +123,6 @@ // // -------------------------------------------------------------------------- // -// int32 StreamMusic(uint8 *filename, int32 loopFlag) -// -// Streams music from the file defined by filename. The loopFlag should -// be set to RDSE_FXLOOP if the music is to loop back to the start. -// Otherwise, it should be RDSE_FXSPOT. -// The return value must be checked for any problems. -// -// -------------------------------------------------------------------------- -// // int32 StreamCompMusic(uint8 *filename, uint32 id, int32 loopFlag) // // Streams music 'id' from the cluster file 'filename'. The loopFlag should @@ -312,8 +130,6 @@ // Otherwise, it should be RDSE_FXSPOT. // The return value must be checked for any problems. // -// StreamCompMusic should not be used inconjunction with StreamMusic. -// // -------------------------------------------------------------------------- // // void StopMusic(void) @@ -346,34 +162,21 @@ // //============================================================================= - - - #define WIN32_LEAN_AND_MEAN -//#include <windows.h> -//#include <windowsx.h> -#include <stdio.h> - #include "stdafx.h" #include "driver96.h" #include "rdwin.h" // for hwnd. #include "d_sound.h" #include "../sword2.h" +#include "sound/mixer.h" // Decompression macros -#define MakeCompressedByte(shift,sign,amplitude) (((shift)<<4) + ((sign)<<3) + (amplitude)) -#define GetCompressedShift(byte) ((byte)>>4) -#define GetCompressedSign(byte) (((byte)>>3) & 1) -#define GetCompressedAmplitude(byte) ((byte) & 7) -#define GetdAPower(dA,power) for (power = 15;power>0 && !((dA) & (1<<power)); power--) - -/* -LPDIRECTSOUND lpDS; -LPDIRECTSOUNDBUFFER dsbPrimary; -LPDIRECTSOUNDBUFFER dsbSpeech; -LPDIRECTSOUNDBUFFER dsbFx[MAXFX]; -*/ +#define MakeCompressedByte(shift, sign, amplitude) (((shift) << 4) + ((sign) << 3) + (amplitude)) +#define GetCompressedShift(byte) ((byte) >> 4) +#define GetCompressedSign(byte) (((byte) >> 3) & 1) +#define GetCompressedAmplitude(byte) ((byte) & 7) +#define GetdAPower(dA, power) for (power = 15; power > 0 && !((dA) & (1 << power)); power--) int32 panTable[33] = { -10000, @@ -388,12 +191,10 @@ int32 panTable[33] = { }; 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] = { @@ -404,10 +205,11 @@ int32 musicVolTable[17] = { -200, -100, -50, 0 }; - +void sword2_sound_handler (void *engine) { + g_sword2->_sound->FxServer(); +} Sword2Sound::Sword2Sound(SoundMixer *mixer) { - soundOn = 0; speechStatus = 0; fxPaused = 0; @@ -421,92 +223,44 @@ Sword2Sound::Sword2Sound(SoundMixer *mixer) { volMusic[0] = 16; volMusic[1] = 16; musicMuted = 0; - + bufferSizeMusic = 44100; _mixer = mixer; } -/* not used seemingly - khalek - -#define SPEECH_EXPANSION - -#ifdef SPEECH_EXPANSION - -int16 ExpandSpeech(int16 sample) -// This code is executed to expand the speech samples to make them sound -// louder, without losing the quality of the sample -{ - double x, xsquared, result; - double expansionFactor = 2.5; - - x = (double) sample; - xsquared = sample * sample; - - if (x < 0.0) - { - result = expansionFactor * x + (expansionFactor - 1.0) * xsquared / 32768.0; - if (result < -32767.0) - result = -32767.0; - } - else - { - result = expansionFactor * x + (1.0 - expansionFactor) * xsquared / 32768.0; - if (result > 32767.0) - result = 32767.0; - } - - return (int16) result; - -} -#endif -*/ - // -------------------------------------------------------------------------- // This function reverse the pan table, thus reversing the stereo. // -------------------------------------------------------------------------- -int32 Sword2Sound::ReverseStereo(void) -{ - int32 i,j; +int32 Sword2Sound::ReverseStereo(void) { + int i,j; - for (i = 0; i<16; i++) - { + for (i = 0; i < 16; i++) { j = panTable[i]; - panTable[i] = panTable[32-i]; - panTable[32-i] = j; + panTable[i] = panTable[32 - i]; + panTable[32 - i] = j; } return (RD_OK); } - - // -------------------------------------------------------------------------- // This function returns the index of the sound effect with the ID passed in. // -------------------------------------------------------------------------- -int32 Sword2Sound::GetFxIndex(int32 id) - -{ - +int32 Sword2Sound::GetFxIndex(int32 id) { int32 i = 0; - while (i < MAXFX) - { + while (i < MAXFX) { if (fxId[i] == id) break; i++; } return(i); - } - -int32 Sword2Sound::IsFxOpen(int32 id) -{ - +int32 Sword2Sound::IsFxOpen(int32 id) { int32 i = 0; - while (i < MAXFX) - { + while (i < MAXFX) { if (fxId[i] == id) break; i++; @@ -516,83 +270,59 @@ int32 Sword2Sound::IsFxOpen(int32 id) return 1; else return 0; - } - // -------------------------------------------------------------------------- // This function checks the status of all current sound effects, and clears // out the ones which are no longer required in a buffer. It is called on // a slow timer from rdwin.c // -------------------------------------------------------------------------- -void Sword2Sound::FxServer(void) - -{ - warning("stub FxServer"); -/* - int32 i; - int32 status; - +void Sword2Sound::FxServer(void) { + int i; if (!soundOn) return; - if (musicPaused[0] + musicPaused[1] == 0) - { + if (musicPaused[0] + musicPaused[1] == 0) { if (compressedMusic == 1) UpdateCompSampleStreaming(); - else if (compressedMusic == 2) - UpdateSampleStreaming(); } - if (fxPaused) - { - for (i=0; i<MAXFX; i++) - { - if ((fxId[i] == 0xfffffffe) || (fxId[i] == 0xffffffff)) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (!(status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING))) - { - if (fxCached[i] == RDSE_FXTOCLEAR) - { - IDirectSoundBuffer_Release(dsbFx[i]); - fxId[i] = 0; + if (fxPaused) { + for (i = 0; i < MAXFX; i++) { + if ((fxId[i] == 0xfffffffe) || (fxId[i] == 0xffffffff)) { + if (!g_engine->_mixer->isChannelActive(soundHandleFx[i])) { + fxId[i] = 0; + if (bufferFx[i] != NULL) { + free(bufferFx[i]); + bufferFx[i] = NULL; } + bufferSizeFx[i] = 0; + flagsFx[i] = 0; } } } return; - } - + } - for (i=0; i<MAXFX; i++) - { - if (fxId[i]) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (!(status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING))) - { - if (fxCached[i] == RDSE_FXTOCLEAR) - { - IDirectSoundBuffer_Release(dsbFx[i]); - fxId[i] = 0; + for (i = 0; i < MAXFX; i++) { + if (fxId[i]) { + if (!g_engine->_mixer->isChannelActive(soundHandleFx[i])) { + fxId[i] = 0; + if (bufferFx[i] != NULL) { + free(bufferFx[i]); + bufferFx[i] = NULL; } + bufferSizeFx[i] = 0; + flagsFx[i] = 0; } } } -*/ } - - - - -int32 Sword2Sound::InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth) - -{ - warning("stub InitaliseSound( %d, %d, %d )", freq, channels, bitDepth); - +int32 Sword2Sound::InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth) { + soundOn = 1; + memset(fxId, 0, sizeof(fxId)); memset(fxCached, 0, sizeof(fxCached)); memset(fxiPaused, 0, sizeof(fxiPaused)); @@ -605,310 +335,79 @@ int32 Sword2Sound::InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth memset(musLooping, 0, sizeof(musLooping)); - memset(streamCursor, 0, sizeof(streamCursor)); memset(musFilePos, 0, sizeof(musFilePos)); memset(musEnd, 0, sizeof(musEnd)); memset(musLastSample, 0, sizeof(musLastSample)); memset(musId, 0, sizeof(musId)); + memset(soundHandleMusic, -1, sizeof(soundHandleMusic)); + memset(soundHandleFx, -1, sizeof(soundHandleFx)); + soundHandleSpeech = -1; + memset(bufferFx, 0, sizeof(bufferFx)); + memset(flagsFx, 0, sizeof(flagsFx)); + memset(bufferSizeFx, 0, sizeof(bufferSizeFx)); -/* - int32 i; - HRESULT hrz; - DSBUFFERDESC dsbd; - WAVEFORMATEX pf; - - - hrz = DirectSoundCreate(NULL, &lpDS, NULL); - if (hrz != DS_OK) - return(RDERR_DSOUNDCREATE); - - hrz = IDirectSound_SetCooperativeLevel(lpDS, hwnd, DSSCL_EXCLUSIVE); - if (hrz != DS_OK) - { - IDirectSound_Release(lpDS); - return(RDERR_DSOUNDCOOPERATE); - } - - - memset(&dsbd, 0, sizeof(DSBUFFERDESC)); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - dsbd.lpwfxFormat = NULL; - hrz = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbPrimary, NULL); - if (hrz != DS_OK) - { - IDirectSound_Release(lpDS); - return(RDERR_DSOUNDPBUFFER); - } - - memset(&pf, 0, sizeof(WAVEFORMATEX)); - - pf.wFormatTag = WAVE_FORMAT_PCM; - - pf.nSamplesPerSec = freq; - - pf.nChannels = channels; - - pf.wBitsPerSample = bitDepth; - pf.nBlockAlign = pf.wBitsPerSample * pf.nChannels >> 3; - pf.nAvgBytesPerSec = pf.nBlockAlign * pf.nSamplesPerSec; - pf.cbSize = 0; - hrz = IDirectSoundBuffer_SetFormat(dsbPrimary, (LPWAVEFORMATEX) &pf); - if (hrz != DS_OK) - { - // We have not been able to set the primary format to the format requested!!! - // But carry on anyway, the mixer will just have to work harder :) - } - - // Clear the fx id's - for (i=0; i<MAXFX; i++) - fxId[i] = 0; - */ - - soundOn = 1; - - /* - //---------------------------------- - // New initialisers (James19aug97) - - memset (fxId, 0, MAXFX*sizeof(int32)); - memset (fxCached, 0, MAXFX*sizeof(uint8)); - memset (fxiPaused, 0, MAXFX*sizeof(uint8)); - memset (fxLooped, 0, MAXFX*sizeof(uint8)); - - memset (musStreaming, 0, MAXFX*sizeof(int16)); - memset (musicPaused, 0, MAXFX*sizeof(int16)); - memset (musCounter, 0, MAXFX*sizeof(int16)); - memset (musFading, 0, MAXFX*sizeof(int16)); - - memset (musLooping, 0, MAXFX*sizeof(int16)); - memset (fpMus, 0, MAXFX*sizeof(FILE*)); - - memset (streamCursor, 0, MAXFX*sizeof(int32)); - memset (musFilePos, 0, MAXFX*sizeof(int32)); - memset (musEnd, 0, MAXFX*sizeof(int32)); - memset (musLastSample, 0, MAXFX*sizeof(int16)); - memset (musId, 0, MAXFX*sizeof(uint32)); -*/ return(RD_OK); - } - -int32 Sword2Sound::PlaySpeech(uint8 *data, uint8 vol, int8 pan) - -{ - warning("stub PlaySpeech"); -/* - uint32 dwBytes1, dwBytes2; - int32 i; - uint32 *data32; - void *lpv1, *lpv2; - _wavHeader *wav; - HRESULT hr; - DSBUFFERDESC dsbd; - PCMWAVEFORMAT wf; - - - wav = (_wavHeader *) data; - - if (soundOn) - { - if (speechStatus) - return(RDERR_SPEECHPLAYING); - - memset(&wf, 0, sizeof(PCMWAVEFORMAT)); - wf.wf.wFormatTag = WAVE_FORMAT_PCM; - wf.wf.nChannels = wav->channels; - wf.wf.nSamplesPerSec = wav->samplesPerSec; - wf.wBitsPerSample = 8 * wav->blockAlign / (wav->samplesPerSec * wav->channels); - wf.wf.nBlockAlign = wf.wf.nChannels * wf.wBitsPerSample / 8; - wf.wf.nAvgBytesPerSec = wf.wf.nSamplesPerSec * wf.wf.nBlockAlign; - - memset(&dsbd, 0, sizeof(DSBUFFERDESC)); - dsbd.dwSize = sizeof(DSBUFFERDESC); - // dsbd.dwFlags = DSBCAPS_CTRLDEFAULT; - dsbd.lpwfxFormat = (LPWAVEFORMATEX) &wf; - - // Set the sample size - search for the size of the data. - i = 0; - while (i<100) - { - if (*data == 'd') - { - data32 = (int32 *) data; - if (*data32 == 'atad') - break; - } - i += 1; - data++; - } - if (i == 100) - return(RDERR_INVALIDWAV); - - dsbd.dwBufferBytes = *(data32 + 1); - - // Create the speech sample buffer - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbSpeech, NULL); - if (hr != DS_OK) - return(RDERR_CREATESOUNDBUFFER); - - // Lock the speech buffer, ready to fill it with data - hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - if (hr == DSERR_BUFFERLOST) - { - IDirectSoundBuffer_Restore(dsbSpeech); - hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - } - - if (hr == DS_OK) - { - // Fill the speech buffer with data - memcpy((uint8 *) lpv1, (uint8 *) (data32 + 2), dwBytes1); - - if (dwBytes1 != dsbd.dwBufferBytes) - { - memcpy((uint8 *) lpv1 + dwBytes1, (uint8 *) (data32 + 2) + dwBytes1, dwBytes2); - } - - // Unlock the buffer now that we've filled it - IDirectSoundBuffer_Unlock(dsbSpeech, lpv1, dwBytes1, lpv2, dwBytes2); - - // Modify the volume according to the master volume - if (speechMuted) - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); - else - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[vol*speechVol]); - - IDirectSoundBuffer_SetPan(dsbSpeech, panTable[pan+16]); - - // Start the speech playing - IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0); - speechStatus = 1; - - } - else - { - IDirectSoundBuffer_Release(dsbSpeech); - return(RDERR_LOCKSPEECHBUFFER); - } - } -*/ - return(RD_OK); - -} - - -int32 Sword2Sound::AmISpeaking() -{ - warning("stub AmISpeaking"); -/* - int32 len; -// int32 status; - int32 readCursor, writeCursor; - int32 dwBytes1, dwBytes2; - int16 *sample; - int32 count = 0; - LPVOID lpv1, lpv2; - HRESULT hr; - -#define POSITIVE_THRESHOLD 350 -#define NEGATIVE_THRESHOLD -350 - if ((!speechMuted) && (!speechPaused) && (dsbSpeech)) - { - if (IDirectSoundBuffer_GetCurrentPosition(dsbSpeech, &readCursor, &writeCursor) != DS_OK) - { +int32 Sword2Sound::AmISpeaking() { + if ((!speechMuted) && (!speechPaused) && (soundHandleSpeech != -1)) { + if (g_engine->_mixer->isChannelActive(soundHandleSpeech)) return (RDSE_SPEAKING); - } - - len = 44100 / 12; - - hr = IDirectSoundBuffer_Lock(dsbSpeech, readCursor, len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - if (hr == DS_OK) - { - for (sample = (int16*)lpv1; sample<(int16*)((int8*)lpv1+dwBytes1); sample+= 90) // 20 samples - if (*sample>POSITIVE_THRESHOLD || *sample<NEGATIVE_THRESHOLD) - count++; - - IDirectSoundBuffer_Unlock(dsbSpeech,lpv1,dwBytes1,lpv2,dwBytes2); - - if (count>5) // 25% of the samples - return (RDSE_SPEAKING); - } - return (RDSE_QUIET); } - return (RDSE_SPEAKING); -*/ - return RDSE_QUIET; + return (RDSE_QUIET); } - -int32 Sword2Sound::GetCompSpeechSize(const char *filename, uint32 speechid) -{ - int32 i; +int32 Sword2Sound::GetCompSpeechSize(const char *filename, uint32 speechid) { + int32 i; uint32 speechIndex[2]; - FILE *fp; + File fp; - // Open the speech cluster and find the data offset & size - fp = fopen(filename, "rb"); - if (fp == NULL) + // Open the speech cluster and find the data offset & size + fp.open(filename, g_engine->getGameDataPath()); + if (fp.isOpen() == false) return(0); - if (fseek(fp, (++speechid)*8, SEEK_SET)) - { - fclose(fp); - return (0); - } + fp.seek((++speechid) * 8, SEEK_SET); - if (fread(speechIndex, sizeof(uint32), 2, fp) != 2) - { - fclose(fp); + if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { + fp.close(); return (0); } - if (!speechIndex[0] || !speechIndex[1]) - { - fclose(fp); + if (!speechIndex[0] || !speechIndex[1]) { + fp.close(); return (0); } - fclose(fp); + fp.close(); - i = (speechIndex[1]-1)*2 + sizeof(_wavHeader) + 8; + i = (speechIndex[1] - 1) * 2 + sizeof(_wavHeader) + 8; return(i); } - -int32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem) -{ - uint32 i; +int32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem) { + uint32 i; uint16 *data16; uint8 *data8; uint32 speechIndex[2]; _wavHeader *pwf = (_wavHeader *) waveMem; - FILE *fp; + File fp; // Open the speech cluster and find the data offset & size - fp = fopen(filename, "rb"); - if (fp == NULL) + fp.open(filename, g_engine->getGameDataPath()); + if (fp.isOpen() == false) return(RDERR_INVALIDFILENAME); - if (fseek(fp, (++speechid)*8, SEEK_SET)) - { - fclose(fp); - return (RDERR_READERROR); - } + fp.seek((++speechid) * 8, SEEK_SET); - if (fread(speechIndex, sizeof(uint32), 2, fp) != 2) - { - fclose(fp); + if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { + fp.close(); return (RDERR_READERROR); } - if (!speechIndex[0] || !speechIndex[1]) - { - fclose(fp); + if (!speechIndex[0] || !speechIndex[1]) { + fp.close(); return (RDERR_INVALIDID); } @@ -934,83 +433,64 @@ int32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uin data16 += 2; - *((uint32*)data16) = (speechIndex[1]-1)*2; + *((uint32*)data16) = (speechIndex[1] - 1) * 2; data16 += 2; - pwf->fileLength = (speechIndex[1]-1)*2 + sizeof(_wavHeader) + 8; - + pwf->fileLength = (speechIndex[1] - 1) * 2 + sizeof(_wavHeader) + 8; // Calculate position in buffer to load compressed sound into data8 = (uint8*)data16 + (speechIndex[1]-1); - if (fseek(fp, speechIndex[0], SEEK_SET)) - { - fclose(fp); - return (RDERR_INVALIDID); - } + fp.seek(speechIndex[0], SEEK_SET); - if (fread(data8, sizeof(uint8), speechIndex[1], fp) != speechIndex[1]) - { - fclose(fp); + if (fp.read(data8, speechIndex[1]) != speechIndex[1]) { + fp.close(); return (RDERR_INVALIDID); } - fclose(fp); + fp.close(); data16[0] = *((int16*)data8); // Starting Value - i=1; + i = 1; - while (i<(speechIndex[1]-1)) - { - if (GetCompressedSign(data8[i+1])) - data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); + while (i < (speechIndex[1] - 1)) { + if (GetCompressedSign(data8[i + 1])) + data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); else - data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); + data16[i] = data16[i - 1] + (GetCompressedAmplitude(data8[i + 1])<<GetCompressedShift(data8[i + 1])); i++; } return(RD_OK); } - -int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) -{ - - uint32 dwBytes1, dwBytes2; - uint32 i; +int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) { + uint32 i; uint16 *data16; - uint8 *data8; + uint8 *data8; uint32 speechIndex[2]; - void *lpv1; - File fp; + void *lpv1; + File fp; uint32 bufferSize; - if (!speechMuted) - { + if (!speechMuted) { if (GetSpeechStatus() == RDERR_SPEECHPLAYING) return RDERR_SPEECHPLAYING; - // Open the speech cluster and find the data offset & size - if (fp.open(filename, g_sword2->getGameDataPath()) == false) + // Open the speech cluster and find the data offset & size + fp.open(filename, g_engine->getGameDataPath()); + if (fp.isOpen() == false) return(RDERR_INVALIDFILENAME); - /* FIXME ? our fseek returns void not int - if (fp.seek((++speechid) * 8, SEEK_SET)) - { - fp.close(); - return (RDERR_READERROR); - } - */ - fp.seek((++speechid) * 8, SEEK_SET); - if (fp.read(speechIndex, sizeof(uint32) * 2) != (2 * sizeof(uint32))) - { + fp.seek((++speechid) * 8, SEEK_SET); + + if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) { fp.close(); return (RDERR_READERROR); } - if (speechIndex[0] == 0 || speechIndex[1] == 0) - { + if (speechIndex[0] == 0 || speechIndex[1] == 0) { fp.close(); return (RDERR_INVALIDID); } @@ -1018,23 +498,14 @@ int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 v bufferSize = (speechIndex[1] - 1) * 2; // Create tempory buffer for compressed speech - if ((data8 = (uint8 *)malloc(speechIndex[1])) == NULL) - { + if ((data8 = (uint8 *)malloc(speechIndex[1])) == NULL) { fp.close(); return(RDERR_OUTOFMEMORY); } - /* FIXME ? see above - if (fp.seek(speechIndex[0], SEEK_SET)) - { - fp.close(); - free(data8); - return (RDERR_INVALIDID); - } - */ + fp.seek(speechIndex[0], SEEK_SET); - if (fp.read(data8, sizeof(uint8) * speechIndex[1]) != (speechIndex[1] * sizeof(uint8))) - { + if (fp.read(data8, speechIndex[1]) != speechIndex[1]) { fp.close(); free(data8); return (RDERR_INVALIDID); @@ -1042,240 +513,187 @@ int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 v fp.close(); - // Create the speech sample buffer - /* - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbSpeech, NULL); - if (hr != DS_OK) - { - free(data8); - return(RDERR_CREATESOUNDBUFFER); - } - - // Lock the speech buffer, ready to fill it with data - hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - if (hr == DSERR_BUFFERLOST) - { - IDirectSoundBuffer_Restore(dsbSpeech); - hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - } - */ - lpv1 = malloc(bufferSize); - dwBytes1 = dwBytes2 = bufferSize; - if (1 /*hr == DS_OK*/) - { - // decompress data into speech buffer. - data16 = (uint16*)lpv1; + // decompress data into speech buffer. + data16 = (uint16*)lpv1; - data16[0] = *((int16*)data8); // Starting Value - i=1; - - while (i<dwBytes1/2) - { - if (GetCompressedSign(data8[i+1])) - data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); - else - data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); - - - i++; - } - - if (dwBytes1 != bufferSize) - { - while (i<(dwBytes1+dwBytes2)/2) - { - if (GetCompressedSign(data8[i+1])) - data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); - else - data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); - - - i++; - } - } - - free(data8); - - // Unlock the buffer now that we've filled it - //IDirectSoundBuffer_Unlock(dsbSpeech, lpv1, dwBytes1, lpv2, dwBytes2); + data16[0] = *((int16*)data8); // Starting Value + i = 1; - // Modify the volume according to the master volume - /* - if (speechMuted) - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); + while (i < bufferSize / 2) { + if (GetCompressedSign(data8[i + 1])) + data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); else - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[vol*speechVol]); + data16[i] = data16[i - 1] + (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1])); + i++; + } - IDirectSoundBuffer_SetPan(dsbSpeech, panTable[pan+16]); - */ + free(data8); - //TODO: Implement volume change + panning - - // Start the speech playing - speechPaused = 1; -// IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0); + // Modify the volume according to the master volume + if (speechMuted) { +// IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[vol*speechVol]); + } +// IDirectSoundBuffer_SetPan(dsbSpeech, panTable[pan+16]); + + // Start the speech playing + speechPaused = 1; - uint32 flags = SoundMixer::FLAG_16BITS; - flags |= SoundMixer::FLAG_AUTOFREE; + uint32 flags = SoundMixer::FLAG_16BITS; + flags |= SoundMixer::FLAG_AUTOFREE; - //Until the mixer supports LE samples natively, we need to convert our LE ones to BE - for (uint j = 0; j < (bufferSize / 2); j++) - data16[j] = TO_BE_16(data16[j]); + //Until the mixer supports LE samples natively, we need to convert our LE ones to BE + for (uint j = 0; j < (bufferSize / 2); j++) + data16[j] = TO_BE_16(data16[j]); - PlayingSoundHandle speechHandle = 0; - _mixer->playRaw(&speechHandle, data16, bufferSize, 22050, flags); + soundHandleSpeech = -1; + _mixer->playRaw(&soundHandleSpeech, data16, bufferSize, 22050, flags); - speechStatus = 1; - } - else - { - //IDirectSoundBuffer_Release(dsbSpeech); - free(data8); - return(RDERR_LOCKSPEECHBUFFER); - } + speechStatus = 1; } DipMusic(); - - // return read error for now so we get subtitles - return (RDERR_READERROR); + return (RD_OK); } -int32 Sword2Sound::StopSpeechSword2(void) - -{ - warning("stub StopSpeechSword2"); -/* - int32 status; - - +int32 Sword2Sound::StopSpeechSword2(void) { if (!soundOn) return(RD_OK); - if (speechStatus) - { - IDirectSoundBuffer_GetStatus(dsbSpeech, &status); - if (status & DSBSTATUS_PLAYING) - { - IDirectSoundBuffer_Stop(dsbSpeech); -// SetMusicVolume(GetMusicVolume()); - } - - IDirectSoundBuffer_Release(dsbSpeech); - dsbSpeech = 0; + if (speechStatus) { + g_engine->_mixer->stopHandle(soundHandleSpeech); + soundHandleSpeech = -1; speechStatus = 0; return(RD_OK); } -*/ return(RDERR_SPEECHNOTPLAYING); - } - - -int32 Sword2Sound::GetSpeechStatus(void) -{ - warning("stub GetSpeechStatus"); -/* - int32 status; - - +int32 Sword2Sound::GetSpeechStatus(void) { if ((!soundOn) || (!speechStatus)) return(RDSE_SAMPLEFINISHED); if (speechPaused) return(RDSE_SAMPLEPLAYING); - IDirectSoundBuffer_GetStatus(dsbSpeech, &status); - if (!(status & DSBSTATUS_PLAYING)) - { + if (g_engine->_mixer->isChannelActive(soundHandleSpeech) == false) { speechStatus = 0; - IDirectSoundBuffer_Release(dsbSpeech); - dsbSpeech = 0; -// SetMusicVolume(GetMusicVolume()); + soundHandleSpeech = -1; return(RDSE_SAMPLEFINISHED); } return(RDSE_SAMPLEPLAYING); -*/ - return RDSE_SAMPLEFINISHED; - } - -void Sword2Sound::SetSpeechVolume(uint8 volume) -{ - warning("stub SetSpeechVolume"); -/* +void Sword2Sound::SetSpeechVolume(uint8 volume) { speechVol = volume; - if (dsbSpeech && !speechMuted && GetSpeechStatus() == RDSE_SAMPLEPLAYING) - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); -*/ + if ((soundHandleSpeech != -1) && !speechMuted && GetSpeechStatus() == RDSE_SAMPLEPLAYING) { +// IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); + } } - -uint8 Sword2Sound::GetSpeechVolume() -{ +uint8 Sword2Sound::GetSpeechVolume() { return speechVol; } - -void Sword2Sound::MuteSpeech(uint8 mute) -{ - warning("stub MuteSpeech( %d )", mute); -/* +void Sword2Sound::MuteSpeech(uint8 mute) { speechMuted = mute; - if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) - { - if (mute) - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); - else - IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); + if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) { + if (mute) { +// IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); + } } -*/ } - -uint8 Sword2Sound::IsSpeechMute(void) -{ +uint8 Sword2Sound::IsSpeechMute(void) { return (speechMuted); } - -int32 Sword2Sound::PauseSpeech(void) -{ - warning("PauseSpeech"); -/* - if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) - { +int32 Sword2Sound::PauseSpeech(void) { + if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) { speechPaused = 1; - return (IDirectSoundBuffer_Stop(dsbSpeech)); + g_engine->_mixer->pauseChannels(true); } -*/ return(RD_OK); } -int32 Sword2Sound::UnpauseSpeech(void) -{ - warning("UnpauseSpeech"); -/* - if (speechPaused) - { +int32 Sword2Sound::UnpauseSpeech(void) { + if (speechPaused) { speechPaused = 0; - return (IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0)); + g_engine->_mixer->pauseChannels(false); } -*/ return(RD_OK); } +int32 Sword2Sound::OpenFx(int32 id, uint8 *data) { + int32 i, fxi; + uint32 *data32; + _wavHeader *wav; + + wav = (_wavHeader *) data; + + if (soundOn) { + // Check for a valid id. + if (id == 0) + return(RDERR_INVALIDID); + + // Check that the fx is not already open + for (i = 0; i < MAXFX; i++) { + if (fxId[i] == id) + return(RDERR_FXALREADYOPEN); + } + + // Now choose a free slot for the fx + fxi = 0; + while (fxi < MAXFX) { + if (fxId[fxi] == 0) + break; + fxi++; + } + + if (fxi == MAXFX) + 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; + if (*data32 == 'atad') + break; + } + i += 1; + data++; + } + if (i == 100) + return(RDERR_INVALIDWAV); + + bufferSizeFx[fxi] = *(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 (wav->channels == 2) + flagsFx[fxi] |= SoundMixer::FLAG_STEREO; + + //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] = TO_BE_16(bufferFx[fxi][j]); -int32 Sword2Sound::OpenFx(int32 id, uint8 *data) + fxId[fxi] = id; + fxCached[fxi] = RDSE_FXCACHED; + } + return(RD_OK); -{ - warning("stub OpenFx( %d )", id); /* uint32 dwBytes1, dwBytes2; int32 i, fxi; @@ -1381,16 +799,116 @@ int32 Sword2Sound::OpenFx(int32 id, uint8 *data) fxCached[fxi] = RDSE_FXCACHED; } -*/ return(RD_OK); - +*/ } +int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) { + int32 i, loop; + HRESULT hr; +return RD_OK; + if (type == RDSE_FXLOOP) + loop = 1; + else + loop = 0; -int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) + if (soundOn) { + if (data == NULL) { + if (type == RDSE_FXLEADOUT) { + id = 0xffffffff; + i = GetFxIndex(id); + if (i == MAXFX) { + return(RDERR_FXNOTOPEN); + } + fxLooped[i] = 0; + flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + + // Start the sound effect playing + if (musicMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbFx[i], musicVolTable[volMusic[0]]); + } +// IDirectSoundBuffer_SetPan(dsbFx[i], 0); + g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], 22050, flagsFx[i]); + + fxCached[i] = RDSE_FXTOCLEAR; + } else { + i = GetFxIndex(id); + if (i == MAXFX) { + return(RDERR_FXNOTOPEN); + } + fxLooped[i] = loop; + if (loop == 1) + flagsFx[i] |= SoundMixer::FLAG_LOOP; + else + flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + + fxVolume[i] = vol; + + // Start the sound effect playing + if (fxMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); + } +// IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); + + g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], 22050, flagsFx[i]); + if (id == 0xffffffff) { + fxCached[i] = RDSE_FXTOCLEAR; + } + } + } else { + if (type == RDSE_FXLEADIN) { + id = 0xfffffffe; + hr = OpenFx(id, data); + if (hr != RD_OK) { + return hr; + } + i = GetFxIndex(id); + if (i == MAXFX) { + return RDERR_FXFUCKED; + } + fxCached[i] = RDSE_FXTOCLEAR; + if (musicMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbFx[i], musicVolTable[volMusic[0]]); + } +// IDirectSoundBuffer_SetPan(dsbFx[i], 0); + g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], 22050, flagsFx[i]); + } else { + hr = OpenFx(id, data); + if (hr != RD_OK) { + return(hr); + } + + i = GetFxIndex(id); + if (i == MAXFX) { + return(RDERR_FXFUCKED); + } + fxCached[i] = RDSE_FXTOCLEAR; + fxLooped[i] = loop; + if (loop == 1) + flagsFx[i] |= SoundMixer::FLAG_LOOP; + else + flagsFx[i] &= ~SoundMixer::FLAG_LOOP; + fxVolume[i] = vol; + + // Start the sound effect playing + if (fxMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); + } +// IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); + g_engine->_mixer->playRaw(&soundHandleFx[i], bufferFx[i], bufferSizeFx[i], 22050, flagsFx[i]); + } + } + } + return(RD_OK); -{ - warning("stub PlayFx( %d, %d, %d, %d )", id, vol, pan, type); /* int32 i, loop; HRESULT hr; @@ -1487,839 +1005,414 @@ int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type } } } -*/ return(RD_OK); - +*/ } - -int32 Sword2Sound::SetFxVolumePan(int32 id, uint8 vol, int8 pan) -{ - warning("stub SetFxVolumePan( %d, %d, %d )", id, vol, pan); -/* +int32 Sword2Sound::SetFxVolumePan(int32 id, uint8 vol, int8 pan) { int32 i = GetFxIndex(id); if (i == MAXFX) return RDERR_FXNOTOPEN; fxVolume[i] = vol; - if (!fxMuted) - IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); - IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); -*/ + if (!fxMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); +// IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); + } return RD_OK; } -int32 Sword2Sound::SetFxIdVolume(int32 id, uint8 vol) -{ - warning("stub SetFxIdVolume( %d, %d )", id, vol); -/* +int32 Sword2Sound::SetFxIdVolume(int32 id, uint8 vol) { int32 i = GetFxIndex(id); if (i == MAXFX) return RDERR_FXNOTOPEN; fxVolume[i] = vol; - if (!fxMuted) - IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); -*/ + if (!fxMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); + } return RD_OK; } - - -int32 Sword2Sound::ClearAllFx(void) - -{ - warning("stub ClearAllFx"); -/* - int32 status; - int32 i; - +int32 Sword2Sound::ClearAllFx(void) { + int i; if (!soundOn) return(RD_OK); i = 0; - while (i < MAXFX) - { - if ((fxId[i]) && (fxId[i] != 0xfffffffe) && (fxId[i] != 0xffffffff)) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) - { - IDirectSoundBuffer_Stop(dsbFx[i]); - } - IDirectSoundBuffer_Release(dsbFx[i]); + while (i < MAXFX) { + if ((fxId[i]) && (fxId[i] != 0xfffffffe) && (fxId[i] != 0xffffffff)) { + g_engine->_mixer->stopHandle(soundHandleFx[i]); fxId[i] = 0; fxiPaused[i] = 0; + if (bufferFx[i] != NULL) { + free(bufferFx[i]); + bufferFx[i] = NULL; + } + bufferSizeFx[i] = 0; + flagsFx[i] = 0; } i++; } - -*/ return(RD_OK); - } - -int32 Sword2Sound::CloseFx(int32 id) - -{ - warning("stub CloseFx( %d )", id); -/* - int32 i; - int32 status; - +int32 Sword2Sound::CloseFx(int32 id) { + int i; if (!soundOn) return(RD_OK); i = GetFxIndex(id); - if (i<MAXFX) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) - { - IDirectSoundBuffer_Stop(dsbFx[i]); - } - - IDirectSoundBuffer_Release(dsbFx[i]); + 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; + } + bufferSizeFx[i] = 0; + flagsFx[i] = 0; } -*/ return(RD_OK); - } +int32 Sword2Sound::PauseFx(void) { + int i; -int32 Sword2Sound::PauseFx(void) - -{ - warning("stub PauseFx"); -/* - int32 i; - int32 status; - - if (!fxPaused) - { - for (i=0; i<MAXFX; i++) - { - if (fxId[i]) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) - { - fxiPaused[i] = 1; - if (IDirectSoundBuffer_Stop(dsbFx[i]) != RD_OK) - return(RDERR_FXFUCKED); - } - } - else - { + if (!fxPaused) { + for (i = 0; i < MAXFX; i++) { + if (fxId[i]) { + g_engine->_mixer->pauseChannels(true); + fxiPaused[i] = 1; + } else { fxiPaused[i] = 0; } } fxPaused = 1; } -*/ return (RD_OK); - } +int32 Sword2Sound::PauseFxForSequence(void) { + int i; -int32 Sword2Sound::PauseFxForSequence(void) - -{ - warning("stub PauseFxForSequence"); -/* - int32 i; - int32 status; - - if (!fxPaused) - { - for (i=0; i<MAXFX; i++) - { - if ((fxId[i]) && (fxId[i] != 0xfffffffe)) - { - IDirectSoundBuffer_GetStatus(dsbFx[i], &status); - if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) - { - fxiPaused[i] = 1; - IDirectSoundBuffer_Stop(dsbFx[i]); - } - } - else - { + if (!fxPaused) { + for (i = 0; i<MAXFX; i++) { + if ((fxId[i]) && (fxId[i] != 0xfffffffe)) { + g_engine->_mixer->stopHandle(soundHandleFx[i]); + fxiPaused[i] = 1; + } else { fxiPaused[i] = 0; } } fxPaused = 1; } -*/ return (RD_OK); - } +int32 Sword2Sound::UnpauseFx(void) { + int i; - -int32 Sword2Sound::UnpauseFx(void) - -{ - warning("stub UnpauseFx"); -/* - int32 i; - - if (fxPaused) - { - for (i=0; i<MAXFX; i++) - { - if (fxiPaused[i] && fxId[i]) - { - if (IDirectSoundBuffer_Play(dsbFx[i], 0, 0, fxLooped[i]) != RD_OK) - return(RDERR_FXFUCKED); + if (fxPaused) { + for (i = 0; i < MAXFX; i++) { + if (fxiPaused[i] && fxId[i]) { + g_engine->_mixer->pauseChannels(false); } } fxPaused = 0; } -*/ return (RD_OK); } - - -uint8 Sword2Sound::GetFxVolume() -{ +uint8 Sword2Sound::GetFxVolume() { return fxVol; } - -void Sword2Sound::SetFxVolume(uint8 volume) -{ - warning("stub SetFxVolume( %d )", volume); -/* +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) - IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); + for (fxi = 0; fxi < MAXFX; fxi++) { + if (fxId[fxi] && !fxMuted) { +// IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); + } } -*/ } - -void Sword2Sound::MuteFx(uint8 mute) -{ - warning("stub MuteFx( %d )", mute); -/* +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) - IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[0]); - else - IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); + for (fxi = 0; fxi < MAXFX; fxi++) { + if (fxId[fxi]) { + if (mute) { +// IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); + } } } -*/ } -uint8 Sword2Sound::IsFxMute(void) -{ +uint8 Sword2Sound::IsFxMute(void) { return (fxMuted); } - - - -void Sword2Sound::StartMusicFadeDown(int i) - -{ - -// IDirectSoundBuffer_Stop(lpDsbMus[i]); -// IDirectSoundBuffer_Release(lpDsbMus[i]); +void Sword2Sound::StartMusicFadeDown(int i) { + g_engine->_mixer->endStream(soundHandleMusic[i]); musFading[i] = -16; -// musStreaming[i] = 0; - fpMus[i].close(); - + musStreaming[i] = 0; + fpMus.close(); } - -int32 Sword2Sound::StreamMusic(uint8 *filename, int32 looping) - -{ - warning("stub StreamMusic( %s, %d )", filename, looping); -/* - - HRESULT hr; - LPVOID lpv1, lpv2; - DWORD dwBytes1, dwBytes2; - int32 i; +int32 Sword2Sound::StreamCompMusic(const char *filename, uint32 musicId, int32 looping) { + int32 i, j; int32 v0, v1; - int32 bytes; - _wavHeader head; - - // Do not allow compressed and uncompressed music to be streamed at the same time. - if (compressedMusic == 1) - return (RDERR_FXFUCKED); - - compressedMusic = 2; - + uint16 *data16; + uint8 *data8; - if (musStreaming[0] + musStreaming[1] == 0) - { + compressedMusic = 1; + if (musStreaming[0] + musStreaming[1] == 0) { i = 0; - fpMus[i] = fopen(filename, "rb"); - if (fpMus[i] == NULL) - return(RDERR_INVALIDFILENAME); - - fread(&head, sizeof(_wavHeader), 1, fpMus[i]); - streamCursor[i] = 0; - musLooping[i] = looping; - - - memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT)); - wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; - wfMus[i].wf.nChannels = head.channels; - wfMus[i].wf.nSamplesPerSec = head.samplesPerSec; - wfMus[i].wBitsPerSample = 8 * head.blockAlign / (head.samplesPerSec * head.channels); - wfMus[i].wf.nBlockAlign = wfMus[i].wf.nChannels * wfMus[i].wBitsPerSample / 8; - wfMus[i].wf.nAvgBytesPerSec = wfMus[i].wf.nSamplesPerSec * wfMus[i].wf.nBlockAlign; - - - // Reset the sample format and size - memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); - dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); -// dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; - dsbdMus[i].dwBufferBytes = 3 * wfMus[i].wf.nAvgBytesPerSec; // 3 seconds - dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; - - // Create the sound effect sample buffer - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); - if (hr == DS_OK) - { - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - - if (hr == DSERR_BUFFERLOST) - { - IDirectSoundBuffer_Restore(lpDsbMus[i]); - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - } - - if (hr == DS_OK) - { - - // Fill the speech buffer with data - bytes = fread(lpv1, 1, dwBytes1, fpMus[i]); -// memcpy((uint8 *) lpv1, (uint8 *) wavData + sizeof(wavHeader), dwBytes1); - - // Unlock the buffer now that we've filled it - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - - // Modify the volume according to the master volume and music mute state - if (musicMuted) - v0 = v1 = 0; - else - { - v0 = volMusic[0]; - v1 = volMusic[1]; - } - - if (v0 > v1) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); - } - else - { - if (v1 > v0) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); - } - else - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); - } - } - - - // Start the sound effect playing - IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); - - musStreaming[i] = 1; - musCounter[i] = 250; - strcpy(musFilename[i], filename); - - // and exit the function. - } - else - { -// Pdebug("Failed to lock sound buffer upon creation - (%d)", hr & 0x0000ffff); -// DirectSoundDebug("Error - ", hr); - fclose(fpMus[i]); - return(RDERR_LOCKFAILED); - } - } - else - { -// Pdebug("Failed to create sound buffer - (%d)", hr & 0x0000ffff); -// Pdebug("Error - ", hr); - fclose(fpMus[i]); - return(RDERR_CREATESOUNDBUFFER); - } - } - else if (musStreaming[0] + musStreaming[1] == 1) - { - - i = musStreaming[0]; - musLooping[i] = looping; + musLooping[i] = looping; // Save looping info + strcpy(musFilename[i], filename); // And tune id's + musId[i] = musicId; - if (!musFading[1-i]) - StartMusicFadeDown(1 - i); + if (IsMusicMute()) // Don't start streaming if the volume is off. + return (RD_OK); - fpMus[i] = fopen(filename, "rb"); - if (fpMus[i] == NULL) + fpMus.open(filename, g_engine->getGameDataPath()); // Always use fpMus[0] (all music in one cluster) musFilePos[i] for different pieces of music. + if (fpMus.isOpen() == false) return(RDERR_INVALIDFILENAME); - fread(&head, sizeof(_wavHeader), 1, fpMus[i]); - streamCursor[i] = 0; - - - memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT)); - wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; - wfMus[i].wf.nChannels = head.channels; - wfMus[i].wf.nSamplesPerSec = head.samplesPerSec; - wfMus[i].wBitsPerSample = 8 * head.blockAlign / (head.samplesPerSec * head.channels); - wfMus[i].wf.nBlockAlign = wfMus[i].wf.nChannels * wfMus[i].wBitsPerSample / 8; - wfMus[i].wf.nAvgBytesPerSec = wfMus[i].wf.nSamplesPerSec * wfMus[i].wf.nBlockAlign; - - - // Reset the sample format and size - memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); - dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); -// dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; - dsbdMus[i].dwBufferBytes = 6 * wfMus[i].wf.nAvgBytesPerSec; // 3 seconds - dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; - - // Create the sound effect sample buffer - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); - if (hr == DS_OK) - { - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - - if (hr == DSERR_BUFFERLOST) - { - IDirectSoundBuffer_Restore(lpDsbMus[i]); - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - } - - if (hr == DS_OK) - { - - // Fill the speech buffer with data - bytes = fread(lpv1, 1, dwBytes1, fpMus[i]); -// Pdebug("Read %d bytes\n", bytes); -// memcpy((uint8 *) lpv1, (uint8 *) wavData + sizeof(_wavHeader), dwBytes1); - - // Unlock the buffer now that we've filled it - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - - // Modify the volume according to the master volume and music mute state - if (musicMuted) - v0 = v1 = 0; - else - { - v0 = volMusic[0]; - v1 = volMusic[1]; - } + fpMus.seek((musicId + 1) * 8, SEEK_SET); + if (fpMus.read(&musFilePos[i], sizeof(uint32)) != sizeof(uint32)) { + fpMus.close(); + return (RDERR_READERROR); + } - if (v0 > v1) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); - } - else - { - if (v1 > v0) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); - } - else - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); - } - } - - - // Start the sound effect playing - IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); - - musStreaming[i] = 1; - musCounter[i] = 250; - strcpy(musFilename[i], filename); - - } - else - { -// Pdebug("Failed to lock sound buffer upon creation - (%d)", hr & 0x0000ffff); -// DirectSoundDebug("Error - ", hr); - fclose(fpMus[i]); - return(RDERR_LOCKFAILED); - } - } - else - { -// Pdebug("Failed to create sound buffer - (%d)", hr & 0x0000ffff); -// Pdebug("Error - ", hr); - fclose(fpMus[i]); - return(RDERR_CREATESOUNDBUFFER); + if (fpMus.read(&musEnd[i], sizeof(uint32)) != sizeof(uint32)) { + fpMus.close(); + return (RDERR_READERROR); } - } -*/ - return(RD_OK); -} + if (!musEnd[i] || !musFilePos[i]) { + fpMus.close(); + return (RDERR_INVALIDID); + } + musEnd[i] += musFilePos[i]; // Calculate the file position of the end of the music -void Sword2Sound::UpdateSampleStreaming(void) + // Create a temporary buffer + data8 = (uint8*)malloc(bufferSizeMusic / 2); + if (data8 == NULL) { + fpMus.close(); + return(RDERR_OUTOFMEMORY); + } -{ - warning("stub UpdateSampleStreaming"); -/* + // Seek to start of the compressed music + fpMus.seek(musFilePos[i], SEEK_SET); - int32 i; - int32 v0, v1; - int32 readLen; - int32 len; - int32 readCursor, writeCursor; - int32 dwBytes1, dwBytes2; - LPVOID lpv1, lpv2; - HRESULT hr; + // Read the compressed data in to the buffer + if (fpMus.read(data8, bufferSizeMusic / 2) != bufferSizeMusic / 2) { + fpMus.close(); + free(data8); + return (RDERR_INVALIDID); + } + // Store the current position in the file for future streaming + musFilePos[i] = fpMus.pos(); - for (i=0; i<MAXMUS; i++) - { - if (musStreaming[i]) - { - if (musFading[i]) - { - if (musFading[i] < 0) - { - if (++musFading[i] == 0) - { - IDirectSoundBuffer_Stop(lpDsbMus[i]); - IDirectSoundBuffer_Release(lpDsbMus[i]); - musStreaming[i] = 0; - } - else - { - // 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); - } + // decompress the music into the music buffer. + data16 = (uint16 *)malloc(bufferSizeMusic); + + data16[0] = *((int16 *)data8); // First sample value + j = 1; - if (v0 > v1) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); - } - else - { - if (v1 > v0) - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); - } - else - { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); - } - } - } - } - } + while (j < (bufferSizeMusic / 2) - 1) { + if (GetCompressedSign(data8[j + 1])) + data16[j] = data16[j - 1] - (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); else - { - - if (IDirectSoundBuffer_GetCurrentPosition(lpDsbMus[i], &readCursor, &writeCursor) != DS_OK) - { -// Pdebug ("Stopping sample %d cos cant get position", i); - IDirectSoundBuffer_Stop(lpDsbMus[i]); - } + data16[j] = data16[j - 1] + (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); + j++; + } + // Store the value of the last sample ready for next batch of decompression + musLastSample[i] = data16[j - 1]; - len = readCursor - streamCursor[i]; - if (len < 0) - { - len += dsbdMus[i].dwBufferBytes; - } - if (len > 0) - { - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - if (hr == DSERR_BUFFERLOST) - { - IDirectSoundBuffer_Restore(lpDsbMus[i]); - hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); - } + // Free the decompression buffer and unlock the buffer now that we've filled it + free(data8); - if (hr == DS_OK) - { - streamCursor[i] += len; - if (streamCursor[i] >= (int32) dsbdMus[i].dwBufferBytes) - streamCursor[i] -= dsbdMus[i].dwBufferBytes; + // Modify the volume according to the master volume and music mute state + if (musicMuted) + v0 = v1 = 0; + else { + v0 = volMusic[0]; + v1 = volMusic[1]; + } - if (len > dwBytes1) - { - readLen = fread(lpv1, 1, dwBytes1, fpMus[i]); - if (readLen == dwBytes1) - { - readLen = fread(lpv2, 1, dwBytes2, fpMus[i]); - if (readLen != dwBytes2) - { - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - StartMusicFadeDown(i); - if (musLooping[i]) - { - StreamMusic(musFilename[i], musLooping[i]); - } - } - else - { - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - } - } - else - { - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - StartMusicFadeDown(i); - if (musLooping[i]) - { - StreamMusic(musFilename[i], musLooping[i]); - } - } - } - else - { - readLen = fread(lpv1, 1, len, fpMus[i]); - if (readLen != len) - { - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - StartMusicFadeDown(i); - if (musLooping[i]) - { - StreamMusic(musFilename[i], musLooping[i]); - } - } - else - { - IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); - } - } - } -// else -// { -// DirectSoundDebug("Failed to lock sound buffer to write bytes", hr); -// Pdebug("Stream cursor %d", streamCursor[i]); -// Pdebug("len %d", len); -// } - } - //} + if (v0 > v1) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); + } else { + if (v1 > v0) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); + } else { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); } } - } -*/ -} + //Until the mixer supports LE samples natively, we need to convert our LE ones to BE + for (int32 j = 0; j < (bufferSizeMusic / 2); j++) { + data16[j] = TO_BE_16(data16[j]); + } + if (soundHandleMusic[i] == -1) { + soundHandleMusic[i] = g_engine->_mixer->newStream(data16, bufferSizeMusic, 22050, SoundMixer::FLAG_16BITS, 100000); + } else { + g_engine->_mixer->appendStream(soundHandleMusic[i], data16, bufferSizeMusic); + } -int32 Sword2Sound::StreamCompMusic(const char *filename, const char *directory, uint32 musicId, int32 looping) { - // FIXME: Find a good buffer size. The original code mentions three - // seconds. - uint32 buffer_size = 32768; - uint32 i, j; - int32 v0, v1; - uint16 *data16; - uint8 *data8; - - warning("stub StreamCompMusic( %s, %d, %d )", filename, musicId, looping); - - // Do not allow compressed and uncompressed music to be streamed at - // the same time. - if (compressedMusic == 2) - return RDERR_FXFUCKED; - - compressedMusic = 1; + free(data16); - if (musStreaming[0] + musStreaming[1] == 2) { - // Both streams in use, try to find a fading stream + // Recorder some last variables + musStreaming[i] = 1; + musCounter[i] = 250; + } else if (musStreaming[0] + musStreaming[1] == 2) { if (musFading[0]) i = 0; else i = 1; - + musFading[i] = 0; - _mixer->stop(musicChannels[i]); + g_engine->_mixer->endStream(soundHandleMusic[i]); musStreaming[i] = 0; - } + } else if (musStreaming[0] + musStreaming[1] == 1) { + i = musStreaming[0]; // Set i to the free channel - if (musStreaming[0] + musStreaming[1] == 1) { - // Set i to the free channel - i = musStreaming[0]; - } else { - // No music streaming at present - i = 0; - } + musLooping[i] = looping; // Save looping info + strcpy(musFilename[i], filename); // And tune id's + musId[i] = musicId; - musLooping[i] = looping; // Save looping info - strcpy(musFilename[i], filename); // And tune id's - musId[i] = musicId; + if (IsMusicMute()) // Don't start streaming if the volume is off. + return (RD_OK); - // Don't start streaming if the volume is off. - if (IsMusicMute()) - return RD_OK; + if (fpMus.isOpen() == false) + fpMus.open(filename, g_engine->getGameDataPath()); // Always use fpMus[0] (all music in one cluster) musFilePos[i] for different pieces of music. + if (fpMus.isOpen() == false) + return(RDERR_INVALIDFILENAME); - // Always use fpMus[0] (all music in one cluster) - // musFilePos[i] for different pieces of music. - if (!fpMus[0].isOpen()) { - if (!fpMus[0].open(filename, directory)) - return RDERR_INVALIDFILENAME; - } + if (!musFading[1 - i]) // Start other music stream fading out + musFading[1 - i] = -16; - if (musStreaming[0] + musStreaming[1] == 1) { - // Start other music stream fading out - if (!musFading[i - 1]) - musFading[i - 1] = -16; + fpMus.seek((musicId + 1) * 8, SEEK_SET); - // Restart the streaming cursor for this sample - streamCursor[i] = 0; - } + if (fpMus.read(&musFilePos[i], sizeof(uint32)) != sizeof(uint32)) { + fpMus.close(); + return (RDERR_READERROR); + } - // Seek to music index - fpMus[0].seek((musicId + 1) * 8); + if (fpMus.read(&musEnd[i], sizeof(uint32)) != sizeof(uint32)) { + fpMus.close(); + return (RDERR_READERROR); + } - musFilePos[i] = fpMus[0].readUint32LE(); - musEnd[i] = fpMus[0].readUint32LE(); + if (!musEnd[i] || !musFilePos[i]) { + fpMus.close(); + return (RDERR_INVALIDID); + } - // Check that music is valid (has length & offset) - if (!musEnd[i] || !musFilePos[i]) { - fpMus[0].close(); - return RDERR_INVALIDID; - } + musEnd[i] += musFilePos[i]; // Calculate the file position of the end of the music - // Calculate the file position of the end of the music - musEnd[i] += musFilePos[i]; + // Allocate a compressed data buffer + data8 = (uint8*)malloc(bufferSizeMusic); + if (data8 == NULL) { + fpMus.close(); + return(RDERR_OUTOFMEMORY); + } - // Reset streaming cursor and store looping flag - streamCursor[i] = 0; + // Seek to start of the compressed music + fpMus.seek(musFilePos[i], SEEK_SET); - // Allocate a temporary buffer for compressed data - data8 = (uint8 *) malloc(buffer_size / 2); - if (!data8) { - fpMus[0].close(); - return RDERR_OUTOFMEMORY; - } + // Read the compressed data in to the buffer + if (fpMus.read(data8, bufferSizeMusic / 2) != bufferSizeMusic / 2) { + fpMus.close(); + free(data8); + return (RDERR_INVALIDID); + } + + // Store the current position in the file for future streaming + musFilePos[i] = fpMus.pos(); - // Allocate a buffer for the decoded sound - data16 = (uint16 *) malloc(buffer_size); - if (!data16) { - fpMus[0].close(); - free(data8); - return RDERR_OUTOFMEMORY; - } + // decompress the music into the music buffer. + data16 = (uint16 *)malloc(bufferSizeMusic); + + data16[0] = *((int16 *)data8); // First sample value + j = 1; - lpDsbMus[i] = data16; + while (j < (bufferSizeMusic / 2) - 1) { + if (GetCompressedSign(data8[j + 1])) + data16[j] = data16[j - 1] - (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); + else + data16[j] = data16[j - 1] + (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); + j++; + } - // Seek to start of the compressed music - fpMus[0].seek(musFilePos[i]); + // Store the value of the last sample ready for next batch of decompression + musLastSample[i] = data16[j - 1]; - // Read the compressed data in to the buffer - if (fpMus[0].read(data8, buffer_size / 2) != buffer_size / 2) { - fpMus[0].close(); + // Free the compressiong buffer and unlock the buffer now that we've filled it free(data8); - free(data16); - return RDERR_INVALIDID; - } - - // Store the current position in the file for future streaming - musFilePos[i] = fpMus[0].pos(); - - // Decompress the sound into the buffer - // First sample value - data16[0] = READ_LE_UINT16(data8); - j = 1; + // Modify the volume according to the master volume and music mute state + if (musicMuted) + v0 = v1 = 0; + else { + v0 = volMusic[0]; + v1 = volMusic[1]; + } - while (j < (buffer_size / 2) - 1) { - if (GetCompressedSign(data8[j + 1])) - data16[j] = data16[j - 1] - (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); - else - data16[j] = data16[j - 1] + (GetCompressedAmplitude(data8[j + 1]) << GetCompressedShift(data8[j + 1])); - j++; - } + if (v0 > v1) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); + } else { + if (v1 > v0) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); + } else { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); + } + } - // Store the value of the last sample ready for next batch of - // decompression - musLastSample[i] = data16[j - 1]; + //Until the mixer supports LE samples natively, we need to convert our LE ones to BE + for (int32 j = 0; j < (bufferSizeMusic / 2); j++) + data16[j] = TO_BE_16(data16[j]); - // Free the decompression buffer - free(data8); + if (soundHandleMusic[i] == -1) { + soundHandleMusic[i] = g_engine->_mixer->newStream(data16, bufferSizeMusic, 22050, SoundMixer::FLAG_16BITS, 100000); + } else { + g_engine->_mixer->appendStream(soundHandleMusic[i], data16, bufferSizeMusic); + } - // Modify the volume according to the master volume and music - // mute state - if (musicMuted) - v0 = v1 = 0; - else { - v0 = volMusic[0]; - v1 = volMusic[1]; - } + free(data16); -#if 0 - if (v0 > v1) { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); - } else if (v1 > v0) { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); - } else { - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); - IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); + // Record the last variables for streaming and looping + musStreaming[i] = 1; + musCounter[i] = 250; } -#else - warning("FIXME: Implement volume and panning"); -#endif - - // Start the sound effect playing -#if 0 - // FIXME: This does not work. It sounds like white noise to me. - musicChannels[i] = _mixer->playRaw(&musicHandle[i], lpDsbMus[i], buffer_size, 22050, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE); -#else - warning("FIXME: Play the sound"); - free(lpDsbMus[i]); -#endif - - // Record the last variables for streaming and looping - musStreaming[i] = 1; - musCounter[i] = 250; + return (RD_OK); /* HRESULT hr; @@ -2435,6 +1528,7 @@ int32 Sword2Sound::StreamCompMusic(const char *filename, const char *directory, hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); if (hr == DSERR_BUFFERLOST) + { IDirectSoundBuffer_Restore(lpDsbMus[i]); hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); @@ -2725,13 +1819,137 @@ int32 Sword2Sound::StreamCompMusic(const char *filename, const char *directory, } } */ - return(RD_OK); } +void Sword2Sound::UpdateCompSampleStreaming(void) { + uint32 i,j; + int32 v0, v1; + int32 len; + uint16 *data16; + uint8 *data8; + int fade; + + for (i = 0; i < MAXMUS; i++) { + if (musStreaming[i]) { + if (musFading[i]) { + if (musFading[i] < 0) { + if (++musFading[i] == 0) { + g_engine->_mixer->endStream(soundHandleMusic[i]); + musStreaming[i] = 0; + musLooping[i] = 0; + } else { + // 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); + } + + if (v0 > v1) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); + } else { + if (v1 > v0) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); + } else { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +// IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); + } + } + } + } + } else { + len = bufferSizeMusic; + + // Reduce length if it requires reading past the end of the music + if (musFilePos[i] + len >= musEnd[i]) { + len = musEnd[i] - musFilePos[i]; + fade = 1; // End of music reaced so we'll need to fade and repeat + } else + fade = 0; + + if (len > 0) { + data8 = (uint8*)malloc(len / 2); + // Allocate a compressed data buffer + if (data8 == NULL) { + fpMus.close(); + musFading[i] = -16; + } + + // Seek to update position of compressed music when neccassary (probably never occurs) + if (fpMus.pos() != musFilePos[i]) { + fpMus.seek(musFilePos[i], SEEK_SET); + } + // Read the compressed data in to the buffer + if (fpMus.read(data8, len / 2) != (len / 2)) { + fpMus.close(); + free(data8); + musFading[i] = -16; + return; + } + + // Update the current position in the file for future streaming + musFilePos[i] = fpMus.pos(); + + // decompress the music into the music buffer. + data16 = (uint16*)malloc(len); + + // Decompress the first byte using the last decompressed sample + if (GetCompressedSign(data8[0])) + data16[0] = musLastSample[i] - (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); + else + data16[0] = musLastSample[i] + (GetCompressedAmplitude(data8[0]) << GetCompressedShift(data8[0])); + + j = 1; + + while (j < (uint32)len / 2) { + 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]; + + //Until the mixer supports LE samples natively, we need to convert our LE ones to BE + for (int32 j = 0; j < (len / 2); j++) { + data16[j] = TO_BE_16(data16[j]); + } + + if (soundHandleMusic[i] == -1) { + soundHandleMusic[i] = g_engine->_mixer->newStream(data16, bufferSizeMusic, 22050, SoundMixer::FLAG_16BITS, 100000); + } else { + g_engine->_mixer->appendStream(soundHandleMusic[i], data16, len); + } + + free(data16); + + // Free the compressed data buffer and unlock the sound buffer. + free(data8); + + // End of the music so we need to start fading and start the music again + if (fade) { + musFading[i] = -16; // Fade the old music + + // Close the music cluster if it's open + if (fpMus.isOpen()) { + fpMus.close(); + } + + // Loop if neccassary + if (musLooping[i]) { + StreamCompMusic(musFilename[i], musId[i], musLooping[i]); + } + } + } + } + } + } + DipMusic(); -void Sword2Sound::UpdateCompSampleStreaming(void) -{ - warning("stub UpdateCompSampleStreaming"); /* uint32 i,j,k; @@ -2939,9 +2157,11 @@ void Sword2Sound::UpdateCompSampleStreaming(void) */ } -int32 Sword2Sound::DipMusic() -{ - warning("stub DipMusic"); +int32 Sword2Sound::DipMusic() { + // TODO: implement this func + // disable this func for now + return RD_OK; + /* int32 len; int32 readCursor, writeCursor; @@ -3011,262 +2231,104 @@ int32 Sword2Sound::DipMusic() return (hr); */ - return RD_OK; } -int32 Sword2Sound::MusicTimeRemaining() -{ - warning("stub MusicTimeRemaaining"); -/* - int32 writeCursor; - int32 i; - int32 readCursor; +int32 Sword2Sound::MusicTimeRemaining() { + int i; +// int32 readCursor; - for (i=0; i<MAXMUS && !musStreaming[i]; i++) - { + for (i = 0; i < MAXMUS && !musStreaming[i]; i++) { // this is meant to be empty! (James19aug97) } if (i == MAXMUS) return 0; - - if ((IDirectSoundBuffer_GetCurrentPosition(lpDsbMus[i], &readCursor, &writeCursor)) != DS_OK) - return 0; - - return (((132300-readCursor)/2 + (musEnd[i] - musFilePos[i])) / 22050); -*/ - return 0; + return (musEnd[i] - musFilePos[i]) / 22050; + // TODO: plus channel offset + // return (((132300 - readCursor) / 2 + (musEnd[i] - musFilePos[i])) / 22050); } +void Sword2Sound::StopMusic(void) { + int i; + for (i = 0; i < MAXMUS; i++) { + if (musStreaming[i]) + musFading[i] = -16; + else + musLooping[i] = 0; + } -void Sword2Sound::StopMusic(void) -{ - int32 i; - - switch (compressedMusic) - { - case 1: // compressed music streaming - for (i = 0; i<MAXMUS; i++) - { - if (musStreaming[i]) - musFading[i] = -16; - else - // If the music is muted, make sure the tune doesn't restart. - musLooping[i] = 0; - } - - if (fpMus[0].isOpen()) - fpMus[0].close(); - break; - case 2: - for (i = 0; i<MAXMUS; i++) - { - if (musStreaming[i]) - StartMusicFadeDown(i); - } - break; - default: - break; + if (fpMus.isOpen()) { + fpMus.close(); } } +int32 Sword2Sound::PauseMusic(void) { + int i; -int32 Sword2Sound::PauseMusic(void) -{ - warning("stub PauseMusic"); -/* - int32 i; - - if (soundOn) - { - for (i=0; i<2; i++) - { - if (musStreaming[i]) - { + if (soundOn) { + for (i = 0; i < 2; i++) { + if (musStreaming[i]) { musicPaused[i] = TRUE; - - if (IDirectSoundBuffer_Stop(lpDsbMus[i]) != RD_OK) - return(RDERR_FXFUCKED); - } - else - { + g_engine->_mixer->pauseChannels(true); + } else { musicPaused[i] = FALSE; } } } -*/ return(RD_OK); } -int32 Sword2Sound::UnpauseMusic(void) -{ - warning("stub UnpauseMusic"); -/* - - int32 i; - - if (soundOn) - { - for (i=0; i<2; i++) - { - if (musicPaused[i]) - { - if (IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING) != RD_OK) - return(RDERR_FXFUCKED); +int32 Sword2Sound::UnpauseMusic(void) { + int i; + if (soundOn) { + for (i = 0; i < 2; i++) { + if (musicPaused[i]) { + g_engine->_mixer->pauseChannels(false); musicPaused[i] = FALSE; } } } -*/ return(RD_OK); } - -void Sword2Sound::SetMusicVolume(uint8 volume) -{ - warning("stub SetMusicVolume( %d )", volume); -/* - int32 i; - for (i = 0; i<MAXMUS; i++) - { +void Sword2Sound::SetMusicVolume(uint8 volume) { + int i; + for (i = 0; i < MAXMUS; i++) { volMusic[i] = volume; - if (musStreaming[i] && !musFading[i] && !musicMuted) - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volume]); + if (musStreaming[i] && !musFading[i] && !musicMuted) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volume]); + } } -*/ } - -uint8 Sword2Sound::GetMusicVolume() -{ - return (uint8) volMusic[0]; +uint8 Sword2Sound::GetMusicVolume() { + return (uint8) volMusic[0]; } - -void Sword2Sound::MuteMusic(uint8 mute) -{ - warning("stub MuteMusic( %d )", mute); -/* - int32 i; +void Sword2Sound::MuteMusic(uint8 mute) { + int i; musicMuted = mute; - for (i = 0; i<MAXMUS; i++) - { - if (!mute) - { + for (i = 0; i < MAXMUS; i++) { + if (!mute) { if (!musStreaming[i] && musLooping[i]) StreamCompMusic(musFilename[i], musId[i], musLooping[i]); } - if (musStreaming[i] && !musFading[i]) - { - if (mute) - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[0]); - else - IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volMusic[i]]); + if (musStreaming[i] && !musFading[i]) { + if (mute) { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[0]); + } else { +// IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volMusic[i]]); + } } } -*/ } - -uint8 Sword2Sound::IsMusicMute(void) -{ +uint8 Sword2Sound::IsMusicMute(void) { return (musicMuted); } - - - -void Sword2Sound::GetSoundStatus(_drvSoundStatus *s) -{ - int i; - -// s->hwnd = hwnd; -// s->lpDS = lpDS; -// s->dsbPrimary = dsbPrimary; -// s->dsbSpeech = dsbSpeech; - s->soundOn = soundOn; - s->speechStatus = speechStatus; - s->fxPaused = fxPaused; - s->speechPaused = speechPaused; - s->speechVol = speechVol; - s->fxVol = fxVol; - s->speechMuted = speechMuted; - s->fxMuted = fxMuted; - s->compressedMusic = compressedMusic; - s->musicMuted = musicMuted; - - memcpy(s->fxId, fxId, sizeof(int32) * MAXFX); - memcpy(s->fxCached, fxCached, sizeof(uint8) * MAXFX); -// memcpy(s->dsbFx, dsbFx, sizeof(LPDIRECTSOUNDBUFFER) * MAXFX); - memcpy(s->fxiPaused, fxiPaused, sizeof(uint8) * MAXFX); - memcpy(s->fxLooped, fxLooped, sizeof(uint8) * MAXFX); - memcpy(s->musStreaming, musStreaming, sizeof(int16) * MAXMUS); - memcpy(s->musicPaused, musicPaused, sizeof(int16) * MAXMUS); - memcpy(s->musCounter, musCounter, sizeof(int16) * MAXMUS); - memcpy(s->musFading, musFading, sizeof(int16) * MAXMUS); - memcpy(s->musLooping, musLooping, sizeof(int16) * MAXMUS); - memcpy(s->musLastSample,musLastSample, sizeof(int16) * MAXMUS); - memcpy(s->streamCursor, streamCursor, sizeof(int32) * MAXMUS); - memcpy(s->musFilePos, musFilePos, sizeof(int32) * MAXMUS); - memcpy(s->musEnd, musEnd, sizeof(int32) * MAXMUS); - memcpy(s->musId, musId, sizeof(uint32) * MAXMUS); - memcpy(s->volMusic, volMusic, sizeof(uint32) * 2); -// memcpy(s->dsbdMus, dsbdMus, sizeof(DSBUFFERDESC) * MAXMUS); -// memcpy(s->lpDsbMus, lpDsbMus, sizeof(LPDIRECTSOUNDBUFFER) * MAXMUS); - memcpy(s->fpMus, fpMus, sizeof(FILE*) * MAXMUS); -// memcpy(s->wfMus, wfMus, sizeof(PCMWAVEFORMAT) * MAXMUS); - - for (i = 0; i<MAXMUS; i++) - memcpy(s->musFilename[i], musFilename[i], sizeof(char) * 256); -} - - -void Sword2Sound::SetSoundStatus(_drvSoundStatus *s) -{ - int i; - -// hwnd = s->hwnd; -// lpDS = s->lpDS; -// dsbPrimary = s->dsbPrimary; -// dsbSpeech = s->dsbSpeech; - soundOn = s->soundOn; - speechStatus = s->speechStatus; - fxPaused = s->fxPaused; - speechPaused = s->speechPaused; - speechVol = s->speechVol; - fxVol = s->fxVol; - speechMuted = s->speechMuted; - fxMuted = s->fxMuted; - compressedMusic = s->compressedMusic; - musicMuted = s->musicMuted; - - memcpy(fxId, s->fxId, sizeof(int32) * MAXFX); - memcpy(fxCached, s->fxCached, sizeof(uint8) * MAXFX); -// memcpy(dsbFx, s->dsbFx, sizeof(LPDIRECTSOUNDBUFFER) * MAXFX); - memcpy(fxiPaused, s->fxiPaused, sizeof(uint8) * MAXFX); - memcpy(fxLooped, s->fxLooped, sizeof(uint8) * MAXFX); - memcpy(musStreaming, s->musStreaming, sizeof(int16) * MAXMUS); - memcpy(musicPaused, s->musicPaused, sizeof(int16) * MAXMUS); - memcpy(musCounter, s->musCounter, sizeof(int16) * MAXMUS); - memcpy(musFading, s->musFading, sizeof(int16) * MAXMUS); - memcpy(musLooping, s->musLooping, sizeof(int16) * MAXMUS); - memcpy(musLastSample,s->musLastSample, sizeof(int16) * MAXMUS); - memcpy(streamCursor, s->streamCursor, sizeof(int32) * MAXMUS); - memcpy(musFilePos, s->musFilePos, sizeof(int32) * MAXMUS); - memcpy(musEnd, s->musEnd, sizeof(int32) * MAXMUS); - memcpy(musId, s->musId, sizeof(uint32) * MAXMUS); - memcpy(volMusic, s->volMusic, sizeof(uint32) * 2); -// memcpy(dsbdMus, s->dsbdMus, sizeof(DSBUFFERDESC) * MAXMUS); -// memcpy(lpDsbMus, s->lpDsbMus, sizeof(LPDIRECTSOUNDBUFFER) * MAXMUS); -// memcpy(fpMus, s->fpMus, sizeof(FILE*) * MAXMUS); -// memcpy(wfMus, s->wfMus, sizeof(PCMWAVEFORMAT) * MAXMUS); - - for (i = 0; i<MAXMUS; i++) - memcpy(musFilename[i], s->musFilename[i], sizeof(char) * 256); -} - diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h index def3eaf268..7fb4af60fa 100644 --- a/sword2/driver/d_sound.h +++ b/sword2/driver/d_sound.h @@ -41,6 +41,8 @@ #include "sound/mixer.h" #include "common/file.h" +void sword2_sound_handler (void *engine); + class Sword2Sound { public: Sword2Sound(SoundMixer *mixer); @@ -65,7 +67,7 @@ class Sword2Sound { int32 PauseMusic(void); int32 UnpauseMusic(void); int32 StreamMusic(uint8 *filename, int32 looping); - int32 StreamCompMusic(const char *filename, const char *directory, uint32 musicId, int32 looping); + int32 StreamCompMusic(const char *filename, uint32 musicId, int32 looping); int32 MusicTimeRemaining(); int32 ReverseStereo(void); uint8 GetFxVolume(void); @@ -75,8 +77,6 @@ class Sword2Sound { uint8 IsFxMute(void); uint8 IsSpeechMute(void); void StopMusic(void); - void GetSoundStatus(_drvSoundStatus *s); - void SetSoundStatus(_drvSoundStatus *s); void SetFxVolume(uint8 vol); void SetSpeechVolume(uint8 vol); void SetMusicVolume(uint8 vol); @@ -92,14 +92,16 @@ class Sword2Sound { int32 GetFxIndex(int32 id); void StartMusicFadeDown(int i); int32 DipMusic(); - void UpdateSampleStreaming(void); int32 fxId[MAXFX]; uint8 fxCached[MAXFX]; uint8 fxiPaused[MAXFX]; uint8 fxLooped[MAXFX]; uint8 fxVolume[MAXFX]; - + uint32 flagsFx[MAXFX]; + uint16 *bufferFx[MAXFX]; + int32 bufferSizeFx[MAXFX]; + uint8 soundOn; uint8 speechStatus; uint8 fxPaused; @@ -116,14 +118,13 @@ class Sword2Sound { int16 musFading[MAXMUS]; int16 musLooping[MAXMUS]; - //DSBUFFERDESC dsbdMus[MAXMUS]; - //LPDIRECTSOUNDBUFFER lpDsbMus[MAXMUS]; - PlayingSoundHandle musicHandle[MAXMUS]; + PlayingSoundHandle soundHandleFx[MAXFX]; + PlayingSoundHandle soundHandleMusic[MAXMUS]; + PlayingSoundHandle soundHandleSpeech; + File fpMus; + int bufferSizeMusic; + int musicIndexChannel[MAXMUS]; int musicChannels[MAXMUS]; - uint16 *lpDsbMus[MAXMUS]; - File fpMus[MAXMUS]; - //FILE *fpMus[MAXMUS]; - //PCMWAVEFORMAT wfMus[MAXMUS]; int32 streamCursor[MAXMUS]; char musFilename[MAXMUS][256]; int32 musFilePos[MAXMUS]; @@ -132,7 +133,6 @@ class Sword2Sound { uint32 musId[MAXMUS]; uint32 volMusic[2]; uint8 musicMuted; - }; diff --git a/sword2/driver/driver96.h b/sword2/driver/driver96.h index 5c30de2f29..78588aed85 100644 --- a/sword2/driver/driver96.h +++ b/sword2/driver/driver96.h @@ -1365,50 +1365,6 @@ typedef struct // DDCOLORKEY blackColorKey; } _drvDrawStatus; - - -// This is the structure which is used to set and -// retrieve the direct sound drivers global variables. - -typedef struct -{ -// HWND hwnd; -// LPDIRECTSOUND lpDS; -// LPDIRECTSOUNDBUFFER dsbPrimary; -// LPDIRECTSOUNDBUFFER dsbSpeech; -// LPDIRECTSOUNDBUFFER dsbFx[MAXFX]; - int32 fxId[MAXFX]; - uint8 fxCached[MAXFX]; - uint8 soundOn; - uint8 speechStatus; - uint8 fxPaused; - char musFilename[MAXMUS][256]; - uint8 speechPaused; - uint8 speechVol; - uint8 fxVol; - uint8 speechMuted; - uint8 fxMuted; - uint8 musicMuted; - uint8 compressedMusic; - uint8 fxiPaused[MAXFX]; - uint8 fxLooped[MAXFX]; - int16 musStreaming[MAXMUS]; - int16 musicPaused[MAXMUS]; - int16 musCounter[MAXMUS]; - int16 musFading[MAXMUS]; - int16 musLooping[MAXMUS]; - int16 musLastSample[MAXMUS]; - int32 streamCursor[MAXMUS]; - int32 musFilePos[MAXMUS]; - int32 musEnd[MAXMUS]; - uint32 musId[MAXMUS]; -// DSBUFFERDESC dsbdMus[MAXMUS]; -// LPDIRECTSOUNDBUFFER lpDsbMus[MAXMUS]; - FILE *fpMus[MAXMUS]; -// PCMWAVEFORMAT wfMus[MAXMUS]; - uint32 volMusic[2]; -} _drvSoundStatus; - // This is the structure which is used to retrieve // the keyboard driver bits. diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp index 299721c9ce..4a4a1ac812 100644 --- a/sword2/driver/rdwin.cpp +++ b/sword2/driver/rdwin.cpp @@ -19,12 +19,9 @@ #define WIN32_LEAN_AND_MEAN -//#include <windows.h> -//#include <windowsx.h> -#include <stdio.h> - #include "common/stdafx.h" #include "common/engine.h" +#include "common/timer.h" #include "driver96.h" @@ -532,6 +529,7 @@ int32 CloseAppWindow(void) DestroyWindow(hwnd); */ // just quit for now + g_engine->_timer->releaseProcedure(sword2_sound_handler); g_system->quit(); return(RD_OK); diff --git a/sword2/sound.cpp b/sword2/sound.cpp index e16c51b8ce..fae889a483 100644 --- a/sword2/sound.cpp +++ b/sword2/sound.cpp @@ -412,7 +412,7 @@ int32 FN_play_music(int32 *params) // updated by James on 10apr97 sprintf(filename,"Music.clu"); - rv = g_sword2->_sound->StreamCompMusic(filename, g_sword2->getGameDataPath(), params[0], loopFlag); + rv = g_sword2->_sound->StreamCompMusic(filename, params[0], loopFlag); #ifdef _SWORD2_DEBUG if (rv) diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp index 6a7d05b951..c7828840d4 100644 --- a/sword2/sword2.cpp +++ b/sword2/sword2.cpp @@ -18,15 +18,12 @@ */ //------------------------------------------------------------------------------------ -#include <ctype.h> -#include <stdio.h> -//#include <windows.h> - #include "stdafx.h" #include "driver/driver96.h" #include "driver/palette.h" #include "common/gameDetector.h" #include "common/config-file.h" +#include "common/timer.h" #include "build_display.h" #include "console.h" #include "controls.h" @@ -318,6 +315,7 @@ void Sword2State::go() } */ + g_engine->_timer->installProcedure(sword2_sound_handler, 1000000); Zdebug("CALLING: InitialiseGame"); if (InitialiseGame()) { |