diff --git a/3rdParty/Storm/Source/storm.h b/3rdParty/Storm/Source/storm.h index a2b922770..f86b44b0e 100644 --- a/3rdParty/Storm/Source/storm.h +++ b/3rdParty/Storm/Source/storm.h @@ -211,12 +211,6 @@ SNetSendTurn( BOOL STORMAPI SFileCloseArchive(HANDLE hArchive); BOOL STORMAPI SFileCloseFile(HANDLE hFile); -BOOL STORMAPI SFileDdaBeginEx(HANDLE hFile, DWORD flags, DWORD mask, unsigned __int32 lDistanceToMove, signed __int32 volume, signed int pan, int a7); -void SFileFreeChunk(); -BOOL STORMAPI SFileDdaDestroy(); -BOOL STORMAPI SFileDdaEnd(HANDLE hFile); -BOOL STORMAPI SFileDdaGetPos(HANDLE hFile, DWORD *current, DWORD *end); - BOOL STORMAPI SFileDdaSetVolume(HANDLE hFile, signed int bigvolume, signed int volume); LONG STORMAPI SFileGetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); diff --git a/Source/effects.cpp b/Source/effects.cpp index 0fb5c7863..2edb99035 100644 --- a/Source/effects.cpp +++ b/Source/effects.cpp @@ -11,10 +11,8 @@ DEVILUTION_BEGIN_NAMESPACE int sfxdelay; int sfxdnum; -/** A handle to the current sound effect playing. */ -HANDLE sghStream; /** Specifies the sound file and the playback state of the current sound effect. */ -TSFX *sgpStreamSFX; +static TSFX *sgpStreamSFX = NULL; /** * Monster sound type prefix @@ -1069,11 +1067,10 @@ BOOL effect_is_playing(int nSFX) void stream_stop() { - if (sghStream) { - SFileDdaEnd(sghStream); - SFileCloseFile(sghStream); - SFileFreeChunk(); - sghStream = NULL; + if (sgpStreamSFX != NULL) { + sgpStreamSFX->pSnd->DSB->Stop(); + sound_file_cleanup(sgpStreamSFX->pSnd); + sgpStreamSFX->pSnd = NULL; sgpStreamSFX = NULL; } } @@ -1089,23 +1086,16 @@ static void stream_play(TSFX *pSFX, int lVolume, int lPan) if (lVolume >= VOLUME_MIN) { if (lVolume > VOLUME_MAX) lVolume = VOLUME_MAX; - success = SFileOpenFile(pSFX->pszName, &sghStream); - if (!success) { - sghStream = NULL; - } else { - if (!SFileDdaBeginEx(sghStream, 0x40000, 0, 0, lVolume, lPan, 0)) - stream_stop(); - else - sgpStreamSFX = pSFX; - } + if (pSFX->pSnd == NULL) + pSFX->pSnd = sound_file_load(pSFX->pszName); + pSFX->pSnd->DSB->Play(lVolume, lPan, 0); + sgpStreamSFX = pSFX; } } static void stream_update() { - DWORD current, end; - - if (sghStream != NULL && SFileDdaGetPos(sghStream, ¤t, &end) && current >= end) { + if (sgpStreamSFX != NULL && !sgpStreamSFX->pSnd->DSB->IsPlaying()) { stream_stop(); } } @@ -1410,4 +1400,11 @@ void effects_play_sound(const char *snd_file) } } +int GetSFXLength(int nSFX) +{ + if (sgSFX[nSFX].pSnd == NULL) + sgSFX[nSFX].pSnd = sound_file_load(sgSFX[nSFX].pszName); + return sgSFX[nSFX].pSnd->DSB->GetLength(); +} + DEVILUTION_END_NAMESPACE diff --git a/Source/effects.h b/Source/effects.h index a049df3ec..0d9e05111 100644 --- a/Source/effects.h +++ b/Source/effects.h @@ -29,6 +29,7 @@ void effects_cleanup_sfx(); void sound_init(); void ui_sound_init(); void effects_play_sound(const char *snd_file); +int GetSFXLength(int nSFX); #ifdef __cplusplus } diff --git a/SourceS/soundsample.h b/SourceS/soundsample.h index 4809ce0bd..49a67ab39 100644 --- a/SourceS/soundsample.h +++ b/SourceS/soundsample.h @@ -5,11 +5,12 @@ namespace dvl { typedef struct SoundSample final { public: - void Release() ; - bool IsPlaying() ; - void Play(int lVolume, int lPan) ; - void Stop() ; - int SetChunk(BYTE *fileData, DWORD dwBytes) ; + void Release(); + bool IsPlaying(); + void Play(int lVolume, int lPan, int channel = -1); + void Stop(); + int SetChunk(BYTE *fileData, DWORD dwBytes); + int GetLength(); private: Mix_Chunk *chunk; diff --git a/SourceX/sound.cpp b/SourceX/sound.cpp index fbda8057f..8c6b5a072 100644 --- a/SourceX/sound.cpp +++ b/SourceX/sound.cpp @@ -173,8 +173,6 @@ void snd_init(HWND hWnd) void sound_cleanup() { - SFileDdaDestroy(); - if (gbSndInited) { gbSndInited = false; snd_set_volume("Sound Volume", sglSoundVolume); diff --git a/SourceX/soundsample.cpp b/SourceX/soundsample.cpp index ef0b23cd5..d9e5d4828 100644 --- a/SourceX/soundsample.cpp +++ b/SourceX/soundsample.cpp @@ -11,9 +11,16 @@ void SoundSample::Release() Mix_FreeChunk(chunk); }; +/** + * @brief Check if a the sound is being played atm + */ bool SoundSample::IsPlaying() { - for (int i = 1; i < Mix_AllocateChannels(-1); i++) { + if (chunk == NULL) + return false; + + int channels = Mix_AllocateChannels(-1); + for (int i = 0; i < channels; i++) { if (Mix_GetChunk(i) == chunk && Mix_Playing(i)) { return true; } @@ -22,9 +29,15 @@ bool SoundSample::IsPlaying() return false; }; -void SoundSample::Play(int lVolume, int lPan) +/** + * @brief Start playing the sound + */ +void SoundSample::Play(int lVolume, int lPan, int channel) { - int channel = Mix_PlayChannel(-1, chunk, 0); + if (chunk == NULL) + return; + + channel = Mix_PlayChannel(channel, chunk, 0); if (channel == -1) { SDL_Log("Too few channels, skipping sound"); return; @@ -35,9 +48,16 @@ void SoundSample::Play(int lVolume, int lPan) Mix_SetPanning(channel, pan > 0 ? pan : 255, pan < 0 ? abs(pan) : 255); }; +/** + * @brief Stop playing the sound + */ void SoundSample::Stop() { - for (int i = 1; i < Mix_AllocateChannels(-1); i++) { + if (chunk == NULL) + return; + + int channels = Mix_AllocateChannels(-1); + for (int i = 0; i < channels; i++) { if (Mix_GetChunk(i) != chunk) { continue; } @@ -46,6 +66,12 @@ void SoundSample::Stop() } }; +/** + * @brief This can load WAVE, AIFF, RIFF, OGG, and VOC formats + * @param fileData Buffer containing file data + * @param dwBytes Length of buffer + * @return 0 on success, -1 otherwise + */ int SoundSample::SetChunk(BYTE *fileData, DWORD dwBytes) { SDL_RWops *buf1 = SDL_RWFromConstMem(fileData, dwBytes); @@ -61,4 +87,24 @@ int SoundSample::SetChunk(BYTE *fileData, DWORD dwBytes) return 0; }; +/** + * @return Audio duration in ms + */ +int SoundSample::GetLength() +{ + if (chunk == NULL) + return 0; + + int frequency, channels; + Uint16 format; + Mix_QuerySpec(&frequency, &format, &channels); + + int bytePerSample = 2; + if (format == AUDIO_U8 || format == AUDIO_S8) { + bytePerSample = 1; + } + + return chunk->alen * 1000 / (frequency * channels * bytePerSample); +}; + } // namespace dvl diff --git a/SourceX/storm/storm.cpp b/SourceX/storm/storm.cpp index 3db815075..9c9b1fd6c 100644 --- a/SourceX/storm/storm.cpp +++ b/SourceX/storm/storm.cpp @@ -40,72 +40,6 @@ radon::File &getIni() return ini; } -static Mix_Chunk *SFileChunk = NULL; - -BOOL SFileDdaBeginEx(HANDLE hFile, DWORD flags, DWORD mask, unsigned __int32 lDistanceToMove, - signed __int32 volume, signed int pan, int a7) -{ - DWORD bytestoread = SFileGetFileSize(hFile, 0); - char *SFXbuffer = (char *)malloc(bytestoread); - SFileReadFile(hFile, SFXbuffer, bytestoread, NULL, NULL); - - SDL_RWops *rw = SDL_RWFromConstMem(SFXbuffer, bytestoread); - if (rw == NULL) { - SDL_Log(SDL_GetError()); - return false; - } - if (SFileChunk) { - SFileDdaEnd(hFile); - SFileFreeChunk(); - } - SFileChunk = Mix_LoadWAV_RW(rw, 1); - free(SFXbuffer); - - Mix_Volume(0, MIX_MAX_VOLUME - MIX_MAX_VOLUME * volume / VOLUME_MIN); - int panned = 255 - 255 * abs(pan) / 10000; - Mix_SetPanning(0, pan <= 0 ? 255 : panned, pan >= 0 ? 255 : panned); - Mix_PlayChannel(0, SFileChunk, 0); - - return true; -} - -void SFileFreeChunk() -{ - if (SFileChunk) { - Mix_FreeChunk(SFileChunk); - SFileChunk = NULL; - } -} - -BOOL SFileDdaDestroy() -{ - if (SFileChunk) { - Mix_FreeChunk(SFileChunk); - SFileChunk = NULL; - } - - return true; -} - -BOOL SFileDdaEnd(HANDLE hFile) -{ - Mix_HaltChannel(0); - - return true; -} - -BOOL SFileDdaGetPos(HANDLE hFile, DWORD *current, DWORD *end) -{ - *current = 0; - *end = 1; - - if (Mix_GetChunk(0) != SFileChunk || !Mix_Playing(0)) { - *current = *end; - } - - return true; -} - BOOL SFileDdaSetVolume(HANDLE hFile, signed int bigvolume, signed int volume) { Mix_VolumeMusic(MIX_MAX_VOLUME - MIX_MAX_VOLUME * bigvolume / VOLUME_MIN);