Conflicts:
	src/CMakeLists.txt
This commit is contained in:
Christoph Oelckers 2015-04-27 09:41:06 +02:00
commit 3ddc3d8feb
54 changed files with 4631 additions and 683 deletions

View file

@ -106,6 +106,9 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
option( NO_FMOD "Disable FMODEx sound support" OFF )
option( NO_OPENAL "Disable OpenAL sound support" OFF )
find_package( BZip2 ) find_package( BZip2 )
find_package( JPEG ) find_package( JPEG )
find_package( ZLIB ) find_package( ZLIB )

28
FindMPG123.cmake Normal file
View file

@ -0,0 +1,28 @@
# - Find mpg123
# Find the native mpg123 includes and library
#
# MPG123_INCLUDE_DIR - where to find mpg123.h
# MPG123_LIBRARIES - List of libraries when using mpg123.
# MPG123_FOUND - True if mpg123 found.
IF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
# Already in cache, be silent
SET(MPG123_FIND_QUIETLY TRUE)
ENDIF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
FIND_PATH(MPG123_INCLUDE_DIR mpg123.h
PATHS "${MPG123_DIR}"
PATH_SUFFIXES include
)
FIND_LIBRARY(MPG123_LIBRARIES NAMES mpg123 mpg123-0
PATHS "${MPG123_DIR}"
PATH_SUFFIXES lib
)
# MARK_AS_ADVANCED(MPG123_LIBRARIES MPG123_INCLUDE_DIR)
# handle the QUIETLY and REQUIRED arguments and set MPG123_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MPG123 DEFAULT_MSG MPG123_LIBRARIES MPG123_INCLUDE_DIR)

29
FindSndFile.cmake Normal file
View file

@ -0,0 +1,29 @@
# - Try to find SndFile
# Once done this will define
#
# SNDFILE_FOUND - system has SndFile
# SNDFILE_INCLUDE_DIRS - the SndFile include directory
# SNDFILE_LIBRARIES - Link these to use SndFile
#
# Copyright © 2006 Wengo
# Copyright © 2009 Guillaume Martres
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
find_path(SNDFILE_INCLUDE_DIR NAMES sndfile.h)
find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1)
set(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR})
set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY})
INCLUDE(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if
# all listed variables are TRUE
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
# show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view
mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)

View file

@ -1,4 +1,5 @@
cmake_minimum_required( VERSION 2.4 ) cmake_minimum_required( VERSION 2.4 )
if( NOT NO_FMOD AND FMOD_INCLUDE_DIR )
add_library( output_sdl MODULE output_sdl.c ) add_library( output_sdl MODULE output_sdl.c )
include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} ) include_directories( ${FMOD_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} )
target_link_libraries( output_sdl ${SDL2_LIBRARY} ) target_link_libraries( output_sdl ${SDL2_LIBRARY} )
@ -7,3 +8,4 @@ FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}
add_custom_command( TARGET output_sdl POST_BUILD add_custom_command( TARGET output_sdl POST_BUILD
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
endif( NOT NO_FMOD AND FMOD_INCLUDE_DIR )

View file

@ -213,40 +213,20 @@ else( WIN32 )
endif( FPU_CONTROL_DIR ) endif( FPU_CONTROL_DIR )
endif( WIN32 ) endif( WIN32 )
if( X64 )
set( NO_ASM ON )
endif( X64 )
# Check if we have OpenGL
if( NOT OPENGL_FOUND )
message( FATAL_ERROR "OpenGL is required for building." )
endif( NOT OPENGL_FOUND )
if( NOT OPENGL_GLU_FOUND )
message( FATAL_ERROR "OpenGL GLU is required for building." )
endif( NOT OPENGL_GLU_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${OPENGL_LIBRARIES} )
include_directories( ${OPENGL_INCLUDE_DIR} )
# Decide on the name of the FMOD library we want to use.
if( NOT FMOD_LIB_NAME AND MSVC )
set( FMOD_LIB_NAME fmodex${X64}_vc )
endif( NOT FMOD_LIB_NAME AND MSVC )
if( NOT FMOD_LIB_NAME AND BORLAND )
set( FMOD_LIB_NAME fmodex${X64}_bc )
endif( NOT FMOD_LIB_NAME AND BORLAND )
if( NOT FMOD_LIB_NAME )
set( FMOD_LIB_NAME fmodex${X64} )
endif( NOT FMOD_LIB_NAME )
if( NOT NO_OPENAL )
find_package( OpenAL )
mark_as_advanced(CLEAR OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
if( OPENAL_FOUND )
include_directories( ${OPENAL_INCLUDE_DIR} )
set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} )
else( OPENAL_FOUND )
set( NO_OPENAL ON )
endif( OPENAL_FOUND )
endif( NOT NO_OPENAL )
if( NOT NO_FMOD )
# Search for FMOD include files # Search for FMOD include files
if( NOT WIN32 ) if( NOT WIN32 )
find_path( FMOD_INCLUDE_DIR fmod.hpp find_path( FMOD_INCLUDE_DIR fmod.hpp
PATHS ${FMOD_LOCAL_INC_DIRS} ) PATHS ${FMOD_LOCAL_INC_DIRS} )
@ -260,13 +240,28 @@ endif( NOT FMOD_INCLUDE_DIR )
if( FMOD_INCLUDE_DIR ) if( FMOD_INCLUDE_DIR )
message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" ) message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" )
include_directories( "${FMOD_INCLUDE_DIR}" )
else( FMOD_INCLUDE_DIR ) else( FMOD_INCLUDE_DIR )
message( SEND_ERROR "Could not find FMOD include files" ) message( STATUS "Could not find FMOD include files" )
set( NO_FMOD ON )
endif( FMOD_INCLUDE_DIR ) endif( FMOD_INCLUDE_DIR )
endif( NOT NO_FMOD )
if( NOT NO_FMOD )
# Decide on the name of the FMOD library we want to use.
if( NOT FMOD_LIB_NAME AND MSVC )
set( FMOD_LIB_NAME fmodex${X64}_vc )
endif( NOT FMOD_LIB_NAME AND MSVC )
if( NOT FMOD_LIB_NAME AND BORLAND )
set( FMOD_LIB_NAME fmodex${X64}_bc )
endif( NOT FMOD_LIB_NAME AND BORLAND )
if( NOT FMOD_LIB_NAME )
set( FMOD_LIB_NAME fmodex${X64} )
endif( NOT FMOD_LIB_NAME )
# Search for FMOD library # Search for FMOD library
if( WIN32 OR APPLE ) if( WIN32 OR APPLE )
find_library( FMOD_LIBRARY ${FMOD_LIB_NAME} find_library( FMOD_LIBRARY ${FMOD_LIB_NAME}
PATHS ${FMOD_SEARCH_PATHS} PATHS ${FMOD_SEARCH_PATHS}
@ -279,10 +274,27 @@ endif( WIN32 OR APPLE )
if( FMOD_LIBRARY ) if( FMOD_LIBRARY )
message( STATUS "FMOD library found at ${FMOD_LIBRARY}" ) message( STATUS "FMOD library found at ${FMOD_LIBRARY}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FMOD_LIBRARY}" )
else( FMOD_LIBRARY ) else( FMOD_LIBRARY )
message( SEND_ERROR "Could not find FMOD library" ) message( STATUS "Could not find FMOD library" )
set( NO_FMOD ON )
endif( FMOD_LIBRARY ) endif( FMOD_LIBRARY )
endif( NOT NO_FMOD )
if( NO_FMOD )
add_definitions( -DNO_FMOD=1 )
endif( NO_FMOD )
if( NO_OPENAL )
add_definitions( -DNO_OPENAL=1 )
endif( NO_OPENAL )
# Search for libSndFile
find_package( SndFile )
# Search for libmpg123
find_package( MPG123 )
# Search for FluidSynth # Search for FluidSynth
@ -530,9 +542,17 @@ add_custom_target( revision_check ALL
# Libraries ZDoom needs # Libraries ZDoom needs
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${FMOD_LIBRARY}" ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" )
include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" ) include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
if( SNDFILE_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SNDFILE_LIBRARIES}" )
include_directories( "${SNDFILE_INCLUDE_DIRS}" )
endif( SNDFILE_FOUND )
if( MPG123_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${MPG123_LIBRARIES}" )
include_directories( "${MPG123_INCLUDE_DIR}" )
endif( MPG123_FOUND )
if( NOT DYN_FLUIDSYNTH) if( NOT DYN_FLUIDSYNTH)
if( FLUIDSYNTH_FOUND ) if( FLUIDSYNTH_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
@ -673,6 +693,12 @@ else( SSE_MATTERS )
set( X86_SOURCES ) set( X86_SOURCES )
endif( SSE_MATTERS ) endif( SSE_MATTERS )
if( SNDFILE_FOUND )
add_definitions( -DHAVE_SNDFILE )
endif( SNDFILE_FOUND )
if( MPG123_FOUND )
add_definitions( -DHAVE_MPG123 )
endif( MPG123_FOUND )
if( DYN_FLUIDSYNTH ) if( DYN_FLUIDSYNTH )
add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH ) add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH )
elseif( FLUIDSYNTH_FOUND ) elseif( FLUIDSYNTH_FOUND )
@ -1120,6 +1146,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
sound/fmodsound.cpp sound/fmodsound.cpp
sound/i_music.cpp sound/i_music.cpp
sound/i_sound.cpp sound/i_sound.cpp
sound/mpg123_decoder.cpp
sound/music_cd.cpp sound/music_cd.cpp
sound/music_dumb.cpp sound/music_dumb.cpp
sound/music_gme.cpp sound/music_gme.cpp
@ -1136,6 +1163,8 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
sound/music_softsynth_mididevice.cpp sound/music_softsynth_mididevice.cpp
sound/music_timidity_mididevice.cpp sound/music_timidity_mididevice.cpp
sound/music_win_mididevice.cpp sound/music_win_mididevice.cpp
sound/oalsound.cpp
sound/sndfile_decoder.cpp
sound/music_pseudo_mididevice.cpp sound/music_pseudo_mididevice.cpp
textures/animations.cpp textures/animations.cpp
textures/anim_switches.cpp textures/anim_switches.cpp
@ -1248,9 +1277,9 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS )
if( MSVC ) if( MSVC )
option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF )
if( ZDOOM_GENERATE_MAPFILE ) if( ZDOOM_GENERATE_MAPFILE )
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\" /MAP")
else( ZDOOM_GENERATE_MAPFILE ) else( ZDOOM_GENERATE_MAPFILE )
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"")
endif( ZDOOM_GENERATE_MAPFILE ) endif( ZDOOM_GENERATE_MAPFILE )
add_custom_command(TARGET zdoom POST_BUILD add_custom_command(TARGET zdoom POST_BUILD

View file

@ -905,6 +905,7 @@ void D_Display ()
} while (diff < 1); } while (diff < 1);
wipestart = nowtime; wipestart = nowtime;
done = screen->WipeDo (1); done = screen->WipeDo (1);
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
C_DrawConsole (hw2d); // console and C_DrawConsole (hw2d); // console and
M_Drawer (); // menu are drawn even on top of wipes M_Drawer (); // menu are drawn even on top of wipes
screen->Update (); // page flip or blit buffer screen->Update (); // page flip or blit buffer
@ -1003,6 +1004,7 @@ void D_DoomLoop ()
// Update display, next frame, with current state. // Update display, next frame, with current state.
I_StartTic (); I_StartTic ();
D_Display (); D_Display ();
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
} }
catch (CRecoverableError &error) catch (CRecoverableError &error)
{ {

View file

@ -544,3 +544,59 @@ char *MemoryReader::Gets(char *strbuf, int len)
{ {
return GetsFromBuffer(bufptr, strbuf, len); return GetsFromBuffer(bufptr, strbuf, len);
} }
//==========================================================================
//
// MemoryArrayReader
//
// reads data from an array of memory
//
//==========================================================================
MemoryArrayReader::MemoryArrayReader (const char *buffer, long length)
{
buf.Resize(length);
memcpy(&buf[0], buffer, length);
Length=length;
FilePos=0;
}
MemoryArrayReader::~MemoryArrayReader ()
{
}
long MemoryArrayReader::Tell () const
{
return FilePos;
}
long MemoryArrayReader::Seek (long offset, int origin)
{
switch (origin)
{
case SEEK_CUR:
offset+=FilePos;
break;
case SEEK_END:
offset+=Length;
break;
}
FilePos=clamp<long>(offset,0,Length-1);
return 0;
}
long MemoryArrayReader::Read (void *buffer, long len)
{
if (len>Length-FilePos) len=Length-FilePos;
if (len<0) len=0;
memcpy(buffer,&buf[FilePos],len);
FilePos+=len;
return len;
}
char *MemoryArrayReader::Gets(char *strbuf, int len)
{
return GetsFromBuffer((char*)&buf[0], strbuf, len);
}

View file

@ -336,6 +336,24 @@ protected:
const char * bufptr; const char * bufptr;
}; };
class MemoryArrayReader : public FileReader
{
public:
MemoryArrayReader (const char *buffer, long length);
~MemoryArrayReader ();
virtual long Tell () const;
virtual long Seek (long offset, int origin);
virtual long Read (void *buffer, long len);
virtual char *Gets(char *strbuf, int len);
virtual const char *GetBuffer() const { return (char*)&buf[0]; }
TArray<BYTE> &GetArray() { return buf; }
void UpdateLength() { Length = buf.Size(); }
protected:
TArray<BYTE> buf;
};
#endif #endif

View file

