From dd04c36a97c2e09f3f7a8e53f467f51e3396de67 Mon Sep 17 00:00:00 2001 From: nyov Date: Wed, 5 Nov 2014 17:54:06 +0000 Subject: [PATCH] Revert "removed modplug support, the library is too insecure and barely used by anyone" This reverts commit 3b5c781f57c3579632cc7a25e0e534c55e5d5343. --- BSDmakefile | 10 + DPiOS.xcodeproj/project.pbxproj | 6 + darkplaces-dedicated-vs2010.vcxproj | 1 + darkplaces-dedicated-vs2012.vcxproj | 1 + darkplaces-dedicated.vcproj | 4 + darkplaces-sdl-vs2010.vcxproj | 2 + darkplaces-sdl-vs2012.vcxproj | 2 + darkplaces-sdl.dsp | 8 + darkplaces-sdl.vcproj | 8 + darkplaces-wgl-vs2010.vcxproj | 2 + darkplaces-wgl-vs2012.vcxproj | 2 + darkplaces-wgl.vcproj | 8 + darkplaces.dsp | 8 + makefile | 16 + makefile.inc | 24 +- snd_main.c | 3 + snd_mem.c | 11 + snd_modplug.c | 437 ++++++++++++++++++++++++++++ snd_modplug.h | 33 +++ 19 files changed, 576 insertions(+), 10 deletions(-) create mode 100644 snd_modplug.c create mode 100644 snd_modplug.h diff --git a/BSDmakefile b/BSDmakefile index eb135cef..0472e345 100644 --- a/BSDmakefile +++ b/BSDmakefile @@ -28,6 +28,7 @@ DP_LINK_JPEG?=shared DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen +DP_LINK_MODPLUG?=dlopen ###### Optional features ##### DP_CDDA?=enabled @@ -126,6 +127,15 @@ LIB_CRYPTO_RIJNDAEL= CFLAGS_CRYPTO_RIJNDAEL= .endif +# modplug +.if $(DP_LINK_MODPLUG) == "shared" +CFLAGS_SND_MODPLUG=-DLINK_TO_LIBMODPLUG +LIB_SND_MODPLUG=-lmodplug +.else +CFLAGS_SND_MODPLUG= +LIB_SND_MODPLUG= +.endif + .endif diff --git a/DPiOS.xcodeproj/project.pbxproj b/DPiOS.xcodeproj/project.pbxproj index a0488e90..f55f5fa6 100755 --- a/DPiOS.xcodeproj/project.pbxproj +++ b/DPiOS.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ 7463B7BD12F9CE6B00983F6A /* snd_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75212F9CE6B00983F6A /* snd_main.c */; }; 7463B7BE12F9CE6B00983F6A /* snd_mem.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75412F9CE6B00983F6A /* snd_mem.c */; }; 7463B7BF12F9CE6B00983F6A /* snd_mix.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75512F9CE6B00983F6A /* snd_mix.c */; }; + 7463B7C012F9CE6B00983F6A /* snd_modplug.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75612F9CE6B00983F6A /* snd_modplug.c */; }; 7463B7C112F9CE6B00983F6A /* snd_ogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75812F9CE6B00983F6A /* snd_ogg.c */; }; 7463B7C212F9CE6B00983F6A /* snd_sdl.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75A12F9CE6B00983F6A /* snd_sdl.c */; }; 7463B7C312F9CE6B00983F6A /* snd_wav.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B75B12F9CE6B00983F6A /* snd_wav.c */; }; @@ -274,6 +275,8 @@ 7463B75312F9CE6B00983F6A /* snd_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snd_main.h; sourceTree = ""; }; 7463B75412F9CE6B00983F6A /* snd_mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snd_mem.c; sourceTree = ""; }; 7463B75512F9CE6B00983F6A /* snd_mix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snd_mix.c; sourceTree = ""; }; + 7463B75612F9CE6B00983F6A /* snd_modplug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snd_modplug.c; sourceTree = ""; }; + 7463B75712F9CE6B00983F6A /* snd_modplug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snd_modplug.h; sourceTree = ""; }; 7463B75812F9CE6B00983F6A /* snd_ogg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snd_ogg.c; sourceTree = ""; }; 7463B75912F9CE6B00983F6A /* snd_ogg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snd_ogg.h; sourceTree = ""; }; 7463B75A12F9CE6B00983F6A /* snd_sdl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snd_sdl.c; sourceTree = ""; }; @@ -509,6 +512,8 @@ 7463B75312F9CE6B00983F6A /* snd_main.h */, 7463B75412F9CE6B00983F6A /* snd_mem.c */, 7463B75512F9CE6B00983F6A /* snd_mix.c */, + 7463B75612F9CE6B00983F6A /* snd_modplug.c */, + 7463B75712F9CE6B00983F6A /* snd_modplug.h */, 7463B75812F9CE6B00983F6A /* snd_ogg.c */, 7463B75912F9CE6B00983F6A /* snd_ogg.h */, 7463B75A12F9CE6B00983F6A /* snd_sdl.c */, @@ -713,6 +718,7 @@ 7463B7BD12F9CE6B00983F6A /* snd_main.c in Sources */, 7463B7BE12F9CE6B00983F6A /* snd_mem.c in Sources */, 7463B7BF12F9CE6B00983F6A /* snd_mix.c in Sources */, + 7463B7C012F9CE6B00983F6A /* snd_modplug.c in Sources */, 7463B7C112F9CE6B00983F6A /* snd_ogg.c in Sources */, 7463B7C212F9CE6B00983F6A /* snd_sdl.c in Sources */, 7463B7C312F9CE6B00983F6A /* snd_wav.c in Sources */, diff --git a/darkplaces-dedicated-vs2010.vcxproj b/darkplaces-dedicated-vs2010.vcxproj index 2d601db7..3880de03 100644 --- a/darkplaces-dedicated-vs2010.vcxproj +++ b/darkplaces-dedicated-vs2010.vcxproj @@ -263,6 +263,7 @@ + diff --git a/darkplaces-dedicated-vs2012.vcxproj b/darkplaces-dedicated-vs2012.vcxproj index 7d8f85f2..5e1e4916 100644 --- a/darkplaces-dedicated-vs2012.vcxproj +++ b/darkplaces-dedicated-vs2012.vcxproj @@ -354,6 +354,7 @@ + diff --git a/darkplaces-dedicated.vcproj b/darkplaces-dedicated.vcproj index 312fb6fd..895e9830 100755 --- a/darkplaces-dedicated.vcproj +++ b/darkplaces-dedicated.vcproj @@ -1018,6 +1018,10 @@ RelativePath=".\snd_main.h" > + + diff --git a/darkplaces-sdl-vs2010.vcxproj b/darkplaces-sdl-vs2010.vcxproj index 912237b0..f5ac6696 100644 --- a/darkplaces-sdl-vs2010.vcxproj +++ b/darkplaces-sdl-vs2010.vcxproj @@ -166,6 +166,7 @@ + @@ -271,6 +272,7 @@ + diff --git a/darkplaces-sdl-vs2012.vcxproj b/darkplaces-sdl-vs2012.vcxproj index 0e182318..e4edd190 100644 --- a/darkplaces-sdl-vs2012.vcxproj +++ b/darkplaces-sdl-vs2012.vcxproj @@ -257,6 +257,7 @@ + @@ -362,6 +363,7 @@ + diff --git a/darkplaces-sdl.dsp b/darkplaces-sdl.dsp index 11fac692..69425882 100644 --- a/darkplaces-sdl.dsp +++ b/darkplaces-sdl.dsp @@ -362,6 +362,10 @@ SOURCE=.\snd_mix.c # End Source File # Begin Source File +SOURCE=.\snd_modplug.c +# End Source File +# Begin Source File + SOURCE=.\snd_ogg.c # End Source File # Begin Source File @@ -706,6 +710,10 @@ SOURCE=.\snd_main.h # End Source File # Begin Source File +SOURCE=.\snd_modplug.h +# End Source File +# Begin Source File + SOURCE=.\snd_ogg.h # End Source File # Begin Source File diff --git a/darkplaces-sdl.vcproj b/darkplaces-sdl.vcproj index 4914baed..39f36c6a 100755 --- a/darkplaces-sdl.vcproj +++ b/darkplaces-sdl.vcproj @@ -626,6 +626,10 @@ RelativePath=".\snd_mix.c" > + + @@ -1044,6 +1048,10 @@ RelativePath=".\snd_main.h" > + + diff --git a/darkplaces-wgl-vs2010.vcxproj b/darkplaces-wgl-vs2010.vcxproj index 3515e804..2055fc60 100644 --- a/darkplaces-wgl-vs2010.vcxproj +++ b/darkplaces-wgl-vs2010.vcxproj @@ -167,6 +167,7 @@ + @@ -272,6 +273,7 @@ + diff --git a/darkplaces-wgl-vs2012.vcxproj b/darkplaces-wgl-vs2012.vcxproj index f9ad5fb4..ecf841de 100644 --- a/darkplaces-wgl-vs2012.vcxproj +++ b/darkplaces-wgl-vs2012.vcxproj @@ -259,6 +259,7 @@ + @@ -364,6 +365,7 @@ + diff --git a/darkplaces-wgl.vcproj b/darkplaces-wgl.vcproj index 21d6ff3e..a0a4260a 100644 --- a/darkplaces-wgl.vcproj +++ b/darkplaces-wgl.vcproj @@ -628,6 +628,10 @@ RelativePath=".\snd_mix.c" > + + @@ -1046,6 +1050,10 @@ RelativePath=".\snd_main.h" > + + diff --git a/darkplaces.dsp b/darkplaces.dsp index 5cf31799..672e25cb 100644 --- a/darkplaces.dsp +++ b/darkplaces.dsp @@ -366,6 +366,10 @@ SOURCE=.\snd_mix.c # End Source File # Begin Source File +SOURCE=.\snd_modplug.c +# End Source File +# Begin Source File + SOURCE=.\snd_ogg.c # End Source File # Begin Source File @@ -710,6 +714,10 @@ SOURCE=.\snd_main.h # End Source File # Begin Source File +SOURCE=.\snd_modplug.h +# End Source File +# Begin Source File + SOURCE=.\snd_ogg.h # End Source File # Begin Source File diff --git a/makefile b/makefile index bbd0a76d..e2bfdd5e 100644 --- a/makefile +++ b/makefile @@ -112,6 +112,7 @@ ifeq ($(DP_MAKE_TARGET), linux) DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen + DP_LINK_MODPLUG?=dlopen endif # Mac OS X configuration @@ -147,6 +148,7 @@ ifeq ($(DP_MAKE_TARGET), macosx) DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen + DP_LINK_MODPLUG?=dlopen # on OS X, we don't build the CL by default because it uses deprecated # and not-implemented-in-64bit Carbon @@ -188,6 +190,7 @@ ifeq ($(DP_MAKE_TARGET), sunos) DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen + DP_LINK_MODPLUG?=dlopen endif # BSD configuration @@ -223,6 +226,7 @@ endif DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen + DP_LINK_MODPLUG?=dlopen endif # Win32 configuration @@ -282,6 +286,7 @@ ifeq ($(DP_MAKE_TARGET), mingw) DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen + DP_LINK_MODPLUG?=dlopen endif # set these to "" if you want to use dynamic loading instead @@ -334,6 +339,17 @@ ifeq ($(DP_LINK_CRYPTO_RIJNDAEL), dlopen) CFLAGS_CRYPTO_RIJNDAEL= endif +# modplug +ifeq ($(DP_LINK_MODPLUG), shared) + CFLAGS_SND_MODPLUG=-DLINK_TO_LIBMODPLUG + LIB_SND_MODPLUG=-lmodplug +endif +ifeq ($(DP_LINK_MODPLUG), dlopen) + CFLAGS_SND_MODPLUG= + LIB_SND_MODPLUG= +endif + + ##### Sound configuration ##### ifndef DP_SOUND_API diff --git a/makefile.inc b/makefile.inc index c7e98d22..7b793151 100644 --- a/makefile.inc +++ b/makefile.inc @@ -41,7 +41,7 @@ STRIP?=strip ###### Sound and audio CD ##### -OBJ_SND_COMMON=snd_main.o snd_mem.o snd_mix.o snd_ogg.o snd_wav.o +OBJ_SND_COMMON=snd_main.o snd_mem.o snd_mix.o snd_ogg.o snd_wav.o snd_modplug.o # No sound OBJ_SND_NULL=snd_null.o @@ -49,23 +49,23 @@ LIB_SND_NULL= # Open Sound System (Linux, FreeBSD and Solaris) OBJ_SND_OSS=$(OBJ_SND_COMMON) snd_oss.o -LIB_SND_OSS= +LIB_SND_OSS=$(LIB_SND_MODPLUG) # Advanced Linux Sound Architecture (Linux) OBJ_SND_ALSA=$(OBJ_SND_COMMON) snd_alsa.o -LIB_SND_ALSA=-lasound +LIB_SND_ALSA=-lasound $(LIB_SND_MODPLUG) # Core Audio (Mac OS X) OBJ_SND_COREAUDIO=$(OBJ_SND_COMMON) snd_coreaudio.o -LIB_SND_COREAUDIO=-framework CoreAudio +LIB_SND_COREAUDIO=-framework CoreAudio $(LIB_SND_MODPLUG) # BSD / Sun audio API (NetBSD and OpenBSD) OBJ_SND_BSD=$(OBJ_SND_COMMON) snd_bsd.o -LIB_SND_BSD= +LIB_SND_BSD=$(LIB_SND_MODPLUG) # DirectX and Win32 WAVE output (Win32) OBJ_SND_WIN=$(OBJ_SND_COMMON) snd_win.o -LIB_SND_WIN= +LIB_SND_WIN=$(LIB_SND_MODPLUG) # Qantourisc's 3D Realtime Acoustic Lib (3D RAS) OBJ_SND_3DRAS=snd_3dras.o @@ -207,12 +207,12 @@ OBJ_GLX= builddate.c sys_linux.o vid_glx.o thread_pthread.o keysym2ucs.o $(OBJ_M LDFLAGS_UNIXCOMMON=-lm $(LIB_ODE) $(LIB_Z) $(LIB_JPEG) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) LDFLAGS_UNIXCL=-L$(UNIX_X11LIBPATH) -lX11 -lXpm -lXext -lXxf86vm -pthread $(LIB_SOUND) -LDFLAGS_UNIXCL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl +LDFLAGS_UNIXCL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl -lmodplug LDFLAGS_UNIXSV_PRELOAD=-lz -ljpeg -lpng -lcurl -LDFLAGS_UNIXSDL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl +LDFLAGS_UNIXSDL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl -lmodplug CFLAGS_UNIX_PRELOAD=-DPREFER_PRELOAD -LDFLAGS_UNIXSDL=$(SDLCONFIG_LIBS) +LDFLAGS_UNIXSDL=$(SDLCONFIG_LIBS) $(LIB_SND_MODPLUG) EXE_UNIXCL=darkplaces-glx EXE_UNIXSV=darkplaces-dedicated EXE_UNIXSDL=darkplaces-sdl @@ -280,7 +280,7 @@ OBJ_WGL= builddate.c sys_win.o vid_wgl.o thread_null.o $(OBJ_MENU) $(OBJ_SND_WIN # see LDFLAGS_WINCOMMON in makefile LDFLAGS_WINCL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) -mwindows -lwinmm -luser32 -lgdi32 -ldxguid -ldinput -lcomctl32 -lws2_32 $(LDFLAGS_D3D) $(LIB_Z) $(LIB_JPEG) LDFLAGS_WINSV=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) -mconsole -lwinmm -lws2_32 $(LIB_Z) $(LIB_JPEG) -LDFLAGS_WINSDL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) $(SDLCONFIG_LIBS) -lwinmm -lws2_32 $(LIB_Z) $(LIB_JPEG) +LDFLAGS_WINSDL=$(LDFLAGS_WINCOMMON) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) $(SDLCONFIG_LIBS) $(LIB_SND_MODPLUG) -lwinmm -lws2_32 $(LIB_Z) $(LIB_JPEG) EXE_WINCL=darkplaces.exe EXE_WINSV=darkplaces-dedicated.exe EXE_WINSDL=darkplaces-sdl.exe @@ -490,6 +490,10 @@ prepare : $(CMD_CP) makefile.inc $(BUILD_DIR)/ $(CMD_CP) $(MAKEFILE) $(BUILD_DIR)/ +snd_modplug.o: snd_modplug.c + $(CHECKLEVEL2) + $(DO_CC) $(CFLAGS_SND_MODPLUG) + #this checks USEODE when compiling so it needs the ODE flags as well prvm_cmds.o: prvm_cmds.c $(CHECKLEVEL2) diff --git a/snd_main.c b/snd_main.c index 251084a0..325d3dfb 100644 --- a/snd_main.c +++ b/snd_main.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_main.h" #include "snd_ogg.h" +#include "snd_modplug.h" #include "csprogs.h" #include "cl_collision.h" #ifdef CONFIG_CD @@ -916,6 +917,7 @@ void S_Init(void) memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); OGG_OpenLibrary (); + ModPlug_OpenLibrary (); } @@ -929,6 +931,7 @@ Shutdown and free all resources void S_Terminate (void) { S_Shutdown (); + ModPlug_CloseLibrary (); OGG_CloseLibrary (); // Free all SFXs diff --git a/snd_mem.c b/snd_mem.c index f6f9c145..8778b0cc 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_main.h" #include "snd_ogg.h" #include "snd_wav.h" +#include "snd_modplug.h" /* @@ -343,6 +344,11 @@ qboolean S_LoadSound (sfx_t *sfx, qboolean complain) if (OGG_LoadVorbisFile (namebuffer, sfx)) goto loaded; } + else + { + if (ModPlug_LoadModPlugFile (namebuffer, sfx)) + goto loaded; + } } // LordHavoc: then try without the added sound/ as wav and ogg @@ -362,6 +368,11 @@ qboolean S_LoadSound (sfx_t *sfx, qboolean complain) if (OGG_LoadVorbisFile (namebuffer, sfx)) goto loaded; } + else + { + if (ModPlug_LoadModPlugFile (namebuffer, sfx)) + goto loaded; + } // Can't load the sound! sfx->flags |= SFXFLAG_FILEMISSING; diff --git a/snd_modplug.c b/snd_modplug.c new file mode 100644 index 00000000..fa0e57f5 --- /dev/null +++ b/snd_modplug.c @@ -0,0 +1,437 @@ +/* + Copyright (C) 2003-2005 Mathieu Olivier + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + + +#include "quakedef.h" +#include "snd_main.h" +#include "snd_modplug.h" + +#ifdef LINK_TO_LIBMODPLUG + +#include +qboolean ModPlug_OpenLibrary (void) +{ + return true; // statically linked +} +void ModPlug_CloseLibrary (void) +{ +} +#define modplug_dll 1 +#define qModPlug_Load ModPlug_Load +#define qModPlug_Unload ModPlug_Unload +#define qModPlug_Read ModPlug_Read +#define qModPlug_Seek ModPlug_Seek +#define qModPlug_GetSettings ModPlug_GetSettings +#define qModPlug_SetSettings ModPlug_SetSettings +#define qModPlug_SetMasterVolume ModPlug_SetMasterVolume + +#else +// BEGIN SECTION FROM modplug.h + + /* + * This source code is public domain. + * + * Authors: Kenton Varda (C interface wrapper) + */ + + enum _ModPlug_Flags + { + MODPLUG_ENABLE_OVERSAMPLING = 1 << 0, /* Enable oversampling (*highly* recommended) */ + MODPLUG_ENABLE_NOISE_REDUCTION = 1 << 1, /* Enable noise reduction */ + MODPLUG_ENABLE_REVERB = 1 << 2, /* Enable reverb */ + MODPLUG_ENABLE_MEGABASS = 1 << 3, /* Enable megabass */ + MODPLUG_ENABLE_SURROUND = 1 << 4 /* Enable surround sound. */ + }; + + enum _ModPlug_ResamplingMode + { + MODPLUG_RESAMPLE_NEAREST = 0, /* No interpolation (very fast, extremely bad sound quality) */ + MODPLUG_RESAMPLE_LINEAR = 1, /* Linear interpolation (fast, good quality) */ + MODPLUG_RESAMPLE_SPLINE = 2, /* Cubic spline interpolation (high quality) */ + MODPLUG_RESAMPLE_FIR = 3 /* 8-tap fir filter (extremely high quality) */ + }; + + typedef struct _ModPlug_Settings + { + int mFlags; /* One or more of the MODPLUG_ENABLE_* flags above, bitwise-OR'ed */ + + /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then + * down-mixes to the settings you choose. */ + int mChannels; /* Number of channels - 1 for mono or 2 for stereo */ + int mBits; /* Bits per sample - 8, 16, or 32 */ + int mFrequency; /* Sampling rate - 11025, 22050, or 44100 */ + int mResamplingMode; /* One of MODPLUG_RESAMPLE_*, above */ + + int mStereoSeparation; /* Stereo separation, 1 - 256 */ + int mMaxMixChannels; /* Maximum number of mixing channels (polyphony), 32 - 256 */ + + int mReverbDepth; /* Reverb level 0(quiet)-100(loud) */ + int mReverbDelay; /* Reverb delay in ms, usually 40-200ms */ + int mBassAmount; /* XBass level 0(quiet)-100(loud) */ + int mBassRange; /* XBass cutoff in Hz 10-100 */ + int mSurroundDepth; /* Surround level 0(quiet)-100(heavy) */ + int mSurroundDelay; /* Surround delay in ms, usually 5-40ms */ + int mLoopCount; /* Number of times to loop. Zero prevents looping. + -1 loops forever. */ + } ModPlug_Settings; + + struct _ModPlugFile; + typedef struct _ModPlugFile ModPlugFile; + +// END SECTION FROM modplug.h + +static ModPlugFile* (*qModPlug_Load) (const void* data, int size); +static void (*qModPlug_Unload) (ModPlugFile* file); +static int (*qModPlug_Read) (ModPlugFile* file, void* buffer, int size); +static void (*qModPlug_Seek) (ModPlugFile* file, int millisecond); +static void (*qModPlug_GetSettings) (ModPlug_Settings* settings); +static void (*qModPlug_SetSettings) (const ModPlug_Settings* settings); +typedef void (ModPlug_SetMasterVolume_t) (ModPlugFile* file,unsigned int cvol) ; +ModPlug_SetMasterVolume_t *qModPlug_SetMasterVolume; + + +static dllfunction_t modplugfuncs[] = +{ + {"ModPlug_Load", (void **) &qModPlug_Load}, + {"ModPlug_Unload", (void **) &qModPlug_Unload}, + {"ModPlug_Read", (void **) &qModPlug_Read}, + {"ModPlug_Seek", (void **) &qModPlug_Seek}, + {"ModPlug_GetSettings", (void **) &qModPlug_GetSettings}, + {"ModPlug_SetSettings", (void **) &qModPlug_SetSettings}, + {NULL, NULL} +}; + +// Handles for the modplug and modplugfile DLLs +static dllhandle_t modplug_dll = NULL; + +/* +================================================================= + + DLL load & unload + +================================================================= +*/ + +/* +==================== +ModPlug_OpenLibrary + +Try to load the modplugFile DLL +==================== +*/ +qboolean ModPlug_OpenLibrary (void) +{ + const char* dllnames_modplug [] = + { +#if defined(WIN32) + "libmodplug-1.dll", + "modplug.dll", +#elif defined(MACOSX) + "libmodplug.dylib", +#else + "libmodplug.so.1", + "libmodplug.so", +#endif + NULL + }; + + // Already loaded? + if (modplug_dll) + return true; + +// COMMANDLINEOPTION: Sound: -nomodplug disables modplug sound support + if (COM_CheckParm("-nomodplug")) + return false; + +#ifdef __ANDROID__ + Con_Print("Warning: no modplug support in Android yet.\n"); + return false; +#endif + + // Load the DLLs + // We need to load both by hand because some OSes seem to not load + // the modplug DLL automatically when loading the modplugFile DLL + if(Sys_LoadLibrary (dllnames_modplug, &modplug_dll, modplugfuncs)) + { + qModPlug_SetMasterVolume = (ModPlug_SetMasterVolume_t *) Sys_GetProcAddress(modplug_dll, "ModPlug_SetMasterVolume"); + if(!qModPlug_SetMasterVolume) + Con_Print("Warning: modplug volume control not supported. Try getting a newer version of libmodplug.\n"); + return true; + } + else + return false; +} + + +/* +==================== +ModPlug_CloseLibrary + +Unload the modplugFile DLL +==================== +*/ +void ModPlug_CloseLibrary (void) +{ + Sys_UnloadLibrary (&modplug_dll); +} +#endif + + +/* +================================================================= + + modplug decoding + +================================================================= +*/ + +// Per-sfx data structure +typedef struct +{ + unsigned char *file; + size_t filesize; +} modplug_stream_persfx_t; + +// Per-channel data structure +typedef struct +{ + ModPlugFile *mf; + int bs; + int buffer_firstframe; + int buffer_numframes; + unsigned char buffer[STREAM_BUFFERSIZE*4]; +} modplug_stream_perchannel_t; + + +/* +==================== +ModPlug_GetSamplesFloat +==================== +*/ +static void ModPlug_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat) +{ + modplug_stream_perchannel_t* per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data; + modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data; + int newlength, done, ret; + int f = sfx->format.width * sfx->format.channels; // bytes per frame + short *buf; + int i, len; + + // If there's no fetcher structure attached to the channel yet + if (per_ch == NULL) + { + per_ch = (modplug_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch)); + + // Open it with the modplugFile API + per_ch->mf = qModPlug_Load(per_sfx->file, per_sfx->filesize); + if (!per_ch->mf) + { + // we can't call Con_Printf here, not thread safe +// Con_Printf("error while reading ModPlug stream \"%s\"\n", per_sfx->name); + Mem_Free(per_ch); + return; + } + +#ifndef LINK_TO_LIBMODPLUG + if(qModPlug_SetMasterVolume) +#endif + qModPlug_SetMasterVolume(per_ch->mf, 512); // max volume, DP scales down! + + per_ch->bs = 0; + + per_ch->buffer_firstframe = 0; + per_ch->buffer_numframes = 0; + ch->fetcher_data = per_ch; + } + + // if the request is too large for our buffer, loop... + while (numsampleframes * f > (int)sizeof(per_ch->buffer)) + { + done = sizeof(per_ch->buffer) / f; + ModPlug_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat); + firstsampleframe += done; + numsampleframes -= done; + outsamplesfloat += done * sfx->format.channels; + } + + // seek if the request is before the current buffer (loop back) + // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while) + // do not seek if the request overlaps the buffer end at all (expected behavior) + if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe) + { + // we expect to decode forward from here so this will be our new buffer start + per_ch->buffer_firstframe = firstsampleframe; + per_ch->buffer_numframes = 0; + // we don't actually seek - we don't care much about timing on silent mod music streams and looping never happens + //qModPlug_Seek(per_ch->mf, firstsampleframe * 1000.0 / sfx->format.speed); + } + + // decompress the file as needed + if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes) + { + // first slide the buffer back, discarding any data preceding the range we care about + int offset = firstsampleframe - per_ch->buffer_firstframe; + int keeplength = per_ch->buffer_numframes - offset; + if (keeplength > 0) + memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels); + per_ch->buffer_firstframe = firstsampleframe; + per_ch->buffer_numframes -= offset; + // decompress as much as we can fit in the buffer + newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f; + done = 0; + while (newlength > done && (ret = qModPlug_Read(per_ch->mf, (void *)((unsigned char *)per_ch->buffer + done), (int)(newlength - done))) > 0) + done += ret; + // clear the missing space if any + if (done < newlength) + { + memset(per_ch->buffer + done, 0, newlength - done); + // Argh. We didn't get as many samples as we wanted. Probably + // libmodplug forgot what mLoopCount==-1 means... basically, this means + // we can't loop like this. Try to let DP fix it later... + sfx->total_length = firstsampleframe + done / f; + sfx->loopstart = 0; + // can't Con_Printf from this thread + //if (newlength != done) + // Con_DPrintf("ModPlug_Fetch: wanted: %d, got: %d\n", newlength, done); + } + // we now have more data in the buffer + per_ch->buffer_numframes += done / f; + } + + // convert the sample format for the caller + buf = (short *)(per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f); + len = numsampleframes * sfx->format.channels; + for (i = 0;i < len;i++) + outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f); +} + + +/* +==================== +ModPlug_StopChannel +==================== +*/ +static void ModPlug_StopChannel(channel_t *ch) +{ + modplug_stream_perchannel_t *per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data; + + if (per_ch != NULL) + { + // Free the modplug decoder + qModPlug_Unload(per_ch->mf); + + Mem_Free(per_ch); + } +} + + +/* +==================== +ModPlug_FreeSfx +==================== +*/ +static void ModPlug_FreeSfx (sfx_t *sfx) +{ + modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data; + + // Free the modplug file + Mem_Free(per_sfx->file); + + // Free the stream structure + Mem_Free(per_sfx); +} + + +static const snd_fetcher_t modplug_fetcher = { ModPlug_GetSamplesFloat, ModPlug_StopChannel, ModPlug_FreeSfx }; + + +/* +==================== +ModPlug_LoadmodplugFile + +Load an modplug file into memory +==================== +*/ +qboolean ModPlug_LoadModPlugFile (const char *filename, sfx_t *sfx) +{ + unsigned char *data; + fs_offset_t filesize; + ModPlugFile *mf; + modplug_stream_persfx_t* per_sfx; + ModPlug_Settings s; + + if (!modplug_dll) + return false; + + // Already loaded? + if (sfx->fetcher != NULL) + return true; + + // Load the file + data = FS_LoadFile (filename, snd_mempool, false, &filesize); + if (data == NULL) + return false; + + if (developer_loading.integer >= 2) + Con_Printf ("Loading ModPlug file \"%s\"\n", filename); + + qModPlug_GetSettings(&s); + s.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION | MODPLUG_ENABLE_REVERB; + s.mChannels = 2; + s.mBits = 16; + s.mFrequency = 44100; + s.mResamplingMode = MODPLUG_RESAMPLE_SPLINE; + s.mLoopCount = -1; + qModPlug_SetSettings(&s); + + // Open it with the modplugFile API + if (!(mf = qModPlug_Load (data, filesize))) + { + Con_Printf ("error while opening ModPlug file \"%s\"\n", filename); + Mem_Free(data); + return false; + } + +#ifndef LINK_TO_LIBMODPLUG + if(qModPlug_SetMasterVolume) +#endif + qModPlug_SetMasterVolume(mf, 512); // max volume, DP scales down! + + if (developer_loading.integer >= 2) + Con_Printf ("\"%s\" will be streamed\n", filename); + per_sfx = (modplug_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx)); + per_sfx->file = data; + per_sfx->filesize = filesize; + sfx->memsize += sizeof(*per_sfx); + sfx->memsize += filesize; + sfx->format.speed = 44100; // modplug always works at that rate + sfx->format.width = 2; // We always work with 16 bits samples + sfx->format.channels = 2; // stereo rulez ;) (MAYBE default to mono because Amiga MODs sound better then?) + sfx->fetcher_data = per_sfx; + sfx->fetcher = &modplug_fetcher; + sfx->flags |= SFXFLAG_STREAMED; + sfx->total_length = 1<<30; // 2147384647; // they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!) + sfx->loopstart = sfx->total_length; // modplug does it + + return true; +} diff --git a/snd_modplug.h b/snd_modplug.h new file mode 100644 index 00000000..08110801 --- /dev/null +++ b/snd_modplug.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2003 Mathieu Olivier + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef SND_ModPlug_H +#define SND_ModPlug_H + + +qboolean ModPlug_OpenLibrary (void); +void ModPlug_CloseLibrary (void); +qboolean ModPlug_LoadModPlugFile (const char *filename, sfx_t *sfx); + + +#endif -- 2.39.2