diff options
author | Jonathan Gray | 2003-08-02 02:31:36 +0000 |
---|---|---|
committer | Jonathan Gray | 2003-08-02 02:31:36 +0000 |
commit | a932a74dcb8185bc0ddb8edbe98d6c64eb1a8f97 (patch) | |
tree | 125f4ee55fe1f9f129a94096b5f244b9df6499bf /sword2 | |
parent | 02d061598c1a808264ba732fbda8631644cce88f (diff) | |
download | scummvm-rg350-a932a74dcb8185bc0ddb8edbe98d6c64eb1a8f97.tar.gz scummvm-rg350-a932a74dcb8185bc0ddb8edbe98d6c64eb1a8f97.tar.bz2 scummvm-rg350-a932a74dcb8185bc0ddb8edbe98d6c64eb1a8f97.zip |
patch #781530 Initial work on StreamCompMusic() by erik
svn-id: r9394
Diffstat (limited to 'sword2')
-rw-r--r-- | sword2/driver/d_sound.cpp | 200 | ||||
-rw-r--r-- | sword2/driver/d_sound.h | 13 | ||||
-rw-r--r-- | sword2/sound.cpp | 2 | ||||
-rw-r--r-- | sword2/sword2.cpp | 10 |
4 files changed, 209 insertions, 16 deletions
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp index 64117f6d26..5ddc6081fa 100644 --- a/sword2/driver/d_sound.cpp +++ b/sword2/driver/d_sound.cpp @@ -405,7 +405,7 @@ int32 musicVolTable[17] = { -Sword2Sound::Sword2Sound(void) { +Sword2Sound::Sword2Sound(SoundMixer *mixer) { soundOn = 0; speechStatus = 0; @@ -421,6 +421,7 @@ Sword2Sound::Sword2Sound(void) { volMusic[1] = 16; musicMuted = 0; + _mixer = mixer; } /* not used seemingly - khalek @@ -590,6 +591,25 @@ int32 Sword2Sound::InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth { warning("stub InitaliseSound( %d, %d, %d )", freq, channels, bitDepth); + + memset(fxId, 0, sizeof(fxId)); + memset(fxCached, 0, sizeof(fxCached)); + memset(fxiPaused, 0, sizeof(fxiPaused)); + memset(fxLooped, 0, sizeof(fxLooped)); + + memset(musStreaming, 0, sizeof(musStreaming)); + memset(musicPaused, 0, sizeof(musicPaused)); + memset(musCounter, 0, sizeof(musCounter)); + memset(musFading, 0, sizeof(musFading)); + + 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)); + /* int32 i; HRESULT hrz; @@ -1718,7 +1738,7 @@ void Sword2Sound::StartMusicFadeDown(int i) // IDirectSoundBuffer_Release(lpDsbMus[i]); musFading[i] = -16; // musStreaming[i] = 0; - fclose(fpMus[i]); + fpMus[i].close(); } @@ -2122,9 +2142,174 @@ void Sword2Sound::UpdateSampleStreaming(void) -int32 Sword2Sound::StreamCompMusic(const char *filename, uint32 musicId, int32 looping) -{ +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, but I believe that's after ADPCM-decoding. + 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; + + if (musStreaming[0] + musStreaming[1] == 2) { + // Both streams in use, try to find a fading stream + if (musFading[0]) + i = 0; + else + i = 1; + + musFading[i] = 0; + _mixer->stop(musicChannels[i]); + musStreaming[i] = 0; + } + + 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; + + // Don't start streaming if the volume is off. + if (IsMusicMute()) + return RD_OK; + + // 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 (musStreaming[0] + musStreaming[1] == 1) { + // Start other music stream fading out + if (!musFading[i - 1]) + musFading[i - 1] = -16; + + // Restart the streaming cursor for this sample + streamCursor[i] = 0; + } + + // Seek to music index + fpMus[0].seek((musicId + 1) * 8); + + musFilePos[i] = fpMus[0].readUint32LE(); + musEnd[i] = fpMus[0].readUint32LE(); + + // Check that music is valid (has length & offset) + if (!musEnd[i] || !musFilePos[i]) { + fpMus[0].close(); + return RDERR_INVALIDID; + } + + // Calculate the file position of the end of the music + musEnd[i] += musFilePos[i]; + + // Reset streaming cursor and store looping flag + streamCursor[i] = 0; + + // Allocate a temporary buffer for compressed data + data8 = (uint8 *) malloc(buffer_size / 2); + if (!data8) { + fpMus[0].close(); + return RDERR_OUTOFMEMORY; + } + + // Allocate a sound buffer large enough for 3 seconds + data16 = (uint16 *) malloc(buffer_size); + if (!data16) { + fpMus[0].close(); + free(data8); + return RDERR_OUTOFMEMORY; + } + + lpDsbMus[i] = data16; + + // Seek to start of the compressed music + fpMus[0].seek(musFilePos[i]); + + // Read the compressed data in to the buffer + if (fpMus[0].read(data8, buffer_size / 2) != buffer_size / 2) { + fpMus[0].close(); + 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; + + 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++; + } + + // Store the value of the last sample ready for next batch of + // decompression + musLastSample[i] = data16[j - 1]; + + // Free the decompression 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]; + } + +#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); + } +#else + warning("FIXME: Implement volume and panning"); +#endif + + // Start the sound effect playing +#if 0 + musicChannels[i] = _mixer->playADPCM(&musicHandle[i], lpDsbMus[i], buffer_size, 22050, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE); +#else + warning("FIXME: Implement ADPCM-decoding"); + free(lpDsbMus[i]); +#endif + + // Record the last variables for streaming and looping + musStreaming[i] = 1; + musCounter[i] = 250; + /* HRESULT hr; LPVOID lpv1, lpv2; @@ -2861,11 +3046,8 @@ void Sword2Sound::StopMusic(void) musLooping[i] = 0; } - if (fpMus[0]) - { - fclose(fpMus[0]); - fpMus[0] = 0; - } + if (fpMus[0].isOpen()) + fpMus[0].close(); break; case 2: for (i = 0; i<MAXMUS; i++) diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h index 83f3b9db06..def3eaf268 100644 --- a/sword2/driver/d_sound.h +++ b/sword2/driver/d_sound.h @@ -38,11 +38,12 @@ #ifndef D_SOUND_H #define D_SOUND_H -class SoundMixer; +#include "sound/mixer.h" +#include "common/file.h" class Sword2Sound { public: - Sword2Sound(void); + Sword2Sound(SoundMixer *mixer); void FxServer(void); int32 InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth); int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan); @@ -64,7 +65,7 @@ class Sword2Sound { 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, const char *directory, uint32 musicId, int32 looping); int32 MusicTimeRemaining(); int32 ReverseStereo(void); uint8 GetFxVolume(void); @@ -117,7 +118,11 @@ class Sword2Sound { //DSBUFFERDESC dsbdMus[MAXMUS]; //LPDIRECTSOUNDBUFFER lpDsbMus[MAXMUS]; - FILE *fpMus[MAXMUS]; + PlayingSoundHandle musicHandle[MAXMUS]; + int musicChannels[MAXMUS]; + uint16 *lpDsbMus[MAXMUS]; + File fpMus[MAXMUS]; + //FILE *fpMus[MAXMUS]; //PCMWAVEFORMAT wfMus[MAXMUS]; int32 streamCursor[MAXMUS]; char musFilename[MAXMUS][256]; diff --git a/sword2/sound.cpp b/sword2/sound.cpp index a61ae971c5..16c6f8b6ec 100644 --- a/sword2/sound.cpp +++ b/sword2/sound.cpp @@ -415,7 +415,7 @@ int32 FN_play_music(int32 *params) // updated by James on 10apr97 else sprintf(filename,"%sCLUSTERS\\MUSIC.CLU", res_man.GetCdPath()); - rv = g_sword2->_sound->StreamCompMusic(filename, params[0], loopFlag); + rv = g_sword2->_sound->StreamCompMusic(filename, g_sword2->getGameDataPath(), params[0], loopFlag); #ifdef _SWORD2_DEBUG if (rv) diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp index e7dcf62bff..bbc522f37a 100644 --- a/sword2/sword2.cpp +++ b/sword2/sword2.cpp @@ -106,6 +106,14 @@ Sword2State::Sword2State(GameDetector *detector, OSystem *syst) g_sword2 = this; _features = detector->_game.features; _gameId = detector->_game.id; + + // Setup mixer + if (!_mixer->bindToSystem(syst)) + warning("Sound initialization failed"); + + _mixer->setVolume(kDefaultSFXVolume * kDefaultMasterVolume / 255); + + _sound = new Sword2Sound(_mixer); } @@ -167,8 +175,6 @@ int32 Sword2State::InitialiseGame(void) Init_event_system(); Zdebug("RETURNED."); - _sound = new Sword2Sound; - Zdebug("CALLING: Init_fx_queue"); Init_fx_queue(); // initialise the sound fx queue Zdebug("RETURNED."); |