Browse Source

Stream music instead of loading it all at once

RAM usage (my beefy desktop):

* Town: 176 MiB -> 121 MiB
* Cathedral: 191 MiB -> 138 MiB

Performance: 1170 FPS -> 1150 FPS
pull/1204/head
Gleb Mazovetskiy 5 years ago committed by Anders Jenbo
parent
commit
997650aa5d
  1. 1
      CMakeLists.txt
  2. 1
      SourceS/miniwin/misc.h
  3. 39
      SourceX/sound.cpp
  4. 88
      SourceX/storm_sdl_rw.cpp
  5. 16
      SourceX/storm_sdl_rw.h

1
CMakeLists.txt

@ -289,6 +289,7 @@ set(devilutionx_SRCS
SourceX/thread.cpp
SourceX/sound.cpp
SourceX/soundsample.cpp
SourceX/storm_sdl_rw.cpp
SourceX/storm/storm.cpp
SourceX/storm/storm_net.cpp
SourceX/dvlnet/abstract_net.cpp

1
SourceS/miniwin/misc.h

@ -62,6 +62,7 @@ bool PostMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
// MSCVRT emulation
//
#define DVL_FILE_BEGIN 0
#define DVL_FILE_CURRENT 1
#define DVL_FILE_END 2

39
SourceX/sound.cpp

@ -6,6 +6,7 @@
#include "all.h"
#include "../3rdParty/Storm/Source/storm.h"
#include "stubs.h"
#include "storm_sdl_rw.h"
#include <SDL.h>
#include <SDL_mixer.h>
@ -15,9 +16,11 @@ BOOLEAN gbSndInited;
/** Specifies whether background music is enabled. */
HANDLE sghMusic;
namespace {
Mix_Music *music;
SDL_RWops *musicRw;
char *musicBuffer;
} // namespace
/* data */
@ -157,12 +160,10 @@ void music_stop()
{
if (sghMusic) {
Mix_HaltMusic();
SFileCloseFile(sghMusic);
sghMusic = NULL;
Mix_FreeMusic(music);
music = NULL;
musicRw = NULL;
mem_free_dbg(musicBuffer);
SFileCloseFile(sghMusic);
sghMusic = NULL;
sgnMusicTrack = NUM_MUSIC;
}
}
@ -183,17 +184,25 @@ void music_start(int nTrack)
if (!success) {
sghMusic = NULL;
} else {
int bytestoread = SFileGetFileSize(sghMusic, 0);
musicBuffer = (char *)DiabloAllocPtr(bytestoread);
SFileReadFile(sghMusic, musicBuffer, bytestoread, NULL, 0);
musicRw = SDL_RWFromConstMem(musicBuffer, bytestoread);
if (musicRw == NULL) {
ErrSdl();
music = Mix_LoadMUSType_RW(SFileRw_FromStormHandle(sghMusic), MUS_NONE, /*freesrc=*/1);
if (music == NULL) {
SDL_Log("Mix_LoadMUSType_RW: %s", Mix_GetError());
SFileCloseFile(sghMusic);
sghMusic = NULL;
sgnMusicTrack = NUM_MUSIC;
return;
}
music = Mix_LoadMUSType_RW(musicRw, MUS_NONE, 1);
Mix_VolumeMusic(MIX_MAX_VOLUME - MIX_MAX_VOLUME * sgOptions.Audio.nMusicVolume / VOLUME_MIN);
Mix_PlayMusic(music, -1);
if (Mix_PlayMusic(music, -1) < 0) {
SDL_Log("Mix_PlayMusic: %s", Mix_GetError());
Mix_FreeMusic(music);
SFileCloseFile(sghMusic);
sghMusic = NULL;
music = NULL;
sgnMusicTrack = NUM_MUSIC;
return;
}
sgnMusicTrack = nTrack;
}

88
SourceX/storm_sdl_rw.cpp

@ -0,0 +1,88 @@
#include "storm_sdl_rw.h"
#include "all.h"
#include "../3rdParty/Storm/Source/storm.h"
#include "../Source/engine.h"
namespace dvl {
static HANDLE SFileRw_GetHandle(struct SDL_RWops *context)
{
return (HANDLE)context->hidden.unknown.data1;
}
static void SFileRw_SetHandle(struct SDL_RWops *context, HANDLE handle)
{
context->hidden.unknown.data1 = handle;
}
#ifndef USE_SDL1
static Sint64 SFileRw_size(struct SDL_RWops *context)
{
DWORD result;
if (!SFileGetFileSize(SFileRw_GetHandle(context), &result))
return -1;
return result;
}
#endif
#ifndef USE_SDL1
static Sint64 SFileRw_seek(struct SDL_RWops *context, Sint64 offset, int whence)
#else
static int SFileRw_seek(struct SDL_RWops *context, int offset, int whence)
#endif
{
DWORD swhence;
switch (whence) {
case RW_SEEK_SET:
swhence = DVL_FILE_BEGIN;
break;
case RW_SEEK_CUR:
swhence = DVL_FILE_CURRENT;
break;
case RW_SEEK_END:
swhence = DVL_FILE_END;
break;
default:
return -1;
}
return SFileSetFilePointer(SFileRw_GetHandle(context), offset, NULL, swhence);
}
#ifndef USE_SDL1
static size_t SFileRw_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
#else
static int SFileRw_read(struct SDL_RWops *context, void *ptr, int size, int maxnum)
#endif
{
DWORD num_read = 0;
SFileReadFile(SFileRw_GetHandle(context), ptr, maxnum * size, &num_read, NULL);
return num_read;
}
static int SFileRw_close(struct SDL_RWops *context)
{
mem_free_dbg(context);
return 0;
}
SDL_RWops *SFileRw_FromStormHandle(HANDLE handle)
{
SDL_RWops *result = (SDL_RWops *)DiabloAllocPtr(sizeof(SDL_RWops));
#ifndef USE_SDL1
result->size = &SFileRw_size;
result->type = SDL_RWOPS_UNKNOWN;
#else
result->type = 0;
#endif
result->seek = &SFileRw_seek;
result->read = &SFileRw_read;
result->write = NULL;
result->close = &SFileRw_close;
SFileRw_SetHandle(result, handle);
return result;
}
} // namespace dvl

16
SourceX/storm_sdl_rw.h

@ -0,0 +1,16 @@
#pragma once
#include <SDL.h>
#include "../SourceS/miniwin/misc.h"
namespace dvl {
/**
* @brief Creates a read-only SDL_RWops from a Storm file handle.
*
* Does not close the handle when it gets closed.
*/
SDL_RWops *SFileRw_FromStormHandle(HANDLE handle);
} // namespace dvl
Loading…
Cancel
Save