@ -49,6 +49,7 @@
#include "i_music.h" #include "i_music.h"
#include "m_joy.h" #include "m_joy.h"
#include "gi.h" #include "gi.h"
#include "i_sound.h"
#include "optionmenuitems.h" #include "optionmenuitems.h"
@ -60,6 +61,8 @@ static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common setti
FOptionMenuSettings OptionSettings; FOptionMenuSettings OptionSettings;
FOptionMap OptionValues; FOptionMap OptionValues;
void I_BuildALDeviceList(FOptionValues *opt);
static void DeinitMenus() static void DeinitMenus()
{ {
{ {
@ -168,6 +171,14 @@ static bool CheckSkipOptionBlock(FScanner &sc)
filter = true; filter = true;
#endif #endif
} }
else if (sc.Compare("OpenAL"))
{
filter |= IsOpenALPresent();
}
else if (sc.Compare("FModEx"))
{
filter |= IsFModExPresent();
}
} }
while (sc.CheckString(",")); while (sc.CheckString(","));
sc.MustGetStringName(")"); sc.MustGetStringName(")");
@ -589,7 +600,11 @@ static void ParseOptionSettings(FScanner &sc)
while (!sc.CheckString("}")) while (!sc.CheckString("}"))
{ {
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("ifgame")) if (sc.Compare("else"))
{
SkipSubBlock(sc);
}
else if (sc.Compare("ifgame"))
{ {
if (!CheckSkipGameBlock(sc)) if (!CheckSkipGameBlock(sc))
{ {
@ -626,7 +641,11 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
while (!sc.CheckString("}")) while (!sc.CheckString("}"))
{ {
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("ifgame")) if (sc.Compare("else"))
{
SkipSubBlock(sc);
}
else if (sc.Compare("ifgame"))
{ {
if (!CheckSkipGameBlock(sc)) if (!CheckSkipGameBlock(sc))
{ {
@ -1262,6 +1281,11 @@ void M_CreateMenus()
{ {
I_BuildMIDIMenuList(*opt); I_BuildMIDIMenuList(*opt);
} }
opt = OptionValues.CheckKey(NAME_Aldevices);
if (opt != NULL)
{
I_BuildALDeviceList(*opt);
}
} }
//============================================================================= //=============================================================================

View file

@ -555,6 +555,7 @@ xx(Controlmessage)
xx(Crosshairs) xx(Crosshairs)
xx(Colorpickermenu) xx(Colorpickermenu)
xx(Mididevices) xx(Mididevices)
xx(Aldevices)
xx(CustomizeControls) xx(CustomizeControls)
xx(MessageOptions) xx(MessageOptions)
xx(AutomapOptions) xx(AutomapOptions)

View file

@ -52,29 +52,22 @@ void OPLmusicBlock::Restart()
LastOffset = 0; LastOffset = 0;
} }
OPLmusicFile::OPLmusicFile (FILE *file, BYTE *musiccache, int len) OPLmusicFile::OPLmusicFile (FileReader *reader)
: ScoreLen (len) : ScoreLen (reader->GetLength())
{ {
if (io == NULL) if (io == NULL)
{ {
return; return;
} }
scoredata = new BYTE[len]; scoredata = new BYTE[ScoreLen];
if (file) if (reader->Read(scoredata, ScoreLen) != ScoreLen)
{
if (fread (scoredata, 1, len, file) != (size_t)len)
{ {
fail: delete[] scoredata; fail: delete[] scoredata;
scoredata = NULL; scoredata = NULL;
return; return;
} }
}
else
{
memcpy(scoredata, &musiccache[0], len);
}
if (0 == (NumChips = io->OPLinit(NumChips))) if (0 == (NumChips = io->OPLinit(NumChips)))
{ {
@ -100,7 +93,7 @@ fail: delete[] scoredata;
{ {
RawPlayer = DosBox1; RawPlayer = DosBox1;
SamplesPerTick = OPL_SAMPLE_RATE / 1000; SamplesPerTick = OPL_SAMPLE_RATE / 1000;
ScoreLen = MIN<int>(len - 24, LittleLong(((DWORD *)scoredata)[4])) + 24; ScoreLen = MIN<int>(ScoreLen - 24, LittleLong(((DWORD *)scoredata)[4])) + 24;
} }
else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0)) else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0))
{ {
@ -120,7 +113,7 @@ fail: delete[] scoredata;
RawPlayer = DosBox2; RawPlayer = DosBox2;
SamplesPerTick = OPL_SAMPLE_RATE / 1000; SamplesPerTick = OPL_SAMPLE_RATE / 1000;
int headersize = 0x1A + scoredata[0x19]; int headersize = 0x1A + scoredata[0x19];
ScoreLen = MIN<int>(len - headersize, LittleLong(((DWORD *)scoredata)[3]) * 2) + headersize; ScoreLen = MIN<int>(ScoreLen - headersize, LittleLong(((DWORD *)scoredata)[3]) * 2) + headersize;
} }
else else
{ {

View file

@ -29,7 +29,7 @@ protected:
class OPLmusicFile : public OPLmusicBlock class OPLmusicFile : public OPLmusicBlock
{ {
public: public:
OPLmusicFile(FILE *file, BYTE *musiccache, int len); OPLmusicFile(FileReader *reader);
OPLmusicFile(const OPLmusicFile *source, const char *filename); OPLmusicFile(const OPLmusicFile *source, const char *filename);
virtual ~OPLmusicFile(); virtual ~OPLmusicFile();

View file

@ -4749,7 +4749,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
// [RH] sound sequence overriders // [RH] sound sequence overriders
if (mentry->Type == NULL && mentry->Special == SMT_SSeqOverride) if (mentry->Type == NULL && mentry->Special == SMT_SSeqOverride)
{ {
int type = mentry->Args[0]; int type = mthing->args[0];
if (type == 255) type = -1; if (type == 255) type = -1;
if (type > 63) if (type > 63)
{ {

View file

@ -1366,7 +1366,7 @@ static void S_AddSNDINFO (int lump)
FName nm = sc.String; FName nm = sc.String;
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("timidity")) MidiDevices[nm] = MDEV_TIMIDITY; if (sc.Compare("timidity")) MidiDevices[nm] = MDEV_TIMIDITY;
else if (sc.Compare("fmod")) MidiDevices[nm] = MDEV_FMOD; else if (sc.Compare("fmod") || sc.Compare("sndsys")) MidiDevices[nm] = MDEV_SNDSYS;
else if (sc.Compare("standard")) MidiDevices[nm] = MDEV_MMAPI; else if (sc.Compare("standard")) MidiDevices[nm] = MDEV_MMAPI;
else if (sc.Compare("opl")) MidiDevices[nm] = MDEV_OPL; else if (sc.Compare("opl")) MidiDevices[nm] = MDEV_OPL;
else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT; else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT;

View file

@ -1316,53 +1316,36 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
int size = Wads.LumpLength(sfx->lumpnum); int size = Wads.LumpLength(sfx->lumpnum);
if (size > 0) if (size > 0)
{ {
BYTE *sfxdata;
BYTE *sfxstart;
FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum); FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum);
sfxstart = sfxdata = new BYTE[size]; BYTE *sfxdata = new BYTE[size];
wlump.Read(sfxdata, size); wlump.Read(sfxdata, size);
SDWORD len = LittleLong(((SDWORD *)sfxdata)[1]); SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]);
// If the sound is voc, use the custom loader. // If the sound is voc, use the custom loader.
if (strncmp ((const char *)sfxstart, "Creative Voice File", 19) == 0) if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0)
{ {
sfx->data = GSnd->LoadSoundVoc(sfxstart, size); sfx->data = GSnd->LoadSoundVoc(sfxdata, size);
} }
// If the sound is raw, just load it as such. // If the sound is raw, just load it as such.
else if (sfx->bLoadRAW)
{
sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart);
}
// Otherwise, try the sound as DMX format. // Otherwise, try the sound as DMX format.
// If that fails, let FMOD try and figure it out. else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8)
else if (sfx->bLoadRAW ||
(((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && len <= size - 8))
{ {
int frequency; int frequency = LittleShort(((WORD *)sfxdata)[1]);
if (frequency == 0) frequency = 11025;
if (sfx->bLoadRAW) sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
{
len = Wads.LumpLength (sfx->lumpnum);
frequency = sfx->RawRate;
} }
// If that fails, let the sound system try and figure it out.
else else
{ {
frequency = LittleShort(((WORD *)sfxdata)[1]); sfx->data = GSnd->LoadSound(sfxdata, size);
if (frequency == 0)
{
frequency = 11025;
}
sfxstart = sfxdata + 8;
}
sfx->data = GSnd->LoadSoundRaw(sfxstart, len, frequency, 1, 8, sfx->LoopStart);
}
else
{
len = Wads.LumpLength (sfx->lumpnum);
sfx->data = GSnd->LoadSound(sfxstart, len);
} }
if (sfxdata != NULL)
{
delete[] sfxdata; delete[] sfxdata;
} }
}
if (!sfx->data.isValid()) if (!sfx->data.isValid())
{ {
@ -1930,6 +1913,8 @@ void S_UpdateSounds (AActor *listenactor)
S_ActivatePlayList(false); S_ActivatePlayList(false);
} }
if (listenactor != NULL)
{
// should never happen // should never happen
S_SetListener(listener, listenactor); S_SetListener(listener, listenactor);
@ -1955,6 +1940,7 @@ void S_UpdateSounds (AActor *listenactor)
S_RestoreEvictedChannels(); S_RestoreEvictedChannels();
} }
} }
}
//========================================================================== //==========================================================================
// //
@ -2345,8 +2331,6 @@ bool S_StartMusic (const char *m_id)
// specified, it will only be played if the specified CD is in a drive. // specified, it will only be played if the specified CD is in a drive.
//========================================================================== //==========================================================================
TArray<BYTE> musiccache;
bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
{ {
if (!force && PlayList) if (!force && PlayList)
@ -2426,7 +2410,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
else else
{ {
int lumpnum = -1; int lumpnum = -1;
int offset = 0, length = 0; int length = 0;
int device = MDEV_DEFAULT; int device = MDEV_DEFAULT;
MusInfo *handle = NULL; MusInfo *handle = NULL;
FName musicasname = musicname; FName musicasname = musicname;
@ -2447,6 +2431,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
musicname += 7; musicname += 7;
} }
FileReader *reader = NULL;
if (!FileExists (musicname)) if (!FileExists (musicname))
{ {
if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1) if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1)
@ -2469,33 +2454,21 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
} }
if (handle == NULL) if (handle == NULL)
{ {
if (!Wads.IsUncompressedFile(lumpnum)) if (Wads.LumpLength (lumpnum) == 0)
{
// We must cache the music data and use it from memory.
// shut down old music before reallocating and overwriting the cache!
S_StopMusic (true);
offset = -1; // this tells the low level code that the music
// is being used from memory
length = Wads.LumpLength (lumpnum);
if (length == 0)
{ {
return false; return false;
} }
musiccache.Resize(length); reader = Wads.ReopenLumpNumNewFile(lumpnum);
Wads.ReadLump(lumpnum, &musiccache[0]); if (reader == NULL)
{
return false;
}
}
} }
else else
{ {
offset = Wads.GetLumpOffset (lumpnum); // Load an external file.
length = Wads.LumpLength (lumpnum); reader = new FileReader(musicname);
if (length == 0)
{
return false;
}
}
}
} }
// shutdown old music // shutdown old music
@ -2508,6 +2481,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
mus_playing.name = musicname; mus_playing.name = musicname;
mus_playing.baseorder = order; mus_playing.baseorder = order;
LastSong = musicname; LastSong = musicname;
delete reader;
return true; return true;
} }
@ -2515,16 +2489,11 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
if (handle != NULL) if (handle != NULL)
{ {
mus_playing.handle = handle; mus_playing.handle = handle;
} delete reader;
else if (offset != -1)
{
mus_playing.handle = I_RegisterSong (lumpnum != -1 ?
Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)) :
musicname, NULL, offset, length, device);
} }
else else
{ {
mus_playing.handle = I_RegisterSong (NULL, &musiccache[0], -1, length, device); mus_playing.handle = I_RegisterSong (reader, device);
} }
} }
@ -2622,6 +2591,17 @@ void S_StopMusic (bool force)
} }
} }
//==========================================================================
//
//
//
//==========================================================================
void S_UpdateMusic()
{
GSnd->UpdateMusic();
}
//========================================================================== //==========================================================================
// //
// CCMD playsound // CCMD playsound

View file

@ -329,6 +329,7 @@ int S_GetMusic (char **name);
// Stops the music for sure. // Stops the music for sure.
void S_StopMusic (bool force); void S_StopMusic (bool force);
void S_UpdateMusic();
// Stop and resume music, during game PAUSE. // Stop and resume music, during game PAUSE.
void S_PauseSound (bool notmusic, bool notsfx); void S_PauseSound (bool notmusic, bool notsfx);
@ -389,7 +390,7 @@ enum EMidiDevice
MDEV_DEFAULT = -1, MDEV_DEFAULT = -1,
MDEV_MMAPI = 0, MDEV_MMAPI = 0,
MDEV_OPL = 1, MDEV_OPL = 1,
MDEV_FMOD = 2, MDEV_SNDSYS = 2,
MDEV_TIMIDITY = 3, MDEV_TIMIDITY = 3,
MDEV_FLUIDSYNTH = 4, MDEV_FLUIDSYNTH = 4,
MDEV_GUS = 5, MDEV_GUS = 5,

758
src/sound/efx.h Normal file
View file

@ -0,0 +1,758 @@
#ifndef AL_EFX_H
#define AL_EFX_H
#ifdef __cplusplus
extern "C" {
#endif
#define ALC_EXT_EFX_NAME "ALC_EXT_EFX"
#define ALC_EFX_MAJOR_VERSION 0x20001
#define ALC_EFX_MINOR_VERSION 0x20002
#define ALC_MAX_AUXILIARY_SENDS 0x20003
/* Listener properties. */
#define AL_METERS_PER_UNIT 0x20004
/* Source properties. */
#define AL_DIRECT_FILTER 0x20005
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_AIR_ABSORPTION_FACTOR 0x20007
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
#define AL_CONE_OUTER_GAINHF 0x20009
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
/* Effect properties. */
/* Reverb effect parameters */
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
/* EAX Reverb effect parameters */
#define AL_EAXREVERB_DENSITY 0x0001
#define AL_EAXREVERB_DIFFUSION 0x0002
#define AL_EAXREVERB_GAIN 0x0003
#define AL_EAXREVERB_GAINHF 0x0004
#define AL_EAXREVERB_GAINLF 0x0005
#define AL_EAXREVERB_DECAY_TIME 0x0006
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
#define AL_EAXREVERB_ECHO_TIME 0x000F
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
#define AL_EAXREVERB_MODULATION_TIME 0x0011
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
#define AL_EAXREVERB_HFREFERENCE 0x0014
#define AL_EAXREVERB_LFREFERENCE 0x0015
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
/* Chorus effect parameters */
#define AL_CHORUS_WAVEFORM 0x0001
#define AL_CHORUS_PHASE 0x0002
#define AL_CHORUS_RATE 0x0003
#define AL_CHORUS_DEPTH 0x0004
#define AL_CHORUS_FEEDBACK 0x0005
#define AL_CHORUS_DELAY 0x0006
/* Distortion effect parameters */
#define AL_DISTORTION_EDGE 0x0001
#define AL_DISTORTION_GAIN 0x0002
#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003
#define AL_DISTORTION_EQCENTER 0x0004
#define AL_DISTORTION_EQBANDWIDTH 0x0005
/* Echo effect parameters */
#define AL_ECHO_DELAY 0x0001
#define AL_ECHO_LRDELAY 0x0002
#define AL_ECHO_DAMPING 0x0003
#define AL_ECHO_FEEDBACK 0x0004
#define AL_ECHO_SPREAD 0x0005
/* Flanger effect parameters */
#define AL_FLANGER_WAVEFORM 0x0001
#define AL_FLANGER_PHASE 0x0002
#define AL_FLANGER_RATE 0x0003
#define AL_FLANGER_DEPTH 0x0004
#define AL_FLANGER_FEEDBACK 0x0005
#define AL_FLANGER_DELAY 0x0006
/* Frequency shifter effect parameters */
#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001
#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002
#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003
/* Vocal morpher effect parameters */
#define AL_VOCAL_MORPHER_PHONEMEA 0x0001
#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002
#define AL_VOCAL_MORPHER_PHONEMEB 0x0003
#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004
#define AL_VOCAL_MORPHER_WAVEFORM 0x0005
#define AL_VOCAL_MORPHER_RATE 0x0006
/* Pitchshifter effect parameters */
#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001
#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002
/* Ringmodulator effect parameters */
#define AL_RING_MODULATOR_FREQUENCY 0x0001
#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002
#define AL_RING_MODULATOR_WAVEFORM 0x0003
/* Autowah effect parameters */
#define AL_AUTOWAH_ATTACK_TIME 0x0001
#define AL_AUTOWAH_RELEASE_TIME 0x0002
#define AL_AUTOWAH_RESONANCE 0x0003
#define AL_AUTOWAH_PEAK_GAIN 0x0004
/* Compressor effect parameters */
#define AL_COMPRESSOR_ONOFF 0x0001
/* Equalizer effect parameters */
#define AL_EQUALIZER_LOW_GAIN 0x0001
#define AL_EQUALIZER_LOW_CUTOFF 0x0002
#define AL_EQUALIZER_MID1_GAIN 0x0003
#define AL_EQUALIZER_MID1_CENTER 0x0004
#define AL_EQUALIZER_MID1_WIDTH 0x0005
#define AL_EQUALIZER_MID2_GAIN 0x0006
#define AL_EQUALIZER_MID2_CENTER 0x0007
#define AL_EQUALIZER_MID2_WIDTH 0x0008
#define AL_EQUALIZER_HIGH_GAIN 0x0009
#define AL_EQUALIZER_HIGH_CUTOFF 0x000A
/* Effect type */
#define AL_EFFECT_FIRST_PARAMETER 0x0000
#define AL_EFFECT_LAST_PARAMETER 0x8000
#define AL_EFFECT_TYPE 0x8001
/* Effect types, used with the AL_EFFECT_TYPE property */
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
#define AL_EFFECT_EAXREVERB 0x8000
/* Auxiliary Effect Slot properties. */
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECTSLOT_GAIN 0x0002
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
/* NULL Auxiliary Slot ID to disable a source send. */
#define AL_EFFECTSLOT_NULL 0x0000
/* Filter properties. */
/* Lowpass filter parameters */
#define AL_LOWPASS_GAIN 0x0001
#define AL_LOWPASS_GAINHF 0x0002
/* Highpass filter parameters */
#define AL_HIGHPASS_GAIN 0x0001
#define AL_HIGHPASS_GAINLF 0x0002
/* Bandpass filter parameters */
#define AL_BANDPASS_GAIN 0x0001
#define AL_BANDPASS_GAINLF 0x0002
#define AL_BANDPASS_GAINHF 0x0003
/* Filter type */
#define AL_FILTER_FIRST_PARAMETER 0x0000
#define AL_FILTER_LAST_PARAMETER 0x8000
#define AL_FILTER_TYPE 0x8001
/* Filter types, used with the AL_FILTER_TYPE property */
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
/* Effect object function types. */
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
/* Filter object function types. */
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
/* Auxiliary Effect Slot object function types. */
typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
#endif
/* Filter ranges and defaults. */
/* Lowpass filter */
#define LOWPASS_MIN_GAIN (0.0f)
#define LOWPASS_MAX_GAIN (1.0f)
#define LOWPASS_DEFAULT_GAIN (1.0f)
#define LOWPASS_MIN_GAINHF (0.0f)
#define LOWPASS_MAX_GAINHF (1.0f)
#define LOWPASS_DEFAULT_GAINHF (1.0f)
/* Highpass filter */
#define HIGHPASS_MIN_GAIN (0.0f)
#define HIGHPASS_MAX_GAIN (1.0f)
#define HIGHPASS_DEFAULT_GAIN (1.0f)
#define HIGHPASS_MIN_GAINLF (0.0f)
#define HIGHPASS_MAX_GAINLF (1.0f)
#define HIGHPASS_DEFAULT_GAINLF (1.0f)
/* Bandpass filter */
#define BANDPASS_MIN_GAIN (0.0f)
#define BANDPASS_MAX_GAIN (1.0f)
#define BANDPASS_DEFAULT_GAIN (1.0f)
#define BANDPASS_MIN_GAINHF (0.0f)
#define BANDPASS_MAX_GAINHF (1.0f)
#define BANDPASS_DEFAULT_GAINHF (1.0f)
#define BANDPASS_MIN_GAINLF (0.0f)
#define BANDPASS_MAX_GAINLF (1.0f)
#define BANDPASS_DEFAULT_GAINLF (1.0f)
/* Effect parameter ranges and defaults. */
/* Standard reverb effect */
#define AL_REVERB_MIN_DENSITY (0.0f)
#define AL_REVERB_MAX_DENSITY (1.0f)
#define AL_REVERB_DEFAULT_DENSITY (1.0f)
#define AL_REVERB_MIN_DIFFUSION (0.0f)
#define AL_REVERB_MAX_DIFFUSION (1.0f)
#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
#define AL_REVERB_MIN_GAIN (0.0f)
#define AL_REVERB_MAX_GAIN (1.0f)
#define AL_REVERB_DEFAULT_GAIN (0.32f)
#define AL_REVERB_MIN_GAINHF (0.0f)
#define AL_REVERB_MAX_GAINHF (1.0f)
#define AL_REVERB_DEFAULT_GAINHF (0.89f)
#define AL_REVERB_MIN_DECAY_TIME (0.1f)
#define AL_REVERB_MAX_DECAY_TIME (20.0f)
#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE
#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE
#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
/* EAX reverb effect */
#define AL_EAXREVERB_MIN_DENSITY (0.0f)
#define AL_EAXREVERB_MAX_DENSITY (1.0f)
#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
#define AL_EAXREVERB_MIN_GAIN (0.0f)
#define AL_EAXREVERB_MAX_GAIN (1.0f)
#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
#define AL_EAXREVERB_MIN_GAINHF (0.0f)
#define AL_EAXREVERB_MAX_GAINHF (1.0f)
#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
#define AL_EAXREVERB_MIN_GAINLF (0.0f)
#define AL_EAXREVERB_MAX_GAINLF (1.0f)
#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE
#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE
#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
/* Chorus effect */
#define AL_CHORUS_WAVEFORM_SINUSOID (0)
#define AL_CHORUS_WAVEFORM_TRIANGLE (1)
#define AL_CHORUS_MIN_WAVEFORM (0)
#define AL_CHORUS_MAX_WAVEFORM (1)
#define AL_CHORUS_DEFAULT_WAVEFORM (1)
#define AL_CHORUS_MIN_PHASE (-180)
#define AL_CHORUS_MAX_PHASE (180)
#define AL_CHORUS_DEFAULT_PHASE (90)
#define AL_CHORUS_MIN_RATE (0.0f)
#define AL_CHORUS_MAX_RATE (10.0f)
#define AL_CHORUS_DEFAULT_RATE (1.1f)
#define AL_CHORUS_MIN_DEPTH (0.0f)
#define AL_CHORUS_MAX_DEPTH (1.0f)
#define AL_CHORUS_DEFAULT_DEPTH (0.1f)
#define AL_CHORUS_MIN_FEEDBACK (-1.0f)
#define AL_CHORUS_MAX_FEEDBACK (1.0f)
#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f)
#define AL_CHORUS_MIN_DELAY (0.0f)
#define AL_CHORUS_MAX_DELAY (0.016f)
#define AL_CHORUS_DEFAULT_DELAY (0.016f)
/* Distortion effect */
#define AL_DISTORTION_MIN_EDGE (0.0f)
#define AL_DISTORTION_MAX_EDGE (1.0f)
#define AL_DISTORTION_DEFAULT_EDGE (0.2f)
#define AL_DISTORTION_MIN_GAIN (0.01f)
#define AL_DISTORTION_MAX_GAIN (1.0f)
#define AL_DISTORTION_DEFAULT_GAIN (0.05f)
#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f)
#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f)
#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f)
#define AL_DISTORTION_MIN_EQCENTER (80.0f)
#define AL_DISTORTION_MAX_EQCENTER (24000.0f)
#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f)
#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f)
#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f)
#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f)
/* Echo effect */
#define AL_ECHO_MIN_DELAY (0.0f)
#define AL_ECHO_MAX_DELAY (0.207f)
#define AL_ECHO_DEFAULT_DELAY (0.1f)
#define AL_ECHO_MIN_LRDELAY (0.0f)
#define AL_ECHO_MAX_LRDELAY (0.404f)
#define AL_ECHO_DEFAULT_LRDELAY (0.1f)
#define AL_ECHO_MIN_DAMPING (0.0f)
#define AL_ECHO_MAX_DAMPING (0.99f)
#define AL_ECHO_DEFAULT_DAMPING (0.5f)
#define AL_ECHO_MIN_FEEDBACK (0.0f)
#define AL_ECHO_MAX_FEEDBACK (1.0f)
#define AL_ECHO_DEFAULT_FEEDBACK (0.5f)
#define AL_ECHO_MIN_SPREAD (-1.0f)
#define AL_ECHO_MAX_SPREAD (1.0f)
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
/* Flanger effect */
#define AL_FLANGER_WAVEFORM_SINUSOID (0)
#define AL_FLANGER_WAVEFORM_TRIANGLE (1)
#define AL_FLANGER_MIN_WAVEFORM (0)
#define AL_FLANGER_MAX_WAVEFORM (1)
#define AL_FLANGER_DEFAULT_WAVEFORM (1)
#define AL_FLANGER_MIN_PHASE (-180)
#define AL_FLANGER_MAX_PHASE (180)
#define AL_FLANGER_DEFAULT_PHASE (0)
#define AL_FLANGER_MIN_RATE (0.0f)
#define AL_FLANGER_MAX_RATE (10.0f)
#define AL_FLANGER_DEFAULT_RATE (0.27f)
#define AL_FLANGER_MIN_DEPTH (0.0f)
#define AL_FLANGER_MAX_DEPTH (1.0f)
#define AL_FLANGER_DEFAULT_DEPTH (1.0f)
#define AL_FLANGER_MIN_FEEDBACK (-1.0f)
#define AL_FLANGER_MAX_FEEDBACK (1.0f)
#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f)
#define AL_FLANGER_MIN_DELAY (0.0f)
#define AL_FLANGER_MAX_DELAY (0.004f)
#define AL_FLANGER_DEFAULT_DELAY (0.002f)
/* Frequency shifter effect */
#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f)
#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f)
#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f)
#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2)
#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0)
#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1)
#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2)
#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2)
#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0)
/* Vocal morpher effect */
#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0)
#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0)
#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24)
#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0)
#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0)
#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10)
#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24)
#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0)
#define AL_VOCAL_MORPHER_PHONEME_A (0)
#define AL_VOCAL_MORPHER_PHONEME_E (1)
#define AL_VOCAL_MORPHER_PHONEME_I (2)
#define AL_VOCAL_MORPHER_PHONEME_O (3)
#define AL_VOCAL_MORPHER_PHONEME_U (4)
#define AL_VOCAL_MORPHER_PHONEME_AA (5)
#define AL_VOCAL_MORPHER_PHONEME_AE (6)
#define AL_VOCAL_MORPHER_PHONEME_AH (7)
#define AL_VOCAL_MORPHER_PHONEME_AO (8)
#define AL_VOCAL_MORPHER_PHONEME_EH (9)
#define AL_VOCAL_MORPHER_PHONEME_ER (10)
#define AL_VOCAL_MORPHER_PHONEME_IH (11)
#define AL_VOCAL_MORPHER_PHONEME_IY (12)
#define AL_VOCAL_MORPHER_PHONEME_UH (13)
#define AL_VOCAL_MORPHER_PHONEME_UW (14)
#define AL_VOCAL_MORPHER_PHONEME_B (15)
#define AL_VOCAL_MORPHER_PHONEME_D (16)
#define AL_VOCAL_MORPHER_PHONEME_F (17)
#define AL_VOCAL_MORPHER_PHONEME_G (18)
#define AL_VOCAL_MORPHER_PHONEME_J (19)
#define AL_VOCAL_MORPHER_PHONEME_K (20)
#define AL_VOCAL_MORPHER_PHONEME_L (21)
#define AL_VOCAL_MORPHER_PHONEME_M (22)
#define AL_VOCAL_MORPHER_PHONEME_N (23)
#define AL_VOCAL_MORPHER_PHONEME_P (24)
#define AL_VOCAL_MORPHER_PHONEME_R (25)
#define AL_VOCAL_MORPHER_PHONEME_S (26)
#define AL_VOCAL_MORPHER_PHONEME_T (27)
#define AL_VOCAL_MORPHER_PHONEME_V (28)
#define AL_VOCAL_MORPHER_PHONEME_Z (29)
#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0)
#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1)
#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2)
#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0)
#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2)
#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0)
#define AL_VOCAL_MORPHER_MIN_RATE (0.0f)
#define AL_VOCAL_MORPHER_MAX_RATE (10.0f)
#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f)
/* Pitch shifter effect */
#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12)
#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12)
#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12)
#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50)
#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50)
#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0)
/* Ring modulator effect */
#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f)
#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f)
#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f)
#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f)
#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f)
#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f)
#define AL_RING_MODULATOR_SINUSOID (0)
#define AL_RING_MODULATOR_SAWTOOTH (1)
#define AL_RING_MODULATOR_SQUARE (2)
#define AL_RING_MODULATOR_MIN_WAVEFORM (0)
#define AL_RING_MODULATOR_MAX_WAVEFORM (2)
#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0)
/* Autowah effect */
#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f)
#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f)
#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f)
#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f)
#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f)
#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f)
#define AL_AUTOWAH_MIN_RESONANCE (2.0f)
#define AL_AUTOWAH_MAX_RESONANCE (1000.0f)
#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f)
#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f)
#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f)
#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f)
/* Compressor effect */
#define AL_COMPRESSOR_MIN_ONOFF (0)
#define AL_COMPRESSOR_MAX_ONOFF (1)
#define AL_COMPRESSOR_DEFAULT_ONOFF (1)
/* Equalizer effect */
#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f)
#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f)
#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f)
#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f)
#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f)
#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f)
#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f)
#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f)
#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f)
#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f)
#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f)
#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f)
#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f)
#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f)
#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f)
#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f)
#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f)
#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f)
#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f)
#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f)
#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f)
#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f)
#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f)
#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f)
#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f)
#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f)
/* Source parameter value ranges and defaults. */
#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f)
#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f)
#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f)
#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_MIN_CONE_OUTER_GAINHF (0.0f)
#define AL_MAX_CONE_OUTER_GAINHF (1.0f)
#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f)
#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE
#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE
#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE
#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
/* Listener parameter value ranges and defaults. */
#define AL_MIN_METERS_PER_UNIT FLT_MIN
#define AL_MAX_METERS_PER_UNIT FLT_MAX
#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* AL_EFX_H */

34
src/sound/except.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __EXCEPT_H
#define __EXCEPT_H
#ifdef _MSC_VER
//==========================================================================
//
// CheckException
//
//==========================================================================
#ifndef FACILITY_VISUALCPP
#define FACILITY_VISUALCPP ((LONG)0x6d)
#endif
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
inline int CheckException(DWORD code)
{
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
{
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#else
#define __try
#define __except(a) if (0)
#endif
#endif

View file

@ -2,6 +2,8 @@
#ifndef FMOD_WRAP_H #ifndef FMOD_WRAP_H
#define FMOD_WRAP_H #define FMOD_WRAP_H
#ifndef NO_FMOD
#if !defined(_WIN32) || defined(_MSC_VER) #if !defined(_WIN32) || defined(_MSC_VER)
// Use the real C++ interface if it's supported on this platform. // Use the real C++ interface if it's supported on this platform.
#include "fmod.hpp" #include "fmod.hpp"
@ -610,3 +612,4 @@ namespace FMOD
#endif #endif
#endif #endif
#endif

View file

@ -52,6 +52,7 @@ extern HWND Window;
#include <malloc.h> #include <malloc.h>
#endif #endif
#include "except.h"
#include "templates.h" #include "templates.h"
#include "fmodsound.h" #include "fmodsound.h"
#include "c_cvars.h" #include "c_cvars.h"
@ -62,6 +63,7 @@ extern HWND Window;
#include "v_palette.h" #include "v_palette.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "s_sound.h" #include "s_sound.h"
#include "files.h"
#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43400 #if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43400
#error You are trying to compile with an unsupported version of FMOD. #error You are trying to compile with an unsupported version of FMOD.
@ -79,6 +81,35 @@ extern HWND Window;
#define SPECTRUM_SIZE 256 #define SPECTRUM_SIZE 256
// PUBLIC DATA DEFINITIONS -------------------------------------------------
ReverbContainer *ForcedEnvironment;
CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, snd_buffercount, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_hrtf, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_profile, false, 0)
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
// Clamp to the DSP unit's limits.
if (*self < 10 && *self != 0)
{
self = 10;
}
else if (*self > 22000)
{
self = 22000;
}
}
#ifndef NO_FMOD
#if FMOD_VERSION < 0x43400 #if FMOD_VERSION < 0x43400
#define FMOD_OPENSTATE_PLAYING FMOD_OPENSTATE_STREAMING #define FMOD_OPENSTATE_PLAYING FMOD_OPENSTATE_STREAMING
#endif #endif
@ -112,34 +143,6 @@ EXTERN_CVAR (Int, snd_channels)
extern int sfx_empty; extern int sfx_empty;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
ReverbContainer *ForcedEnvironment;
CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, snd_buffercount, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_hrtf, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_profile, false, 0)
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
// Clamp to the DSP unit's limits.
if (*self < 10 && *self != 0)
{
self = 10;
}
else if (*self > 22000)
{
self = 22000;
}
}
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static const ReverbContainer *PrevEnvironment; static const ReverbContainer *PrevEnvironment;
@ -301,14 +304,21 @@ class FMODStreamCapsule : public SoundStream
public: public:
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, const char *url) FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, const char *url)
: Owner(owner), Stream(NULL), Channel(NULL), : Owner(owner), Stream(NULL), Channel(NULL),
UserData(NULL), Callback(NULL), URL(url), Ended(false) UserData(NULL), Callback(NULL), URL(url), Reader(NULL), Ended(false)
{
SetStream(stream);
}
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, FileReader *reader)
: Owner(owner), Stream(NULL), Channel(NULL),
UserData(NULL), Callback(NULL), Reader(reader), Ended(false)
{ {
SetStream(stream); SetStream(stream);
} }
FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner) FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner)
: Owner(owner), Stream(NULL), Channel(NULL), : Owner(owner), Stream(NULL), Channel(NULL),
UserData(udata), Callback(callback), Ended(false) UserData(udata), Callback(callback), Reader(NULL), Ended(false)
{} {}
~FMODStreamCapsule() ~FMODStreamCapsule()
@ -321,6 +331,10 @@ public:
{ {
Stream->release(); Stream->release();
} }
if (Reader != NULL)
{
delete Reader;
}
} }
void SetStream(FMOD::Sound *stream) void SetStream(FMOD::Sound *stream)
@ -590,6 +604,7 @@ private:
FMOD::Channel *Channel; FMOD::Channel *Channel;
void *UserData; void *UserData;
SoundStreamCallback Callback; SoundStreamCallback Callback;
FileReader *Reader;
FString URL; FString URL;
bool Ended; bool Ended;
bool JustStarted; bool JustStarted;
@ -619,30 +634,6 @@ bool FMODSoundRenderer::IsValid()
return InitSuccess; return InitSuccess;
} }
#ifdef _MSC_VER
//==========================================================================
//
// CheckException
//
//==========================================================================
#ifndef FACILITY_VISUALCPP
#define FACILITY_VISUALCPP ((LONG)0x6d)
#endif
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
static int CheckException(DWORD code)
{
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
{
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
//========================================================================== //==========================================================================
// //
// FMODSoundRenderer :: Init // FMODSoundRenderer :: Init
@ -680,14 +671,8 @@ bool FMODSoundRenderer::Init()
Printf("I_InitSound: Initializing FMOD\n"); Printf("I_InitSound: Initializing FMOD\n");
// Create a System object and initialize. // This is just for safety. Normally this should never be called if FMod Ex cannot be found.
#ifdef _MSC_VER if (!IsFModExPresent())
__try {
#endif
result = FMOD::System_Create(&Sys);
#ifdef _MSC_VER
}
__except(CheckException(GetExceptionCode()))
{ {
Sys = NULL; Sys = NULL;
Printf(TEXTCOLOR_ORANGE"Failed to load fmodex" Printf(TEXTCOLOR_ORANGE"Failed to load fmodex"
@ -697,7 +682,9 @@ bool FMODSoundRenderer::Init()
".dll\n"); ".dll\n");
return false; return false;
} }
#endif
// Create a System object and initialize.
result = FMOD::System_Create(&Sys);
if (result != FMOD_OK) if (result != FMOD_OK)
{ {
Sys = NULL; Sys = NULL;
@ -1604,34 +1591,79 @@ static void SetCustomLoopPts(FMOD::Sound *sound)
//========================================================================== //==========================================================================
// //
// FMODSoundRenderer :: OpenStream // open_reader_callback
// close_reader_callback
// read_reader_callback
// seek_reader_callback
// //
// Creates a streaming sound from a file on disk. // FMOD_CREATESOUNDEXINFO callbacks to handle reading resource data from a
// FileReader.
// //
//========================================================================== //==========================================================================
SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int flags, int offset, int length) static FMOD_RESULT F_CALLBACK open_reader_callback(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata)
{
FileReader *reader = NULL;
if(sscanf(name, "_FileReader_%p", &reader) != 1)
{
Printf("Invalid name in callback: %s\n", name);
return FMOD_ERR_FILE_NOTFOUND;
}
*filesize = reader->GetLength();
*handle = reader;
*userdata = reader;
return FMOD_OK;
}
static FMOD_RESULT F_CALLBACK close_reader_callback(void *handle, void *userdata)
{
return FMOD_OK;
}
static FMOD_RESULT F_CALLBACK read_reader_callback(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata)
{
FileReader *reader = reinterpret_cast<FileReader*>(handle);
*bytesread = reader->Read(buffer, sizebytes);
if(*bytesread > 0) return FMOD_OK;
return FMOD_ERR_FILE_EOF;
}
static FMOD_RESULT F_CALLBACK seek_reader_callback(void *handle, unsigned int pos, void *userdata)
{
FileReader *reader = reinterpret_cast<FileReader*>(handle);
if(reader->Seek(pos, SEEK_SET) == 0)
return FMOD_OK;
return FMOD_ERR_FILE_COULDNOTSEEK;
}
//==========================================================================
//
// FMODSoundRenderer :: OpenStream
//
// Creates a streaming sound from a FileReader.
//
//==========================================================================
SoundStream *FMODSoundRenderer::OpenStream(FileReader *reader, int flags)
{ {
FMOD_MODE mode; FMOD_MODE mode;
FMOD_CREATESOUNDEXINFO exinfo; FMOD_CREATESOUNDEXINFO exinfo;
FMOD::Sound *stream; FMOD::Sound *stream;
FMOD_RESULT result; FMOD_RESULT result;
bool url;
FString patches; FString patches;
FString name;
InitCreateSoundExInfo(&exinfo); InitCreateSoundExInfo(&exinfo);
exinfo.useropen = open_reader_callback;
exinfo.userclose = close_reader_callback;
exinfo.userread = read_reader_callback;
exinfo.userseek = seek_reader_callback;
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM; mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
if(flags & SoundStream::Loop) if(flags & SoundStream::Loop)
{
mode |= FMOD_LOOP_NORMAL; mode |= FMOD_LOOP_NORMAL;
}
if (offset == -1)
{
mode |= FMOD_OPENMEMORY;
offset = 0;
}
exinfo.length = length;
exinfo.fileoffset = offset;
if((*snd_midipatchset)[0] != '\0') if((*snd_midipatchset)[0] != '\0')
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -1650,37 +1682,80 @@ SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int fla
exinfo.dlsname = patches; exinfo.dlsname = patches;
} }
url = (offset == 0 && length == 0 && strstr(filename_or_data, "://") > filename_or_data); name.Format("_FileReader_%p", reader);
if (url) result = Sys->createSound(name, mode, &exinfo, &stream);
{
// Use a larger buffer for URLs so that it's less likely to be effected
// by hiccups in the data rate from the remote server.
Sys->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
}
result = Sys->createSound(filename_or_data, mode, &exinfo, &stream);
if (url)
{
// Restore standard buffer size.
Sys->setStreamBufferSize(16*1024, FMOD_TIMEUNIT_RAWBYTES);
}
if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL) if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL)
{ {
// FMOD_ERR_FORMAT could refer to either the main sound file or // FMOD_ERR_FORMAT could refer to either the main sound file or
// to the DLS instrument set. Try again without special DLS // to the DLS instrument set. Try again without special DLS
// instruments to see if that lets it succeed. // instruments to see if that lets it succeed.
exinfo.dlsname = NULL; exinfo.dlsname = NULL;
result = Sys->createSound(filename_or_data, mode, &exinfo, &stream); result = Sys->createSound(name, mode, &exinfo, &stream);
if (result == FMOD_OK) if (result == FMOD_OK)
{ {
Printf("%s is an unsupported format.\n", *snd_midipatchset); Printf("%s is an unsupported format.\n", *snd_midipatchset);
} }
} }
if(result != FMOD_OK)
return NULL;
SetCustomLoopPts(stream);
return new FMODStreamCapsule(stream, this, reader);
}
SoundStream *FMODSoundRenderer::OpenStream(const char *url, int flags)
{
FMOD_MODE mode;
FMOD_CREATESOUNDEXINFO exinfo;
FMOD::Sound *stream;
FMOD_RESULT result;
FString patches;
InitCreateSoundExInfo(&exinfo);
mode = FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM;
if(flags & SoundStream::Loop)
mode |= FMOD_LOOP_NORMAL;
if((*snd_midipatchset)[0] != '\0')
{
#ifdef _WIN32
// If the path does not contain any path separators, automatically
// prepend $PROGDIR to the path.
if (strcspn(snd_midipatchset, ":/\\") == strlen(snd_midipatchset))
{
patches << "$PROGDIR/" << snd_midipatchset;
patches = NicePath(patches);
}
else
#endif
{
patches = NicePath(snd_midipatchset);
}
exinfo.dlsname = patches;
}
// Use a larger buffer for URLs so that it's less likely to be effected
// by hiccups in the data rate from the remote server.
Sys->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
result = Sys->createSound(url, mode, &exinfo, &stream);
if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL)
{
exinfo.dlsname = NULL;
result = Sys->createSound(url, mode, &exinfo, &stream);
if(result == FMOD_OK) if(result == FMOD_OK)
{ {
SetCustomLoopPts(stream); Printf("%s is an unsupported format.\n", *snd_midipatchset);
return new FMODStreamCapsule(stream, this, url ? filename_or_data : NULL);
} }
}
// Restore standard buffer size.
Sys->setStreamBufferSize(16*1024, FMOD_TIMEUNIT_RAWBYTES);
if(result != FMOD_OK)
return NULL; return NULL;
SetCustomLoopPts(stream);
return new FMODStreamCapsule(stream, this, url);
} }
//========================================================================== //==========================================================================
@ -3098,3 +3173,45 @@ FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES
#endif #endif
} }
#endif // NO_FMOD
//==========================================================================
//
// IsFModExPresent
//
// Check if FMod can be used
//
//==========================================================================
bool IsFModExPresent()
{
#ifdef NO_FMOD
return false;
#elif !defined _WIN32
return true; // on non-Windows we cannot delay load the library so it has to be present.
#else
static bool cached_result;
static bool done = false;
if (!done)
{
done = true;
FMOD::System *Sys;
FMOD_RESULT result;
__try
{
result = FMOD::System_Create(&Sys);
}
__except (CheckException(GetExceptionCode()))
{
// FMod could not be delay loaded
return false;
}
if (result == FMOD_OK) Sys->release();
cached_result = true;
}
return cached_result;
#endif
}

View file

@ -2,6 +2,8 @@
#define FMODSOUND_H #define FMODSOUND_H
#include "i_sound.h" #include "i_sound.h"
#ifndef NO_FMOD
#include "fmod_wrap.h" #include "fmod_wrap.h"
class FMODSoundRenderer : public SoundRenderer class FMODSoundRenderer : public SoundRenderer
@ -22,9 +24,8 @@ public:
// Streaming sounds. // Streaming sounds.
SoundStream *CreateStream (SoundStreamCallback callback, int buffsamples, int flags, int samplerate, void *userdata); SoundStream *CreateStream (SoundStreamCallback callback, int buffsamples, int flags, int samplerate, void *userdata);
SoundStream *OpenStream (const char *filename, int flags, int offset, int length); SoundStream *OpenStream (FileReader *reader, int flags);
long PlayStream (SoundStream *stream, int volume); SoundStream *OpenStream (const char *url, int flags);
void StopStream (SoundStream *stream);
// Starts a sound. // Starts a sound.
FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan); FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan);
@ -126,3 +127,4 @@ private:
}; };
#endif #endif
#endif

View file

@ -99,7 +99,7 @@ EXTERN_CVAR (Int, snd_mididevice)
static bool MusicDown = true; static bool MusicDown = true;
static BYTE *ungzip(BYTE *data, int *size); static bool ungzip(BYTE *data, int size, TArray<BYTE> &newdata);
MusInfo *currSong; MusInfo *currSong;
int nomusic = 0; int nomusic = 0;
@ -301,21 +301,21 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
// //
//========================================================================== //==========================================================================
static MIDIStreamer *CreateMIDIStreamer(FILE *file, BYTE *musiccache, int len, EMidiDevice devtype, EMIDIType miditype) static MIDIStreamer *CreateMIDIStreamer(FileReader &reader, EMidiDevice devtype, EMIDIType miditype)
{ {
switch (miditype) switch (miditype)
{ {
case MIDI_MUS: case MIDI_MUS:
return new MUSSong2(file, musiccache, len, devtype); return new MUSSong2(reader, devtype);
case MIDI_MIDI: case MIDI_MIDI:
return new MIDISong2(file, musiccache, len, devtype); return new MIDISong2(reader, devtype);
case MIDI_HMI: case MIDI_HMI:
return new HMISong(file, musiccache, len, devtype); return new HMISong(reader, devtype);
case MIDI_XMI: case MIDI_XMI:
return new XMISong(file, musiccache, len, devtype); return new XMISong(reader, devtype);
default: default:
return NULL; return NULL;
@ -377,100 +377,61 @@ static EMIDIType IdentifyMIDIType(DWORD *id, int size)
// //
//========================================================================== //==========================================================================
MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int len, int device) MusInfo *I_RegisterSong (FileReader *reader, int device)
{ {
FILE *file;
MusInfo *info = NULL; MusInfo *info = NULL;
const char *fmt; const char *fmt;
DWORD id[32/4]; DWORD id[32/4];
BYTE *ungzipped;
int i;
if (nomusic) if (nomusic)
{ {
delete reader;
return 0; return 0;
} }
if (offset != -1) if(reader->Read(id, 32) != 32 || reader->Seek(-32, SEEK_CUR) != 0)
{
file = fopen (filename, "rb");
if (file == NULL)
{ {
delete reader;
return 0; return 0;
} }
if (len == 0 && offset == 0)
{
fseek (file, 0, SEEK_END);
len = ftell (file);
fseek (file, 0, SEEK_SET);
}
else
{
fseek (file, offset, SEEK_SET);
}
if (len < 32)
{
return 0;
}
if (fread (id, 4, 32/4, file) != 32/4)
{
fclose (file);
return 0;
}
fseek (file, -32, SEEK_CUR);
}
else
{
file = NULL;
if (len < 32)
{
return 0;
}
for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
}
}
#ifndef _WIN32 #ifndef _WIN32
// non-Windows platforms don't support MDEV_MMAPI so map to MDEV_FMOD // non-Windows platforms don't support MDEV_MMAPI so map to MDEV_SNDSYS
if (device == MDEV_MMAPI) if (device == MDEV_MMAPI)
device = MDEV_FMOD; device = MDEV_SNDSYS;
#endif #endif
// Check for gzip compression. Some formats are expected to have players // Check for gzip compression. Some formats are expected to have players
// that can handle it, so it simplifies things if we make all songs // that can handle it, so it simplifies things if we make all songs
// gzippable. // gzippable.
ungzipped = NULL;
if ((id[0] & MAKE_ID(255, 255, 255, 0)) == GZIP_ID) if ((id[0] & MAKE_ID(255, 255, 255, 0)) == GZIP_ID)
{ {
if (offset != -1) int len = reader->GetLength();
{
BYTE *gzipped = new BYTE[len]; BYTE *gzipped = new BYTE[len];
if (fread(gzipped, 1, len, file) != (size_t)len) if (reader->Read(gzipped, len) != len)
{ {
delete[] gzipped; delete[] gzipped;
fclose(file); delete reader;
return NULL; return NULL;
} }
ungzipped = ungzip(gzipped, &len); delete reader;
MemoryArrayReader *memreader = new MemoryArrayReader(NULL, 0);
if (!ungzip(gzipped, len, memreader->GetArray()))
{
delete[] gzipped; delete[] gzipped;
delete memreader;
return 0;
} }
else delete[] gzipped;
memreader->UpdateLength();
if (memreader->Read(id, 32) != 32 || memreader->Seek(-32, SEEK_CUR) != 0)
{ {
ungzipped = ungzip(musiccache, &len); delete memreader;
} return 0;
if (ungzipped == NULL)
{
fclose(file);
return NULL;
}
musiccache = ungzipped;
for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
} }
reader = memreader;
} }
EMIDIType miditype = IdentifyMIDIType(id, sizeof(id)); EMIDIType miditype = IdentifyMIDIType(id, sizeof(id));
@ -478,22 +439,22 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{ {
EMidiDevice devtype = (EMidiDevice)device; EMidiDevice devtype = (EMidiDevice)device;
retry_as_fmod: retry_as_sndsys:
info = CreateMIDIStreamer(file, musiccache, len, devtype, miditype); info = CreateMIDIStreamer(*reader, devtype, miditype);
if (info != NULL && !info->IsValid()) if (info != NULL && !info->IsValid())
{ {
delete info; delete info;
info = NULL; info = NULL;
} }
if (info == NULL && devtype != MDEV_FMOD && snd_mididevice < 0) if (info == NULL && devtype != MDEV_SNDSYS && snd_mididevice < 0)
{ {
devtype = MDEV_FMOD; devtype = MDEV_SNDSYS;
goto retry_as_fmod; goto retry_as_sndsys;
} }
#ifdef _WIN32 #ifdef _WIN32
if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0) if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0)
{ {
info = CreateMIDIStreamer(file, musiccache, len, MDEV_MMAPI, miditype); info = CreateMIDIStreamer(*reader, MDEV_MMAPI, miditype);
} }
#endif #endif
} }
@ -504,74 +465,62 @@ retry_as_fmod:
(id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL (id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
(id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF (id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF
{ {
info = new OPLMUSSong (file, musiccache, len); info = new OPLMUSSong (*reader);
} }
// Check for game music // Check for game music
else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0') else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0')
{ {
info = GME_OpenSong(file, musiccache, len, fmt); info = GME_OpenSong(*reader, fmt);
} }
// Check for module formats // Check for module formats
else else
{ {
info = MOD_OpenSong(file, musiccache, len); info = MOD_OpenSong(*reader);
} }
if (info == NULL) if (info == NULL)
{ {
// Check for CDDA "format" // Check for CDDA "format"
if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24))) if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
{
if (file != NULL)
{ {
DWORD subid; DWORD subid;
fseek (file, 8, SEEK_CUR); reader->Seek(8, SEEK_CUR);
if (fread (&subid, 4, 1, file) != 1) if (reader->Read (&subid, 4) != 4)
{ {
fclose (file); delete reader;
return 0; return 0;
} }
fseek (file, -12, SEEK_CUR); reader->Seek(-12, SEEK_CUR);
if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24))) if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24)))
{ {
// This is a CDDA file // This is a CDDA file
info = new CDDAFile (file, len); info = new CDDAFile (*reader);
}
} }
} }
// no FMOD => no modules/streams // no support in sound system => no modules/streams
// 1024 bytes is an arbitrary restriction. It's assumed that anything // 1024 bytes is an arbitrary restriction. It's assumed that anything
// smaller than this can't possibly be a valid music file if it hasn't // smaller than this can't possibly be a valid music file if it hasn't
// been identified already, so don't even bother trying to load it. // been identified already, so don't even bother trying to load it.
// Of course MIDIs shorter than 1024 bytes should pass. // Of course MIDIs shorter than 1024 bytes should pass.
if (info == NULL && (len >= 1024 || id[0] == MAKE_ID('M','T','h','d'))) if (info == NULL && (reader->GetLength() >= 1024 || id[0] == MAKE_ID('M','T','h','d')))
{ {
// Let FMOD figure out what it is. // Let the sound system figure out what it is.
if (file != NULL) info = new StreamSong (reader);
{ // Assumed ownership
fclose (file); reader = NULL;
file = NULL;
}
info = new StreamSong (offset >= 0 ? filename : (const char *)musiccache, offset, len);
} }
} }
if (reader != NULL) delete reader;
if (info && !info->IsValid ()) if (info && !info->IsValid ())
{ {
delete info; delete info;
info = NULL; info = NULL;
} }
if (file != NULL)
{
fclose (file);
}
if (ungzipped != NULL)
{
delete[] ungzipped;
}
return info; return info;
} }
@ -605,7 +554,7 @@ MusInfo *I_RegisterURLSong (const char *url)
{ {
StreamSong *song; StreamSong *song;
song = new StreamSong(url, 0, 0); song = new StreamSong(url);
if (song->IsValid()) if (song->IsValid())
{ {
return song; return song;
@ -623,13 +572,12 @@ MusInfo *I_RegisterURLSong (const char *url)
// //
//========================================================================== //==========================================================================
BYTE *ungzip(BYTE *data, int *complen) static bool ungzip(BYTE *data, int complen, TArray<BYTE> &newdata)
{ {
const BYTE *max = data + *complen - 8; const BYTE *max = data + complen - 8;
const BYTE *compstart = data + 10; const BYTE *compstart = data + 10;
BYTE flags = data[3]; BYTE flags = data[3];
unsigned isize; unsigned isize;
BYTE *newdata;
z_stream stream; z_stream stream;
int err; int err;
@ -658,16 +606,16 @@ BYTE *ungzip(BYTE *data, int *complen)
} }
if (compstart >= max - 1) if (compstart >= max - 1)
{ {
return NULL; return false;
} }
// Decompress // Decompress
isize = LittleLong(*(DWORD *)(data + *complen - 4)); isize = LittleLong(*(DWORD *)(data + complen - 4));
newdata = new BYTE[isize]; newdata.Resize(isize);
stream.next_in = (Bytef *)compstart; stream.next_in = (Bytef *)compstart;
stream.avail_in = (uInt)(max - compstart); stream.avail_in = (uInt)(max - compstart);
stream.next_out = newdata; stream.next_out = &newdata[0];
stream.avail_out = isize; stream.avail_out = isize;
stream.zalloc = (alloc_func)0; stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0; stream.zfree = (free_func)0;
@ -675,25 +623,20 @@ BYTE *ungzip(BYTE *data, int *complen)
err = inflateInit2(&stream, -MAX_WBITS); err = inflateInit2(&stream, -MAX_WBITS);
if (err != Z_OK) if (err != Z_OK)
{ {
delete[] newdata; return false;
return NULL;
} }
err = inflate(&stream, Z_FINISH); err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) if (err != Z_STREAM_END)
{ {
inflateEnd(&stream); inflateEnd(&stream);
delete[] newdata; return false;
return NULL;
} }
err = inflateEnd(&stream); err = inflateEnd(&stream);
if (err != Z_OK) if (err != Z_OK)
{ {
delete[] newdata; return false;
return NULL;
} }
*complen = isize; return true;
return newdata;
} }
//========================================================================== //==========================================================================

View file

@ -52,7 +52,7 @@ void I_SetMusicVolume (float volume);
// Registers a song handle to song data. // Registers a song handle to song data.
class MusInfo; class MusInfo;
MusInfo *I_RegisterSong (const char *file, BYTE *musiccache, int offset, int length, int device); MusInfo *I_RegisterSong (FileReader *reader, int device);
MusInfo *I_RegisterCDSong (int track, int cdid = 0); MusInfo *I_RegisterCDSong (int track, int cdid = 0);
MusInfo *I_RegisterURLSong (const char *url); MusInfo *I_RegisterURLSong (const char *url);

View file

@ -23,6 +23,7 @@
#include "i_sound.h" #include "i_sound.h"
#include "i_music.h" #include "i_music.h"
#include "s_sound.h" #include "s_sound.h"
#include "files.h"
void I_InitMusicWin32 (); void I_InitMusicWin32 ();
void I_ShutdownMusicWin32 (); void I_ShutdownMusicWin32 ();
@ -168,16 +169,16 @@ protected:
bool bLooping; bool bLooping;
}; };
// FMOD pseudo-MIDI device -------------------------------------------------- // Sound System pseudo-MIDI device ------------------------------------------
class FMODMIDIDevice : public PseudoMIDIDevice class SndSysMIDIDevice : public PseudoMIDIDevice
{ {
public: public:
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata); int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
bool Preprocess(MIDIStreamer *song, bool looping); bool Preprocess(MIDIStreamer *song, bool looping);
}; };
// MIDI file played with TiMidity++ and possibly streamed through FMOD ------ // MIDI file played with TiMidity++ and possibly streamed through the Sound System
class TimidityPPMIDIDevice : public PseudoMIDIDevice class TimidityPPMIDIDevice : public PseudoMIDIDevice
{ {
@ -500,7 +501,7 @@ protected:
class MUSSong2 : public MIDIStreamer class MUSSong2 : public MIDIStreamer
{ {
public: public:
MUSSong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type); MUSSong2(FileReader &reader, EMidiDevice type);
~MUSSong2(); ~MUSSong2();
MusInfo *GetOPLDumper(const char *filename); MusInfo *GetOPLDumper(const char *filename);
@ -526,7 +527,7 @@ protected:
class MIDISong2 : public MIDIStreamer class MIDISong2 : public MIDIStreamer
{ {
public: public:
MIDISong2(FILE *file, BYTE *musiccache, int length, EMidiDevice type); MIDISong2(FileReader &reader, EMidiDevice type);
~MIDISong2(); ~MIDISong2();
MusInfo *GetOPLDumper(const char *filename); MusInfo *GetOPLDumper(const char *filename);
@ -583,7 +584,7 @@ protected:
class HMISong : public MIDIStreamer class HMISong : public MIDIStreamer
{ {
public: public:
HMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type); HMISong(FileReader &reader, EMidiDevice type);
~HMISong(); ~HMISong();
MusInfo *GetOPLDumper(const char *filename); MusInfo *GetOPLDumper(const char *filename);
@ -626,7 +627,7 @@ protected:
class XMISong : public MIDIStreamer class XMISong : public MIDIStreamer
{ {
public: public:
XMISong(FILE *file, BYTE *musiccache, int length, EMidiDevice type); XMISong(FileReader &reader, EMidiDevice type);
~XMISong(); ~XMISong();
MusInfo *GetOPLDumper(const char *filename); MusInfo *GetOPLDumper(const char *filename);
@ -660,12 +661,13 @@ protected:
EventSource EventDue; EventSource EventDue;
}; };
// Anything supported by FMOD out of the box -------------------------------- // Anything supported by the sound system out of the box --------------------
class StreamSong : public MusInfo class StreamSong : public MusInfo
{ {
public: public:
StreamSong (const char *file, int offset, int length); StreamSong (FileReader *reader);
StreamSong (const char *url);
~StreamSong (); ~StreamSong ();
void Play (bool looping, int subsong); void Play (bool looping, int subsong);
void Pause (); void Pause ();
@ -683,12 +685,12 @@ protected:
SoundStream *m_Stream; SoundStream *m_Stream;
}; };
// MUS file played by a software OPL2 synth and streamed through FMOD ------- // MUS file played by a software OPL2 synth and streamed through the sound system
class OPLMUSSong : public StreamSong class OPLMUSSong : public StreamSong
{ {
public: public:
OPLMUSSong (FILE *file, BYTE *musiccache, int length); OPLMUSSong (FileReader &reader);
~OPLMUSSong (); ~OPLMUSSong ();
void Play (bool looping, int subsong); void Play (bool looping, int subsong);
bool IsPlaying (); bool IsPlaying ();
@ -737,17 +739,17 @@ protected:
class CDDAFile : public CDSong class CDDAFile : public CDSong
{ {
public: public:
CDDAFile (FILE *file, int length); CDDAFile (FileReader &reader);
}; };
// Module played via foo_dumb ----------------------------------------------- // Module played via foo_dumb -----------------------------------------------
MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int len); MusInfo *MOD_OpenSong(FileReader &reader);
// Music played via Game Music Emu ------------------------------------------ // Music played via Game Music Emu ------------------------------------------
const char *GME_CheckFormat(uint32 header); const char *GME_CheckFormat(uint32 header);
MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt); MusInfo *GME_OpenSong(FileReader &reader, const char *fmt);
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------

View file

@ -52,7 +52,12 @@ extern HINSTANCE g_hInst;
#include "doomtype.h" #include "doomtype.h"
#include <math.h> #include <math.h>
#include "except.h"
#include "fmodsound.h" #include "fmodsound.h"
#include "oalsound.h"
#include "mpg123_decoder.h"
#include "sndfile_decoder.h"
#include "m_swap.h" #include "m_swap.h"
#include "stats.h" #include "stats.h"
@ -77,6 +82,16 @@ CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#ifndef NO_FMOD
#define DEF_BACKEND "fmod"
#elif !defined(NO_OPENAL)
#define DEF_BACKEND "openal"
#else
#define DEF_BACKEND "null"
#endif
CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// killough 2/21/98: optionally use varying pitched sounds // killough 2/21/98: optionally use varying pitched sounds
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE) CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
@ -159,8 +174,9 @@ public:
{ {
return NULL; return NULL;
} }
SoundStream *OpenStream (const char *filename, int flags, int offset, int length) SoundStream *OpenStream (FileReader *reader, int flags)
{ {
delete reader;
return NULL; return NULL;
} }
@ -242,6 +258,7 @@ void I_InitSound ()
nosound = !!Args->CheckParm ("-nosound"); nosound = !!Args->CheckParm ("-nosound");
nosfx = !!Args->CheckParm ("-nosfx"); nosfx = !!Args->CheckParm ("-nosfx");
GSnd = NULL;
if (nosound) if (nosound)
{ {
GSnd = new NullSoundRenderer; GSnd = new NullSoundRenderer;
@ -249,9 +266,51 @@ void I_InitSound ()
return; return;
} }
// This has been extended to allow falling back from FMod to OpenAL and vice versa if the currently active sound system cannot be found.
if (stricmp(snd_backend, "null") == 0)
{
GSnd = new NullSoundRenderer;
}
else if(stricmp(snd_backend, "fmod") == 0)
{
#ifndef NO_FMOD
if (IsFModExPresent())
{
GSnd = new FMODSoundRenderer; GSnd = new FMODSoundRenderer;
}
if (!GSnd->IsValid ()) #endif
#ifndef NO_OPENAL
if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent())
{
Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n");
GSnd = new OpenALSoundRenderer;
snd_backend = "openal";
}
#endif
}
else if(stricmp(snd_backend, "openal") == 0)
{
#ifndef NO_OPENAL
if (IsOpenALPresent())
{
GSnd = new OpenALSoundRenderer;
}
#endif
#ifndef NO_FMOD
if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent())
{
Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n");
GSnd = new FMODSoundRenderer;
snd_backend = "fmod";
}
#endif
}
else
{
Printf (TEXTCOLOR_RED"%s: Unknown sound system specified\n", *snd_backend);
snd_backend = "null";
}
if (!GSnd || !GSnd->IsValid ())
{ {
I_CloseSound(); I_CloseSound();
GSnd = new NullSoundRenderer; GSnd = new NullSoundRenderer;
@ -283,6 +342,27 @@ void I_ShutdownSound()
} }
} }
const char *GetSampleTypeName(enum SampleType type)
{
switch(type)
{
case SampleType_UInt8: return "Unsigned 8-bit";
case SampleType_Int16: return "Signed 16-bit";
}
return "(invalid sample type)";
}
const char *GetChannelConfigName(enum ChannelConfig chan)
{
switch(chan)
{
case ChannelConfig_Mono: return "Mono";
case ChannelConfig_Stereo: return "Stereo";
}
return "(invalid channel config)";
}
CCMD (snd_status) CCMD (snd_status)
{ {
GSnd->PrintStatus (); GSnd->PrintStatus ();
@ -321,9 +401,28 @@ FString SoundRenderer::GatherStats ()
return "No stats for this sound renderer."; return "No stats for this sound renderer.";
} }
short *SoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type) short *SoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType ctype)
{ {
return NULL; MemoryReader reader((const char*)coded, sizebytes);
short *samples = (short*)calloc(1, outlen);
ChannelConfig chans;
SampleType type;
int srate;
SoundDecoder *decoder = CreateDecoder(&reader);
if(!decoder) return samples;
decoder->getInfo(&srate, &chans, &type);
if(chans != ChannelConfig_Mono || type != SampleType_Int16)
{
DPrintf("Sample is not 16-bit mono\n");
delete decoder;
return samples;
}
decoder->read((char*)samples, outlen);
delete decoder;
return samples;
} }
void SoundRenderer::DrawWaveDebug(int mode) void SoundRenderer::DrawWaveDebug(int mode)
@ -504,3 +603,51 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length)
return retval; return retval;
} }
SoundStream *SoundRenderer::OpenStream(const char *url, int flags)
{
return 0;
}
SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader)
{
SoundDecoder *decoder = NULL;
int pos = reader->Tell();
#ifdef HAVE_MPG123
decoder = new MPG123Decoder;
if (decoder->open(reader))
return decoder;
reader->Seek(pos, SEEK_SET);
delete decoder;
decoder = NULL;
#endif
#ifdef HAVE_SNDFILE
decoder = new SndFileDecoder;
if (decoder->open(reader))
return decoder;
reader->Seek(pos, SEEK_SET);
delete decoder;
decoder = NULL;
#endif
return decoder;
}
// Default readAll implementation, for decoders that can't do anything better
TArray<char> SoundDecoder::readAll()
{
TArray<char> output;
unsigned total = 0;
unsigned got;
output.Resize(total+32768);
while((got=(unsigned)read(&output[total], output.Size()-total)) > 0)
{
total += got;
output.Resize(total*2);
}
output.Resize(total);
return output;
}

View file

@ -38,6 +38,8 @@
#include "doomtype.h" #include "doomtype.h"
#include "i_soundinternal.h" #include "i_soundinternal.h"
class FileReader;
enum ECodecType enum ECodecType
{ {
CODEC_Unknown, CODEC_Unknown,
@ -82,6 +84,8 @@ public:
typedef bool (*SoundStreamCallback)(SoundStream *stream, void *buff, int len, void *userdata); typedef bool (*SoundStreamCallback)(SoundStream *stream, void *buff, int len, void *userdata);
struct SoundDecoder;
class SoundRenderer class SoundRenderer
{ {
public: public:
@ -101,7 +105,8 @@ public:
// Streaming sounds. // Streaming sounds.
virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0;
virtual SoundStream *OpenStream (const char *filename, int flags, int offset, int length) = 0; virtual SoundStream *OpenStream (FileReader *reader, int flags) = 0;
virtual SoundStream *OpenStream (const char *url, int flags);
// Starts a sound. // Starts a sound.
virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0; virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0;
@ -142,6 +147,7 @@ public:
virtual void UpdateListener (SoundListener *) = 0; virtual void UpdateListener (SoundListener *) = 0;
virtual void UpdateSounds () = 0; virtual void UpdateSounds () = 0;
virtual void UpdateMusic() {}
virtual bool IsValid () = 0; virtual bool IsValid () = 0;
virtual void PrintStatus () = 0; virtual void PrintStatus () = 0;
@ -150,6 +156,9 @@ public:
virtual short *DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type); virtual short *DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type);
virtual void DrawWaveDebug(int mode); virtual void DrawWaveDebug(int mode);
protected:
virtual SoundDecoder *CreateDecoder(FileReader *reader);
}; };
extern SoundRenderer *GSnd; extern SoundRenderer *GSnd;
@ -166,4 +175,7 @@ FISoundChannel *S_GetChannel(void *syschan);
extern ReverbContainer *DefaultEnvironments[26]; extern ReverbContainer *DefaultEnvironments[26];
bool IsFModExPresent();
bool IsOpenALPresent();
#endif #endif

View file

@ -1,7 +1,13 @@
#ifndef __SNDINT_H #ifndef __SNDINT_H
#define __SNDINT_H #define __SNDINT_H
#include <stdio.h>
#include "basictypes.h" #include "basictypes.h"
#include "vectors.h"
#include "tarray.h"
class FileReader;
// For convenience, this structure matches FMOD_REVERB_PROPERTIES. // For convenience, this structure matches FMOD_REVERB_PROPERTIES.
// Since I can't very well #include system-specific stuff in the // Since I can't very well #include system-specific stuff in the
@ -96,8 +102,46 @@ struct FISoundChannel
// callback that can't be passed a sound channel pointer // callback that can't be passed a sound channel pointer
FRolloffInfo Rolloff; FRolloffInfo Rolloff;
float DistanceScale; float DistanceScale;
float DistanceSqr;
bool ManualRolloff;
}; };
enum SampleType
{
SampleType_UInt8,
SampleType_Int16
};
enum ChannelConfig
{
ChannelConfig_Mono,
ChannelConfig_Stereo
};
const char *GetSampleTypeName(enum SampleType type);
const char *GetChannelConfigName(enum ChannelConfig chan);
struct SoundDecoder
{
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
virtual size_t read(char *buffer, size_t bytes) = 0;
virtual TArray<char> readAll();
virtual bool seek(size_t ms_offset) = 0;
virtual size_t getSampleOffset() = 0;
virtual size_t getSampleLength() { return 0; }
SoundDecoder() { }
virtual ~SoundDecoder() { }
protected:
virtual bool open(FileReader *reader) = 0;
friend class SoundRenderer;
private:
// Make non-copyable
SoundDecoder(const SoundDecoder &rhs);
SoundDecoder& operator=(const SoundDecoder &rhs);
};
#endif #endif

View file

@ -0,0 +1,206 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD
#endif
#include "except.h"
#include "mpg123_decoder.h"
#include "files.h"
#ifdef HAVE_MPG123
static bool inited = false;
off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence)
{
MPG123Decoder *self = reinterpret_cast<MPG123Decoder*>(handle);
FileReader *reader = self->Reader;
if(whence == SEEK_SET)
offset += self->StartOffset;
else if(whence == SEEK_CUR)
{
if(offset < 0 && reader->Tell()+offset < self->StartOffset)
return -1;
}
else if(whence == SEEK_END)
{
if(offset < 0 && reader->GetLength()+offset < self->StartOffset)
return -1;
}
if(reader->Seek(offset, whence) != 0)
return -1;
return reader->Tell() - self->StartOffset;
}
ssize_t MPG123Decoder::file_read(void *handle, void *buffer, size_t bytes)
{
FileReader *reader = reinterpret_cast<MPG123Decoder*>(handle)->Reader;
return reader->Read(buffer, bytes);
}
MPG123Decoder::~MPG123Decoder()
{
if(MPG123)
{
mpg123_close(MPG123);
mpg123_delete(MPG123);
MPG123 = 0;
}
}
bool MPG123Decoder::open(FileReader *reader)
{
if(!inited)
{
__try
{
if(mpg123_init() != MPG123_OK)
return false;
inited = true;
}
__except (CheckException(GetExceptionCode()))
{
// this means that the delay loaded decoder DLL was not found.
return false;
}
}
Reader = reader;
StartOffset = 0;
char data[10];
if(file_read(this, data, 10) != 10)
return false;
int start_offset = 0;
// Check for ID3 tags and skip them
if(memcmp(data, "ID3", 3) == 0 &&
(BYTE)data[3] <= 4 && (BYTE)data[4] != 0xff &&
(data[5]&0x0f) == 0 && (data[6]&0x80) == 0 &&
(data[7]&0x80) == 0 && (data[8]&0x80) == 0 &&
(data[9]&0x80) == 0)
{
// ID3v2
start_offset = (data[6]<<21) | (data[7]<<14) |
(data[8]<< 7) | (data[9] );
start_offset += ((data[5]&0x10) ? 20 : 10);
}
StartOffset = start_offset;
if(file_lseek(this, 0, SEEK_SET) != 0)
return false;
// Check for a frame header
bool frame_ok = false;
if(file_read(this, data, 3) == 3)
{
if((BYTE)data[0] == 0xff &&
((data[1]&0xfe) == 0xfa/*MPEG-1*/ || (data[1]&0xfe) == 0xf2/*MPEG-2*/))
{
int brate_idx = (data[2]>>4) & 0x0f;
int srate_idx = (data[2]>>2) & 0x03;
if(brate_idx != 0 && brate_idx != 15 && srate_idx != 3)
frame_ok = (file_lseek(this, 0, SEEK_SET) == 0);
}
}
if(frame_ok)
{
MPG123 = mpg123_new(NULL, NULL);
if(mpg123_replace_reader_handle(MPG123, file_read, file_lseek, NULL) == MPG123_OK &&
mpg123_open_handle(MPG123, this) == MPG123_OK)
{
int enc, channels;
long srate;
if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
{
if((channels == 1 || channels == 2) && srate > 0 &&
mpg123_format_none(MPG123) == MPG123_OK &&
mpg123_format(MPG123, srate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
{
// All OK
Done = false;
return true;
}
}
mpg123_close(MPG123);
}
mpg123_delete(MPG123);
MPG123 = 0;
}
return false;
}
void MPG123Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
{
int enc = 0, channels = 0;
long srate = 0;
mpg123_getformat(MPG123, &srate, &channels, &enc);
*samplerate = srate;
if(channels == 2)
*chans = ChannelConfig_Stereo;
else
*chans = ChannelConfig_Mono;
*type = SampleType_Int16;
}
size_t MPG123Decoder::read(char *buffer, size_t bytes)
{
size_t amt = 0;
while(!Done && bytes > 0)
{
size_t got = 0;
int ret = mpg123_read(MPG123, (unsigned char*)buffer, bytes, &got);
bytes -= got;
buffer += got;
amt += got;
if(ret == MPG123_NEW_FORMAT || ret == MPG123_DONE || got == 0)
{
Done = true;
break;
}
}
return amt;
}
bool MPG123Decoder::seek(size_t ms_offset)
{
int enc, channels;
long srate;
if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
{
size_t smp_offset = (size_t)((double)ms_offset / 1000. * srate);
if(mpg123_seek(MPG123, smp_offset, SEEK_SET) >= 0)
{
Done = false;
return true;
}
}
return false;
}
size_t MPG123Decoder::getSampleOffset()
{
return mpg123_tell(MPG123);
}
size_t MPG123Decoder::getSampleLength()
{
off_t len = mpg123_length(MPG123);
return (len > 0) ? len : 0;
}
#endif

View file

@ -0,0 +1,44 @@
#ifndef MPG123_DECODER_H
#define MPG123_DECODER_H
#include "i_soundinternal.h"
#ifdef HAVE_MPG123
#ifdef _MSC_VER
typedef int ssize_t;
#endif
#include "mpg123.h"
struct MPG123Decoder : public SoundDecoder
{
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes);
virtual bool seek(size_t ms_offset);
virtual size_t getSampleOffset();
virtual size_t getSampleLength();
MPG123Decoder() : MPG123(0) { }
virtual ~MPG123Decoder();
protected:
virtual bool open(FileReader *reader);
private:
mpg123_handle *MPG123;
bool Done;
FileReader *Reader;
int StartOffset;
static off_t file_lseek(void *handle, off_t offset, int whence);
static ssize_t file_read(void *handle, void *buffer, size_t bytes);
// Make non-copyable
MPG123Decoder(const MPG123Decoder &rhs);
MPG123Decoder& operator=(const MPG123Decoder &rhs);
};
#endif
#endif /* MPG123_DECODER_H */

View file

@ -1,5 +1,6 @@
#include "i_musicinterns.h" #include "i_musicinterns.h"
#include "i_cd.h" #include "i_cd.h"
#include "files.h"
void CDSong::Play (bool looping, int subsong) void CDSong::Play (bool looping, int subsong)
{ {
@ -78,31 +79,31 @@ bool CDSong::IsPlaying ()
return m_Status != STATE_Stopped; return m_Status != STATE_Stopped;
} }
CDDAFile::CDDAFile (FILE *file, int length) CDDAFile::CDDAFile (FileReader &reader)
: CDSong () : CDSong ()
{ {
DWORD chunk; DWORD chunk;
WORD track; WORD track;
DWORD discid; DWORD discid;
long endpos = ftell (file) + length - 8; long endpos = reader.Tell() + reader.GetLength() - 8;
// I_RegisterSong already identified this as a CDDA file, so we // I_RegisterSong already identified this as a CDDA file, so we
// just need to check the contents we're interested in. // just need to check the contents we're interested in.
fseek (file, 12, SEEK_CUR); reader.Seek(12, SEEK_CUR);
while (ftell (file) < endpos) while (reader.Tell() < endpos)
{ {
fread (&chunk, 4, 1, file); reader.Read(&chunk, 4);
if (chunk != (('f')|(('m')<<8)|(('t')<<16)|((' ')<<24))) if (chunk != (('f')|(('m')<<8)|(('t')<<16)|((' ')<<24)))
{ {
fread (&chunk, 4, 1, file); reader.Read(&chunk, 4);
fseek (file, chunk, SEEK_CUR); reader.Seek(chunk, SEEK_CUR);
} }
else else
{ {
fseek (file, 6, SEEK_CUR); reader.Seek(6, SEEK_CUR);
fread (&track, 2, 1, file); reader.Read(&track, 2);
fread (&discid, 4, 1, file); reader.Read(&discid, 4);
if (CD_InitID (discid) && CD_CheckTrack (track)) if (CD_InitID (discid) && CD_CheckTrack (track))
{ {

View file

@ -30,6 +30,7 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "i_sound.h" #include "i_sound.h"
#include "i_system.h" #include "i_system.h"
#include "files.h"
#undef CDECL // w32api's windef.h defines this #undef CDECL // w32api's windef.h defines this
#include "../dumb/include/dumb.h" #include "../dumb/include/dumb.h"
@ -531,24 +532,17 @@ static DUMBFILE_SYSTEM mem_dfs = {
// //
//========================================================================== //==========================================================================
DUMBFILE *dumb_read_allfile(dumbfile_mem_status *filestate, BYTE *start, FILE *file, BYTE *musiccache, int lenhave, int lenfull) DUMBFILE *dumb_read_allfile(dumbfile_mem_status *filestate, BYTE *start, FileReader &reader, int lenhave, int lenfull)
{ {
filestate->size = lenfull; filestate->size = lenfull;
filestate->offset = 0; filestate->offset = 0;
if (lenhave >= lenfull) if (lenhave >= lenfull)
{
filestate->ptr = (BYTE *)start; filestate->ptr = (BYTE *)start;
return dumbfile_open_ex(filestate, &mem_dfs);
}
if (musiccache != NULL)
{
filestate->ptr = (BYTE *)musiccache;
}
else else
{ {
BYTE *mem = new BYTE[lenfull]; BYTE *mem = new BYTE[lenfull];
memcpy(mem, start, lenhave); memcpy(mem, start, lenhave);
if (fread(mem + lenhave, 1, lenfull - lenhave, file) != (size_t)(lenfull - lenhave)) if (reader.Read(mem + lenhave, lenfull - lenhave) != (lenfull - lenhave))
{ {
delete[] mem; delete[] mem;
return NULL; return NULL;
@ -753,7 +747,7 @@ static void MOD_SetAutoChip(DUH *duh)
// //
//========================================================================== //==========================================================================
MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size) MusInfo *MOD_OpenSong(FileReader &reader)
{ {
DUH *duh = 0; DUH *duh = 0;
int headsize; int headsize;
@ -777,40 +771,36 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
atterm(dumb_exit); atterm(dumb_exit);
int size = reader.GetLength();
fpos = reader.Tell();
filestate.ptr = start; filestate.ptr = start;
filestate.offset = 0; filestate.offset = 0;
headsize = MIN((int)sizeof(start), size); headsize = MIN((int)sizeof(start), size);
if (musiccache != NULL)
{ if (headsize != reader.Read(start, headsize))
memcpy(start, musiccache, headsize);
}
else
{
fpos = ftell(file);
if ((size_t)headsize != fread(start, 1, headsize, file))
{ {
return NULL; return NULL;
} }
}
if (size >= 4 && dstart[0] == MAKE_ID('I','M','P','M')) if (size >= 4 && dstart[0] == MAKE_ID('I','M','P','M'))
{ {
is_it = true; is_it = true;
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_it_quick(f); duh = dumb_read_it_quick(f);
} }
} }
else if (size >= 17 && !memcmp(start, "Extended Module: ", 17)) else if (size >= 17 && !memcmp(start, "Extended Module: ", 17))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_xm_quick(f); duh = dumb_read_xm_quick(f);
} }
} }
else if (size >= 0x30 && dstart[11] == MAKE_ID('S','C','R','M')) else if (size >= 0x30 && dstart[11] == MAKE_ID('S','C','R','M'))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_s3m_quick(f); duh = dumb_read_s3m_quick(f);
} }
@ -821,7 +811,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
!memcmp( &start[20], "BMOD2STM", 8 ) || !memcmp( &start[20], "BMOD2STM", 8 ) ||
!memcmp( &start[20], "WUZAMOD!", 8 ) ) ) !memcmp( &start[20], "WUZAMOD!", 8 ) ) )
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_stm_quick(f); duh = dumb_read_stm_quick(f);
} }
@ -830,21 +820,21 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
((start[0] == 0x69 && start[1] == 0x66) || ((start[0] == 0x69 && start[1] == 0x66) ||
(start[0] == 0x4A && start[1] == 0x4E))) (start[0] == 0x4A && start[1] == 0x4E)))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_669_quick(f); duh = dumb_read_669_quick(f);
} }
} }
else if (size >= 0x30 && dstart[11] == MAKE_ID('P','T','M','F')) else if (size >= 0x30 && dstart[11] == MAKE_ID('P','T','M','F'))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_ptm_quick(f); duh = dumb_read_ptm_quick(f);
} }
} }
else if (size >= 4 && dstart[0] == MAKE_ID('P','S','M',' ')) else if (size >= 4 && dstart[0] == MAKE_ID('P','S','M',' '))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_psm_quick(f, 0/*start_order*/); duh = dumb_read_psm_quick(f, 0/*start_order*/);
/*start_order = 0;*/ /*start_order = 0;*/
@ -852,14 +842,14 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
} }
else if (size >= 4 && dstart[0] == (DWORD)MAKE_ID('P','S','M',254)) else if (size >= 4 && dstart[0] == (DWORD)MAKE_ID('P','S','M',254))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_old_psm_quick(f); duh = dumb_read_old_psm_quick(f);
} }
} }
else if (size >= 3 && start[0] == 'M' && start[1] == 'T' && start[2] == 'M') else if (size >= 3 && start[0] == 'M' && start[1] == 'T' && start[2] == 'M')
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_mtm_quick(f); duh = dumb_read_mtm_quick(f);
} }
@ -869,7 +859,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
dstart[2] == MAKE_ID('A','M',' ',' ') || dstart[2] == MAKE_ID('A','M',' ',' ') ||
dstart[2] == MAKE_ID('A','M','F','F'))) dstart[2] == MAKE_ID('A','M','F','F')))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_riff_quick(f); duh = dumb_read_riff_quick(f);
} }
@ -878,7 +868,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
!memcmp( start, "ASYLUM Music Format", 19 ) && !memcmp( start, "ASYLUM Music Format", 19 ) &&
!memcmp( start + 19, " V1.0", 5 ) ) !memcmp( start + 19, " V1.0", 5 ) )
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_asy_quick(f); duh = dumb_read_asy_quick(f);
} }
@ -887,7 +877,7 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
dstart[0] == MAKE_ID('O','K','T','A') && dstart[0] == MAKE_ID('O','K','T','A') &&
dstart[1] == MAKE_ID('S','O','N','G')) dstart[1] == MAKE_ID('S','O','N','G'))
{ {
if ((f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
duh = dumb_read_okt_quick(f); duh = dumb_read_okt_quick(f);
} }
@ -898,12 +888,9 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
is_dos = false; is_dos = false;
if (filestate.ptr == (BYTE *)start) if (filestate.ptr == (BYTE *)start)
{ {
if (!(f = dumb_read_allfile(&filestate, start, file, musiccache, headsize, size))) if (!(f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
{ {
if (file != NULL) reader.Seek(fpos, SEEK_SET);
{
fseek(file, fpos, SEEK_SET);
}
return NULL; return NULL;
} }
} }
@ -914,8 +901,8 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
// No way to get the filename, so we can't check for a .mod extension, and // No way to get the filename, so we can't check for a .mod extension, and
// therefore, trying to load an old 15-instrument SoundTracker module is not // therefore, trying to load an old 15-instrument SoundTracker module is not
// safe. We'll restrict MOD loading to 31-instrument modules with known // safe. We'll restrict MOD loading to 31-instrument modules with known
// signatures and let FMOD worry about 15-instrument ones. (Assuming it even // signatures and let the sound system worry about 15-instrument ones.
// supports them; I have not checked.) // (Assuming it even supports them)
duh = dumb_read_mod_quick(f, TRUE); duh = dumb_read_mod_quick(f, TRUE);
} }
@ -944,12 +931,9 @@ MusInfo *MOD_OpenSong(FILE *file, BYTE *musiccache, int size)
else else
{ {
// Reposition file pointer for other codecs to do their checks. // Reposition file pointer for other codecs to do their checks.
if (file != NULL) reader.Seek(fpos, SEEK_SET);
{
fseek(file, fpos, SEEK_SET);
} }
} if (filestate.ptr != (BYTE *)start)
if (filestate.ptr != (BYTE *)start && filestate.ptr != musiccache)
{ {
delete[] const_cast<BYTE *>(filestate.ptr); delete[] const_cast<BYTE *>(filestate.ptr);
} }

View file

@ -42,6 +42,7 @@
#include "critsec.h" #include "critsec.h"
#include <gme/gme.h> #include <gme/gme.h>
#include "v_text.h" #include "v_text.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -104,7 +105,7 @@ const char *GME_CheckFormat(uint32 id)
// //
//========================================================================== //==========================================================================
MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt) MusInfo *GME_OpenSong(FileReader &reader, const char *fmt)
{ {
gme_type_t type; gme_type_t type;
gme_err_t err; gme_err_t err;
@ -123,29 +124,26 @@ MusInfo *GME_OpenSong(FILE *file, BYTE *musiccache, int len, const char *fmt)
{ {
return NULL; return NULL;
} }
if (musiccache != NULL)
{ int fpos = reader.Tell();
song = musiccache; int len = reader.GetLength();
}
else
{
song = new BYTE[len]; song = new BYTE[len];
if (fread(song, 1, len, file) != (size_t)len) if (reader.Read(song, len) != len)
{ {
delete[] song; delete[] song;
gme_delete(emu); gme_delete(emu);
reader.Seek(fpos, SEEK_SET);
return NULL; return NULL;
} }
}
err = gme_load_data(emu, song, len); err = gme_load_data(emu, song, len);
if (song != musiccache)
{
delete[] song; delete[] song;
}
if (err != NULL) if (err != NULL)
{ {
Printf("Failed loading song: %s\n", err); Printf("Failed loading song: %s\n", err);
gme_delete(emu); gme_delete(emu);
reader.Seek(fpos, SEEK_SET);
return NULL; return NULL;
} }
return new GMESong(emu, sample_rate); return new GMESong(emu, sample_rate);

View file

@ -38,6 +38,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -127,7 +128,7 @@ extern char MIDI_CommonLengths[15];
// //
//========================================================================== //==========================================================================
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type) HMISong::HMISong (FileReader &reader, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Tracks(0) : MIDIStreamer(type), MusHeader(0), Tracks(0)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -136,6 +137,7 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
return; return;
} }
#endif #endif
int len = reader.GetLength();
if (len < 0x100) if (len < 0x100)
{ // Way too small to be HMI. { // Way too small to be HMI.
return; return;
@ -143,15 +145,8 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
MusHeader = new BYTE[len]; MusHeader = new BYTE[len];
SongLen = len; SongLen = len;
NumTracks = 0; NumTracks = 0;
if (file != NULL) if (reader.Read(MusHeader, len) != len)
{
if (fread(MusHeader, 1, len, file) != (size_t)len)
return; return;
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0) if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)

View file

@ -33,7 +33,7 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
pair[p+1].Value = -3.0; pair[p+1].Value = -3.0;
pair[p+2].Text = "TiMidity++"; pair[p+2].Text = "TiMidity++";
pair[p+2].Value = -2.0; pair[p+2].Value = -2.0;
pair[p+3].Text = "FMOD"; pair[p+3].Text = "Sound System";
pair[p+3].Value = -1.0; pair[p+3].Value = -1.0;
} }
@ -172,7 +172,7 @@ CCMD (snd_listmididevices)
PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MOD_SWSYNTH, 0); PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MOD_SWSYNTH, 0);
PrintMidiDevice (-3, "Emulated OPL FM Synth", MOD_FMSYNTH, 0); PrintMidiDevice (-3, "Emulated OPL FM Synth", MOD_FMSYNTH, 0);
PrintMidiDevice (-2, "TiMidity++", MOD_SWSYNTH, 0); PrintMidiDevice (-2, "TiMidity++", MOD_SWSYNTH, 0);
PrintMidiDevice (-1, "FMOD", MOD_SWSYNTH, 0); PrintMidiDevice (-1, "Sound System", 0, 0);
if (nummididevices != 0) if (nummididevices != 0)
{ {
for (id = 0; id < nummididevices; ++id) for (id = 0; id < nummididevices; ++id)
@ -217,6 +217,6 @@ CCMD (snd_listmididevices)
Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "");
Printf("%s-1. FMOD\n", -1 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-1. Sound System\n", -1 == snd_mididevice ? TEXTCOLOR_BOLD : "");
} }
#endif #endif

View file

@ -611,7 +611,7 @@ int TimidityPPMIDIDevice::Resume()
{ {
if (LaunchTimidity()) if (LaunchTimidity())
{ {
// Assume success if not mixing with FMOD // Assume success if not mixing with the sound system
if (Stream == NULL || Stream->Play(true, timidity_mastervolume)) if (Stream == NULL || Stream->Play(true, timidity_mastervolume))
{ {
Started = true; Started = true;

View file

@ -215,13 +215,13 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
- if explicitly selected by $mididevice - if explicitly selected by $mididevice
- when snd_mididevice is -2 and no midi device is set for the song - when snd_mididevice is -2 and no midi device is set for the song
- FMod: - Sound System:
- if explicitly selected by $mididevice - if explicitly selected by $mididevice
- when snd_mididevice is -1 and no midi device is set for the song - when snd_mididevice is -1 and no midi device is set for the song
- as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0 - as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0
- MMAPI (Win32 only): - MMAPI (Win32 only):
- if explicitly selected by $mididevice (non-Win32 redirects this to FMOD) - if explicitly selected by $mididevice (non-Win32 redirects this to Sound System)
- when snd_mididevice is >= 0 and no midi device is set for the song - when snd_mididevice is >= 0 and no midi device is set for the song
- as fallback when both OPL and Timidity failed and snd_mididevice is >= 0 - as fallback when both OPL and Timidity failed and snd_mididevice is >= 0
*/ */
@ -233,7 +233,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
} }
switch (snd_mididevice) switch (snd_mididevice)
{ {
case -1: return MDEV_FMOD; case -1: return MDEV_SNDSYS;
case -2: return MDEV_TIMIDITY; case -2: return MDEV_TIMIDITY;
case -3: return MDEV_OPL; case -3: return MDEV_OPL;
case -4: return MDEV_GUS; case -4: return MDEV_GUS;
@ -244,7 +244,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
#ifdef _WIN32 #ifdef _WIN32
return MDEV_MMAPI; return MDEV_MMAPI;
#else #else
return MDEV_FMOD; return MDEV_SNDSYS;
#endif #endif
} }
} }
@ -271,8 +271,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
return new FluidSynthMIDIDevice; return new FluidSynthMIDIDevice;
#endif #endif
case MDEV_FMOD: case MDEV_SNDSYS:
return new FMODMIDIDevice; return new SndSysMIDIDevice;
case MDEV_GUS: case MDEV_GUS:
return new TimidityMIDIDevice; return new TimidityMIDIDevice;
@ -285,8 +285,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
catch (CRecoverableError &err) catch (CRecoverableError &err)
{ {
// The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found. // The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found.
Printf("Unable to create OPL MIDI device: %s\nFalling back to FModEx playback", err.GetMessage()); Printf("Unable to create OPL MIDI device: %s\nFalling back to Sound System playback", err.GetMessage());
return new FMODMIDIDevice; return new SndSysMIDIDevice;
} }
case MDEV_TIMIDITY: case MDEV_TIMIDITY:

View file

@ -42,6 +42,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -91,7 +92,7 @@ static const BYTE CtrlTranslate[15] =
// //
//========================================================================== //==========================================================================
MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type) MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), MusBuffer(0) : MIDIStreamer(type), MusHeader(0), MusBuffer(0)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -104,11 +105,7 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
BYTE front[32]; BYTE front[32];
int start; int start;
if (file == NULL) if (reader.Read(front, sizeof(front)) != sizeof(front))
{
memcpy(front, musiccache, sizeof(front));
}
else if (fread(front, 1, sizeof(front), file) != sizeof(front))
{ {
return; return;
} }
@ -124,24 +121,17 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
} }
// Read the remainder of the song. // Read the remainder of the song.
len = int(len - start); int len = int(reader.GetLength() - start);
if (len < (int)sizeof(MusHeader)) if (len < (int)sizeof(MusHeader))
{ // It's too short. { // It's too short.
return; return;
} }
MusHeader = (MUSHeader *)new BYTE[len]; MusHeader = (MUSHeader *)new BYTE[len];
if (file == NULL)
{
memcpy(MusHeader, musiccache + start, len);
}
else
{
memcpy(MusHeader, front + start, sizeof(front) - start); memcpy(MusHeader, front + start, sizeof(front) - start);
if (fread((BYTE *)MusHeader + sizeof(front) - start, 1, len - (sizeof(front) - start), file) != (size_t)(len - (32 - start))) if (reader.Read((BYTE *)MusHeader + sizeof(front) - start, len - (sizeof(front) - start)) != (len - (32 - start)))
{ {
return; return;
} }
}
// Do some validation of the MUS file. // Do some validation of the MUS file.
if (LittleShort(MusHeader->NumChans) > 15) if (LittleShort(MusHeader->NumChans) > 15)

View file

@ -22,11 +22,11 @@ CUSTOM_CVAR (Int, opl_numchips, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, opl_core, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, opl_core, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
OPLMUSSong::OPLMUSSong (FILE *file, BYTE *musiccache, int len) OPLMUSSong::OPLMUSSong (FileReader &reader)
{ {
int samples = int(OPL_SAMPLE_RATE / 14); int samples = int(OPL_SAMPLE_RATE / 14);
Music = new OPLmusicFile (file, musiccache, len); Music = new OPLmusicFile (&reader);
m_Stream = GSnd->CreateStream (FillStream, samples*4, m_Stream = GSnd->CreateStream (FillStream, samples*4,
(opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this); (opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this);

View file

@ -38,6 +38,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -234,29 +235,30 @@ FString PseudoMIDIDevice::GetStats()
//========================================================================== //==========================================================================
// //
// FMODMIDIDevice :: Open // SndSysMIDIDevice :: Open
// //
//========================================================================== //==========================================================================
int FMODMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata) int SndSysMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
{ {
return 0; return 0;
} }
//========================================================================== //==========================================================================
// //
// FMODMIDIDevice :: Preprocess // SndSysMIDIDevice :: Preprocess
// //
// Create a standard MIDI file and stream it. // Create a standard MIDI file and stream it.
// //
//========================================================================== //==========================================================================
bool FMODMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) bool SndSysMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
{ {
TArray<BYTE> midi; MemoryArrayReader *reader = new MemoryArrayReader(NULL, 0);
song->CreateSMF(reader->GetArray(), looping ? 0 : 1);
reader->UpdateLength();
song->CreateSMF(midi, looping ? 0 : 1);
bLooping = looping; bLooping = looping;
Stream = GSnd->OpenStream((char *)&midi[0], looping ? SoundStream::Loop : 0, -1, midi.Size()); Stream = GSnd->OpenStream(reader, looping ? SoundStream::Loop : 0);
return false; return false;
} }

View file

@ -41,6 +41,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -101,7 +102,7 @@ char MIDI_CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// //
//========================================================================== //==========================================================================
MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type) MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Tracks(0) : MIDIStreamer(type), MusHeader(0), Tracks(0)
{ {
int p; int p;
@ -113,17 +114,10 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
return; return;
} }
#endif #endif
MusHeader = new BYTE[len]; SongLen = reader.GetLength();
SongLen = len; MusHeader = new BYTE[SongLen];
if (file != NULL) if (reader.Read(MusHeader, SongLen) != SongLen)
{
if (fread(MusHeader, 1, len, file) != (size_t)len)
return; return;
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)
@ -153,7 +147,7 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
Tracks = new TrackInfo[NumTracks]; Tracks = new TrackInfo[NumTracks];
// Gather information about each track // Gather information about each track
for (i = 0, p = 14; i < NumTracks && p < len + 8; ++i) for (i = 0, p = 14; i < NumTracks && p < SongLen + 8; ++i)
{ {
DWORD chunkLen = DWORD chunkLen =
(MusHeader[p+4]<<24) | (MusHeader[p+4]<<24) |
@ -161,9 +155,9 @@ MIDISong2::MIDISong2 (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
(MusHeader[p+6]<<8) | (MusHeader[p+6]<<8) |
(MusHeader[p+7]); (MusHeader[p+7]);
if (chunkLen + p + 8 > (DWORD)len) if (chunkLen + p + 8 > (DWORD)SongLen)
{ // Track too long, so truncate it { // Track too long, so truncate it
chunkLen = len - p - 8; chunkLen = SongLen - p - 8;
} }
if (MusHeader[p+0] == 'M' && if (MusHeader[p+0] == 'M' &&

View file

@ -52,9 +52,14 @@ StreamSong::~StreamSong ()
} }
} }
StreamSong::StreamSong (const char *filename_or_data, int offset, int len) StreamSong::StreamSong (FileReader *reader)
{ {
m_Stream = GSnd->OpenStream (filename_or_data, SoundStream::Loop, offset, len); m_Stream = GSnd->OpenStream (reader, SoundStream::Loop);
}
StreamSong::StreamSong (const char *url)
{
m_Stream = GSnd->OpenStream (url, SoundStream::Loop);
} }
bool StreamSong::IsPlaying () bool StreamSong::IsPlaying ()

View file

@ -38,6 +38,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "files.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -107,7 +108,7 @@ extern char MIDI_CommonLengths[15];
// //
//========================================================================== //==========================================================================
XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type) XMISong::XMISong (FileReader &reader, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Songs(0) : MIDIStreamer(type), MusHeader(0), Songs(0)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -116,20 +117,13 @@ XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
return; return;
} }
#endif #endif
MusHeader = new BYTE[len]; SongLen = reader.GetLength();
SongLen = len; MusHeader = new BYTE[SongLen];
if (file != NULL) if (reader.Read(MusHeader, SongLen) != SongLen)
{
if (fread(MusHeader, 1, len, file) != (size_t)len)
return; return;
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Find all the songs in this file. // Find all the songs in this file.
NumSongs = FindXMIDforms(MusHeader, len, NULL); NumSongs = FindXMIDforms(MusHeader, SongLen, NULL);
if (NumSongs == 0) if (NumSongs == 0)
{ {
return; return;
@ -147,7 +141,7 @@ XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
Songs = new TrackInfo[NumSongs]; Songs = new TrackInfo[NumSongs];
memset(Songs, 0, sizeof(*Songs) * NumSongs); memset(Songs, 0, sizeof(*Songs) * NumSongs);
FindXMIDforms(MusHeader, len, Songs); FindXMIDforms(MusHeader, SongLen, Songs);
CurrSong = Songs; CurrSong = Songs;
DPrintf("XMI song count: %d\n", NumSongs); DPrintf("XMI song count: %d\n", NumSongs);
} }

1973
src/sound/oalsound.cpp Normal file

File diff suppressed because it is too large Load diff

211
src/sound/oalsound.h Normal file
View file

@ -0,0 +1,211 @@
#ifndef OALSOUND_H
#define OALSOUND_H
#include "i_sound.h"
#include "s_sound.h"
#include "menu/menu.h"
#ifndef NO_OPENAL
#include "al.h"
#include "alc.h"
#ifndef ALC_ENUMERATE_ALL_EXT
#define ALC_ENUMERATE_ALL_EXT 1
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
#ifndef ALC_EXT_disconnect
#define ALC_EXT_disconnect 1
#define ALC_CONNECTED 0x313
#endif
#ifndef AL_EXT_source_distance_model
#define AL_EXT_source_distance_model 1
#define AL_SOURCE_DISTANCE_MODEL 0x200
#endif
#ifndef AL_SOFT_loop_points
#define AL_SOFT_loop_points 1
#define AL_LOOP_POINTS_SOFT 0x2015
#endif
#ifndef AL_EXT_float32
#define AL_EXT_float32 1
#define AL_FORMAT_MONO_FLOAT32 0x10010
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_EXT_MCFORMATS
#define AL_EXT_MCFORMATS 1
#define AL_FORMAT_QUAD8 0x1204
#define AL_FORMAT_QUAD16 0x1205
#define AL_FORMAT_QUAD32 0x1206
#define AL_FORMAT_REAR8 0x1207
#define AL_FORMAT_REAR16 0x1208
#define AL_FORMAT_REAR32 0x1209
#define AL_FORMAT_51CHN8 0x120A
#define AL_FORMAT_51CHN16 0x120B
#define AL_FORMAT_51CHN32 0x120C
#define AL_FORMAT_61CHN8 0x120D
#define AL_FORMAT_61CHN16 0x120E
#define AL_FORMAT_61CHN32 0x120F
#define AL_FORMAT_71CHN8 0x1210
#define AL_FORMAT_71CHN16 0x1211
#define AL_FORMAT_71CHN32 0x1212
#endif
#include "efx.h"
class OpenALSoundStream;
class OpenALSoundRenderer : public SoundRenderer
{
public:
OpenALSoundRenderer();
virtual ~OpenALSoundRenderer();
virtual void SetSfxVolume(float volume);
virtual void SetMusicVolume(float volume);
virtual SoundHandle LoadSound(BYTE *sfxdata, int length);
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1);
virtual void UnloadSound(SoundHandle sfx);
virtual unsigned int GetMSLength(SoundHandle sfx);
virtual unsigned int GetSampleLength(SoundHandle sfx);
virtual float GetOutputRate();
// Streaming sounds.
virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata);
virtual SoundStream *OpenStream(FileReader *reader, int flags);
// Starts a sound.
virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan);
virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan);
// Changes a channel's volume.
virtual void ChannelVolume(FISoundChannel *chan, float volume);
// Stops a sound channel.
virtual void StopChannel(FISoundChannel *chan);
// Returns position of sound on this channel, in samples.
virtual unsigned int GetPosition(FISoundChannel *chan);
// Synchronizes following sound startups.
virtual void Sync(bool sync);
// Pauses or resumes all sound effect channels.
virtual void SetSfxPaused(bool paused, int slot);
// Pauses or resumes *every* channel, including environmental reverb.
virtual void SetInactive(SoundRenderer::EInactiveState inactive);
// Updates the volume, separation, and pitch of a sound channel.
virtual void UpdateSoundParams3D(SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel);
virtual void UpdateListener(SoundListener *);
virtual void UpdateSounds();
virtual void UpdateMusic();
virtual void MarkStartTime(FISoundChannel*);
virtual float GetAudibility(FISoundChannel*);
virtual bool IsValid();
virtual void PrintStatus();
virtual void PrintDriversList();
virtual FString GatherStats();
private:
struct {
bool EXT_EFX;
bool EXT_disconnect;
} ALC;
struct {
bool EXT_source_distance_model;
bool SOFT_deferred_updates;
bool SOFT_loop_points;
} AL;
// EFX Extension function pointer variables. Loaded after context creation
// if EFX is supported. These pointers may be context- or device-dependant,
// thus can't be static
// Effect objects
LPALGENEFFECTS alGenEffects;
LPALDELETEEFFECTS alDeleteEffects;
LPALISEFFECT alIsEffect;
LPALEFFECTI alEffecti;
LPALEFFECTIV alEffectiv;
LPALEFFECTF alEffectf;
LPALEFFECTFV alEffectfv;
LPALGETEFFECTI alGetEffecti;
LPALGETEFFECTIV alGetEffectiv;
LPALGETEFFECTF alGetEffectf;
LPALGETEFFECTFV alGetEffectfv;
// Filter objects
LPALGENFILTERS alGenFilters;
LPALDELETEFILTERS alDeleteFilters;
LPALISFILTER alIsFilter;
LPALFILTERI alFilteri;
LPALFILTERIV alFilteriv;
LPALFILTERF alFilterf;
LPALFILTERFV alFilterfv;
LPALGETFILTERI alGetFilteri;
LPALGETFILTERIV alGetFilteriv;
LPALGETFILTERF alGetFilterf;
LPALGETFILTERFV alGetFilterfv;
// Auxiliary slot objects
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void);
ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void);
void LoadReverb(const ReverbContainer *env);
void PurgeStoppedSources();
static FSoundChan *FindLowestChannel();
ALCdevice *Device;
ALCcontext *Context;
TArray<ALuint> Sources;
ALfloat SfxVolume;
ALfloat MusicVolume;
int SFXPaused;
TArray<ALuint> FreeSfx;
TArray<ALuint> PausableSfx;
TArray<ALuint> ReverbSfx;
TArray<ALuint> SfxGroup;
const ReverbContainer *PrevEnvironment;
typedef TMap<WORD,ALuint> EffectMap;
typedef TMapIterator<WORD,ALuint> EffectMapIter;
ALuint EnvSlot;
ALuint EnvFilters[2];
EffectMap EnvEffects;
bool WasInWater;
TArray<OpenALSoundStream*> Streams;
friend class OpenALSoundStream;
ALCdevice *InitDevice();
};
#endif // NO_OPENAL
#endif

View file

@ -0,0 +1,152 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD
#endif
#include "except.h"
#include "sndfile_decoder.h"
#include "templates.h"
#include "files.h"
#include "xs_Float.h"
#ifdef HAVE_SNDFILE
sf_count_t SndFileDecoder::file_get_filelen(void *user_data)
{
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
return reader->GetLength();
}
sf_count_t SndFileDecoder::file_seek(sf_count_t offset, int whence, void *user_data)
{
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
if(reader->Seek((long)offset, whence) != 0)
return -1;
return reader->Tell();
}
sf_count_t SndFileDecoder::file_read(void *ptr, sf_count_t count, void *user_data)
{
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
return reader->Read(ptr, (long)count);
}
sf_count_t SndFileDecoder::file_write(const void *ptr, sf_count_t count, void *user_data)
{
return -1;
}
sf_count_t SndFileDecoder::file_tell(void *user_data)
{
FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
return reader->Tell();
}
SndFileDecoder::~SndFileDecoder()
{
if(SndFile)
sf_close(SndFile);
SndFile = 0;
}
bool SndFileDecoder::open(FileReader *reader)
{
__try
{
SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell };
Reader = reader;
SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this);
if (SndFile)
{
if (SndInfo.channels == 1 || SndInfo.channels == 2)
return true;
sf_close(SndFile);
SndFile = 0;
}
}
__except (CheckException(GetExceptionCode()))
{
// this means that the delay loaded decoder DLL was not found.
}
return false;
}
void SndFileDecoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
{
*samplerate = SndInfo.samplerate;
if(SndInfo.channels == 2)
*chans = ChannelConfig_Stereo;
else
*chans = ChannelConfig_Mono;
*type = SampleType_Int16;
}
size_t SndFileDecoder::read(char *buffer, size_t bytes)
{
short *out = (short*)buffer;
size_t frames = bytes / SndInfo.channels / 2;
size_t total = 0;
// It seems libsndfile has a bug with converting float samples from Vorbis
// to the 16-bit shorts we use, which causes some PCM samples to overflow
// and wrap, creating static. So instead, read the samples as floats and
// convert to short ourselves.
// Use a loop to convert a handful of samples at a time, avoiding a heap
// allocation for temporary storage. 64 at a time works, though maybe it
// could be more.
while(total < frames)
{
size_t todo = MIN<size_t>(frames-total, 64/SndInfo.channels);
float tmp[64];
size_t got = (size_t)sf_readf_float(SndFile, tmp, todo);
if(got < todo) frames = total + got;
for(size_t i = 0;i < got*SndInfo.channels;i++)
*out++ = (short)xs_CRoundToInt(clamp(tmp[i] * 32767.f, -32768.f, 32767.f));
total += got;
}
return total * SndInfo.channels * 2;
}
TArray<char> SndFileDecoder::readAll()
{
if(SndInfo.frames <= 0)
return SoundDecoder::readAll();
int framesize = 2 * SndInfo.channels;
TArray<char> output;
output.Resize((unsigned)(SndInfo.frames * framesize));
size_t got = read(&output[0], output.Size());
output.Resize(got);
return output;
}
bool SndFileDecoder::seek(size_t ms_offset)
{
size_t smp_offset = (size_t)((double)ms_offset / 1000. * SndInfo.samplerate);
if(sf_seek(SndFile, smp_offset, SEEK_SET) < 0)
return false;
return true;
}
size_t SndFileDecoder::getSampleOffset()
{
return (size_t)sf_seek(SndFile, 0, SEEK_CUR);
}
size_t SndFileDecoder::getSampleLength()
{
return (size_t)((SndInfo.frames > 0) ? SndInfo.frames : 0);
}
#endif

View file

@ -0,0 +1,44 @@
#ifndef SNDFILE_DECODER_H
#define SNDFILE_DECODER_H
#include "i_soundinternal.h"
#ifdef HAVE_SNDFILE
#include "sndfile.h"
struct SndFileDecoder : public SoundDecoder
{
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes);
virtual TArray<char> readAll();
virtual bool seek(size_t ms_offset);
virtual size_t getSampleOffset();
virtual size_t getSampleLength();
SndFileDecoder() : SndFile(0) { }
virtual ~SndFileDecoder();
protected:
virtual bool open(FileReader *reader);
private:
SNDFILE *SndFile;
SF_INFO SndInfo;
FileReader *Reader;
static sf_count_t file_get_filelen(void *user_data);
static sf_count_t file_seek(sf_count_t offset, int whence, void *user_data);
static sf_count_t file_read(void *ptr, sf_count_t count, void *user_data);
static sf_count_t file_write(const void *ptr, sf_count_t count, void *user_data);
static sf_count_t file_tell(void *user_data);
// Make non-copyable
SndFileDecoder(const SndFileDecoder &rhs);
SndFileDecoder& operator=(const SndFileDecoder &rhs);
};
#endif
#endif /* SNDFILE_DECODER_H */

View file

@ -136,6 +136,17 @@ public:
return Array[Count-1]; return Array[Count-1];
} }
unsigned int Find(const T& item) const
{
unsigned int i;
for(i = 0;i < Count;++i)
{
if(Array[i] == item)
break;
}
return i;
}
unsigned int Push (const T &item) unsigned int Push (const T &item)
{ {
Grow (1); Grow (1);

View file

@ -1228,6 +1228,17 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
return new FWadLump(LumpInfo[lump].lump, true); return new FWadLump(LumpInfo[lump].lump, true);
} }
FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
{
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
{
return NULL;
}
return new FWadLump(lump, LumpInfo[lump].lump);
}
//========================================================================== //==========================================================================
// //
// GetFileReader // GetFileReader
@ -1417,6 +1428,34 @@ FWadLump::FWadLump(FResourceLump *lump, bool alwayscache)
} }
} }
FWadLump::FWadLump(int lumpnum, FResourceLump *lump)
: FileReader()
{
FileReader *f = lump->GetReader();
if (f != NULL && f->GetFile() != NULL)
{
// Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming
int fileno = Wads.GetLumpFile(lumpnum);
const char *filename = Wads.GetWadFullName(fileno);
File = fopen(filename, "rb");
if (File != NULL)
{
Length = lump->LumpSize;
StartPos = FilePos = lump->GetFileOffset();
Lump = NULL;
CloseOnDestruct = true;
Seek(0, SEEK_SET);
return;
}
}
File = NULL;
Length = lump->LumpSize;
StartPos = FilePos = 0;
Lump = lump;
Lump->CacheLump();
}
FWadLump::~FWadLump() FWadLump::~FWadLump()
{ {
if (Lump != NULL) if (Lump != NULL)

View file

@ -112,6 +112,7 @@ public:
private: private:
FWadLump (FResourceLump *Lump, bool alwayscache = false); FWadLump (FResourceLump *Lump, bool alwayscache = false);
FWadLump(int lumpnum, FResourceLump *lump);
FResourceLump *Lump; FResourceLump *Lump;
@ -185,6 +186,7 @@ public:
FWadLump OpenLumpNum (int lump); FWadLump OpenLumpNum (int lump);
FWadLump OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); } FWadLump OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); }
FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE
FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD

View file

@ -1601,19 +1601,19 @@ unsigned int I_MakeRNGSeed()
FString I_GetLongPathName(FString shortpath) FString I_GetLongPathName(FString shortpath)
{ {
static TOptWin32Proc<DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)> static TOptWin32Proc<DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)>
GetLongPathName("kernel32.dll", "GetLongPathNameA", NULL); GetLongPathNameA("kernel32.dll", "GetLongPathNameA");
// Doesn't exist on NT4 // Doesn't exist on NT4
if (GetLongPathName == NULL) if (GetLongPathName == NULL)
return shortpath; return shortpath;
DWORD buffsize = GetLongPathName.Call(shortpath.GetChars(), NULL, 0); DWORD buffsize = GetLongPathNameA.Call(shortpath.GetChars(), NULL, 0);
if (buffsize == 0) if (buffsize == 0)
{ // nothing to change (it doesn't exist, maybe?) { // nothing to change (it doesn't exist, maybe?)
return shortpath; return shortpath;
} }
TCHAR *buff = new TCHAR[buffsize]; TCHAR *buff = new TCHAR[buffsize];
DWORD buffsize2 = GetLongPathName.Call(shortpath.GetChars(), buff, buffsize); DWORD buffsize2 = GetLongPathNameA.Call(shortpath.GetChars(), buff, buffsize);
if (buffsize2 >= buffsize) if (buffsize2 >= buffsize)
{ // Failure! Just return the short path { // Failure! Just return the short path
delete[] buff; delete[] buff;

View file

@ -56,25 +56,20 @@ extern os_t OSPlatform;
template<typename Proto> template<typename Proto>
class TOptWin32Proc class TOptWin32Proc
{ {
static Proto GetOptionalWin32Proc(const char* module, const char* function, const char* alt) static Proto GetOptionalWin32Proc(const char* module, const char* function)
{ {
HMODULE hmodule = GetModuleHandle(module); HMODULE hmodule = GetModuleHandle(module);
if (hmodule == NULL) if (hmodule == NULL)
return NULL; return NULL;
Proto ret = (Proto)GetProcAddress(hmodule, function); return (Proto)GetProcAddress(hmodule, function);
if(ret != NULL || alt == NULL)
return ret;
// Lookup alternate function name (ex. ProcW -> ProcA)
return (Proto)GetProcAddress(hmodule, alt);
} }
public: public:
const Proto Call; const Proto Call;
TOptWin32Proc(const char* module, const char* function, const char* alt=NULL) TOptWin32Proc(const char* module, const char* function)
: Call(GetOptionalWin32Proc(module, function, alt)) {} : Call(GetOptionalWin32Proc(module, function)) {}
// Wrapper object can be tested against NULL, but not directly called. // Wrapper object can be tested against NULL, but not directly called.
operator const void*() const { return Call; } operator const void*() const { return Call; }

View file

@ -1423,6 +1423,11 @@ OptionString SoundOutputsMac
"No sound", "No sound" "No sound", "No sound"
} }
OptionString ALDevices
{
// filled in by the sound code
}
OptionString OutputFormats OptionString OutputFormats
{ {
"PCM-8", "8-bit" "PCM-8", "8-bit"
@ -1454,26 +1459,30 @@ OptionString Resamplers
"Spline", "Spline" "Spline", "Spline"
} }
OptionValue MidiDevices
OptionString SoundBackends
{ {
// filled in by the sound code "fmod", "FMOD Ex"
"openal", "OpenAL"
"null", "No Sound"
} }
OptionMenu SoundOptions OptionString SoundBackendsFModOnly
{ {
Title "SOUND OPTIONS" "fmod", "FMOD Ex"
Slider "Sounds volume", "snd_sfxvolume", 0, 1, 0.05 "null", "No Sound"
Slider "Menu volume", "snd_menuvolume", 0, 1, 0.05 }
Slider "Music volume", "snd_musicvolume", 0, 1, 0.05
Option "MIDI device", "snd_mididevice", "MidiDevices" OptionString SoundBackendsOpenALOnly
StaticText " " {
Option "Underwater reverb", "snd_waterreverb", "OnOff" "openal", "OpenAL"
Slider "Underwater cutoff", "snd_waterlp", 0, 2000, 50, 0 "null", "No Sound"
Option "Randomize pitches", "snd_pitched", "OnOff" }
Slider "Sound channels", "snd_channels", 8, 256, 8, 0
StaticText " " OptionMenu FMODSoundItems
Command "Restart sound", "snd_reset" {
StaticText " " Title "FMOD OPTIONS"
Slider "Underwater cutoff", "snd_waterlp", 0.0, 2000.0, 50.0, 0
IfOption(Windows) IfOption(Windows)
{ {
Option "Output system", "snd_output", "SoundOutputsWindows" Option "Output system", "snd_output", "SoundOutputsWindows"
@ -1490,6 +1499,67 @@ OptionMenu SoundOptions
Option "Speaker mode", "snd_speakermode", "SpeakerModes" Option "Speaker mode", "snd_speakermode", "SpeakerModes"
Option "Resampler", "snd_resampler", "Resamplers" Option "Resampler", "snd_resampler", "Resamplers"
Option "HRTF filter", "snd_hrtf", "OnOff" Option "HRTF filter", "snd_hrtf", "OnOff"
StaticText " "
Option "Buffer size", "snd_buffersize", "BufferSizes"
Option "Buffer count", "snd_buffercount", "BufferCounts"
}
OptionMenu OpenALSoundItems
{
Title "OPENAL OPTIONS"
Option "Playback device", "snd_aldevice", "ALDevices"
Option "Enable EFX", "snd_efx", "OnOff"
}
OptionValue MidiDevices
{
// filled in by the sound code
}
OptionMenu SoundOptions
{
Title "SOUND OPTIONS"
Slider "Sounds volume", "snd_sfxvolume", 0, 1, 0.05
Slider "Menu volume", "snd_menuvolume", 0, 1, 0.05
Slider "Music volume", "snd_musicvolume", 0, 1, 0.05
Option "MIDI device", "snd_mididevice", "MidiDevices"
StaticText " "
Option "Underwater reverb", "snd_waterreverb", "OnOff"
Option "Randomize pitches", "snd_pitched", "OnOff"
Slider "Sound channels", "snd_channels", 8, 256, 8, 0
StaticText " "
ifoption(fmodex)
{
ifoption(openal)
{
Option "Sound backend", "snd_backend", "SoundBackends"
}
else
{
Option "Sound backend", "snd_backend", "SoundBackendsFModOnly"
}
}
else
{
ifoption(openal)
{
Option "Sound backend", "snd_backend", "SoundBackendsOpenALOnly"
}
}
ifoption(fmodex)
{
Submenu "FMOD options", "FMODSoundItems"
}
ifoption(openal)
{
Submenu "OpenAL options", "OpenALSoundItems"
}
StaticText " "
Command "Restart sound", "snd_reset"
StaticText " " StaticText " "
Submenu "Advanced options", "AdvSoundOptions" Submenu "Advanced options", "AdvSoundOptions"
@ -1523,8 +1593,6 @@ OptionMenu AdvSoundOptions
{ {
Title "ADVANCED SOUND OPTIONS" Title "ADVANCED SOUND OPTIONS"
Option "Sample rate", "snd_samplerate", "SampleRates" Option "Sample rate", "snd_samplerate", "SampleRates"
Option "Buffer size", "snd_buffersize", "BufferSizes"
Option "Buffer count", "snd_buffercount", "BufferCounts"
StaticText " " StaticText " "
StaticText "OPL Synthesis", 1 StaticText "OPL Synthesis", 1
Slider "Number of emulated OPL chips", "opl_numchips", 1, 8, 1, 0 Slider "Number of emulated OPL chips", "opl_numchips", 1, 8, 1, 0
@ -1546,7 +1614,7 @@ OptionMenu AdvSoundOptions
OptionValue ModReplayers OptionValue ModReplayers
{ {
0.0, "FMOD" 0.0, "Sound System"
1.0, "foo_dumb" 1.0, "foo_dumb"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 297 B

View file

@ -57,7 +57,7 @@
OmitFramePointers="true" OmitFramePointers="true"
WholeProgramOptimization="false" WholeProgramOptimization="false"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;&quot;game-music-emu&quot;;gdtoa;bzip2;lzma\C" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;&quot;game-music-emu&quot;;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH,HAVE_FLUIDSYNTH,DYN_FLUIDSYNTH" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH,HAVE_FLUIDSYNTH,DYN_FLUIDSYNTH,NO_OPENAL"
StringPooling="true" StringPooling="true"
ExceptionHandling="1" ExceptionHandling="1"
RuntimeLibrary="0" RuntimeLibrary="0"
@ -180,7 +180,7 @@
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
OmitFramePointers="true" OmitFramePointers="true"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;game-music-emu;gdtoa;bzip2;lzma\C" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;game-music-emu;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,NO_OPENAL"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
EnableFunctionLevelLinking="false" EnableFunctionLevelLinking="false"
@ -290,7 +290,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;&quot;game-music-emu&quot;;gdtoa;bzip2;lzma\C" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;&quot;game-music-emu&quot;;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH,HAVE_FLUIDSYNTH,DYN_FLUIDSYNTH" PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH,HAVE_FLUIDSYNTH,DYN_FLUIDSYNTH,NO_OPENAL"
MinimalRebuild="true" MinimalRebuild="true"
RuntimeLibrary="1" RuntimeLibrary="1"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
@ -398,7 +398,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;game-music-emu;gdtoa;bzip2;lzma\C" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;&quot;jpeg-6b&quot;;game-music-emu;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY" PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,NO_OPENAL"
MinimalRebuild="true" MinimalRebuild="true"
RuntimeLibrary="1" RuntimeLibrary="1"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
@ -2481,6 +2481,10 @@
<Filter <Filter
Name="Audio Files" Name="Audio Files"
> >
<File
RelativePath=".\src\sound\efx.h"
>
</File>
<File <File
RelativePath=".\src\sound\fmod_wrap.h" RelativePath=".\src\sound\fmod_wrap.h"
> >
@ -2593,6 +2597,14 @@
RelativePath=".\src\sound\music_xmi_midiout.cpp" RelativePath=".\src\sound\music_xmi_midiout.cpp"
> >
</File> </File>
<File
RelativePath=".\src\sound\oalsound.cpp"
>
</File>
<File
RelativePath=".\src\sound\oalsound.h"
>
</File>
<Filter <Filter
Name="OPL Synth" Name="OPL Synth"
> >