diff --git a/CMakeLists.txt b/CMakeLists.txt index e96249ff3..f426119c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,7 +150,6 @@ endif() 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 ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54dce36ca..d303102b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,56 +34,6 @@ if( CMAKE_SIZEOF_VOID_P MATCHES "8" ) set( X64 64 ) endif() -# You can either use "make install" on the FMOD distribution to put it -# in standard system locations, or you can unpack the FMOD distribution -# in the root of the zdoom tree. e.g.: -# zdoom -# docs -# fmodapilinux[64] -or simply- fmod -# jpeg-6b -# ... -# The recommended method is to put it in the zdoom tree, since its -# headers are unversioned. Especially now that we can't work properly -# with anything newer than 4.26.xx, you probably don't want to use -# a system-wide version. - -# Construct version numbers for searching for the FMOD library on Linux. -set( MINOR_VERSIONS "61" "50" "49" "48" "47" "46" "45" "44" "43" "42" "41" - "40" "39" "38" "37" "36" "35" "34" "33" "32" "31" "30" "29" "28" - "27" "26" "25" "24" "23" "22" "21" "20" "21" "19" "18" "17" "16" - "15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03" - "02" "01" "00" ) -set( MAJOR_VERSIONS "44" "34" "28" "26" "24" "22" "20" ) - -if( NOT FMOD_DIR_VERSIONS ) - set( FMOD_DIR_VERSIONS "" ) -endif() -if( NOT FMOD_VERSIONS ) - set( FMOD_VERSIONS "" ) -endif() -if( NOT FMOD_LOCAL_INC_DIRS ) - set( FMOD_LOCAL_INC_DIRS "" ) -endif() -if( NOT FMOD_LOCAL_LIB_DIRS ) - set( FMOD_LOCAL_LIB_DIRS "" ) -endif() - -set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" ) -foreach( majver ${MAJOR_VERSIONS} ) - foreach( minver ${MINOR_VERSIONS} ) - set( FMOD_VERSIONS ${FMOD_VERSIONS} "fmodex${X64}-4.${majver}.${minver}" ) - # FMOD Ex version 4.44 unified 32-bit and 64-bit linux packages into one. - if( NOT majver EQUAL "44" ) - set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "${CMAKE_HOME_DIRECTORY}/fmodapi4${majver}${minver}linux${X64}" ) - else() - set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "${CMAKE_HOME_DIRECTORY}/fmodapi4${majver}${minver}linux" ) - endif() - endforeach() - foreach( dir ${FMOD_DIR_VERSIONS} ) - set( FMOD_LOCAL_INC_DIRS ${FMOD_LOCAL_INC_DIRS} "${dir}/api/inc" ) - set( FMOD_LOCAL_LIB_DIRS ${FMOD_LOCAL_LIB_DIRS} "${dir}/api/lib" ) - endforeach() -endforeach() if( NOT ZDOOM_LIBS ) set( ZDOOM_LIBS "" ) @@ -100,15 +50,9 @@ if( WIN32 ) add_definitions( -D_WIN32 ) - set( FMOD_SEARCH_PATHS - "C:/Program Files/FMOD SoundSystem/FMOD Programmers API ${WIN_TYPE}/api" - "C:/Program Files (x86)/FMOD SoundSystem/FMOD Programmers API ${WIN_TYPE}/api" - ) - set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES inc ) - set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib ) if( ( MSVC14 AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" ) OR # For VS 2015. - ( MSVC15 AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v150_xp" ) ) # For VS 2017. + ( MSVC15 AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v141_xp" ) ) # For VS 2017. # for modern Windows SDKs the DirectX headers should be available by default. set( DX_dinput8_LIBRARY dinput8 ) set( DX_dxguid_LIBRARY dxguid ) @@ -189,9 +133,6 @@ if( WIN32 ) endif() else() if( APPLE ) - set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) - set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES inc ) - set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib ) set( NO_GTK ON ) set( DYN_GTK OFF ) @@ -204,17 +145,6 @@ else() option( NO_GTK "Disable GTK+ dialogs (Not applicable to Windows)" ) option( DYN_GTK "Load GTK+ at runtime instead of compile time" ON ) - set( FMOD_SEARCH_PATHS - /usr/local/include - /usr/local/include/fmodex - /usr/include - /usr/include/fmodex - /opt/local/include - /opt/local/include/fmodex - /opt/include - /opt/include/fmodex ) - set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES fmodex ) - # Use GTK+ for the IWAD picker, if available. if( NOT NO_GTK ) pkg_check_modules( GTK3 gtk+-3.0 ) @@ -281,82 +211,6 @@ if( NOT NO_OPENAL ) endif() endif() -if( NOT NO_FMOD ) - # Search for FMOD include files - if( NOT WIN32 ) - find_path( FMOD_INCLUDE_DIR fmod.hpp - PATHS ${FMOD_LOCAL_INC_DIRS} ) - endif() - - if( NOT FMOD_INCLUDE_DIR ) - find_path( FMOD_INCLUDE_DIR fmod.hpp - PATHS ${FMOD_SEARCH_PATHS} - ${FMOD_INC_PATH_SUFFIXES} ) - endif() - - if( FMOD_INCLUDE_DIR ) - message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" ) - include_directories( "${FMOD_INCLUDE_DIR}" ) - - if( EXISTS "${FMOD_INCLUDE_DIR}/fmod_common.h" ) - set( FMOD_STUDIO YES ) - set( FMOD_VERSION_FILE "fmod_common.h" ) - else() - set( FMOD_STUDIO NO ) - set( FMOD_VERSION_FILE "fmod.h" ) - endif() - - file( STRINGS "${FMOD_INCLUDE_DIR}/${FMOD_VERSION_FILE}" FMOD_VERSION_LINE REGEX "^#define[ \t]+FMOD_VERSION[ \t]+0x[0-9]+$" ) - string( REGEX REPLACE "^#define[ \t]+FMOD_VERSION[ \t]+0x([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])$" "\\1.\\2.\\3" FMOD_VERSION "${FMOD_VERSION_LINE}" ) - message( STATUS "FMOD version: ${FMOD_VERSION}" ) - - # FMOD Ex didn't hide xiph symbols in the past (not applicable to Win32 since symbols are hidden by default there). - if( NOT WIN32 AND NOT FMOD_STUDIO AND NOT NO_OPENAL AND "${FMOD_VERSION}" VERSION_LESS "4.36.00") - message( SEND_ERROR "Use of FMOD Ex ${FMOD_VERSION} with OpenAL will result in crashes. Either update FMOD to 4.36 or later or set NO_OPENAL." ) - endif() - else() - message( STATUS "Could not find FMOD include files" ) - set( NO_FMOD ON ) - endif() -endif() - -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() - - if( NOT FMOD_LIB_NAME AND BORLAND ) - set( FMOD_LIB_NAME fmodex${X64}_bc ) - endif() - - if( NOT FMOD_LIB_NAME ) - set( FMOD_LIB_NAME fmodex${X64} ) - endif() - - # Search for FMOD library - if( WIN32 OR APPLE ) - find_library( FMOD_LIBRARY ${FMOD_LIB_NAME} - PATHS ${FMOD_SEARCH_PATHS} - ${FMOD_LIB_PATH_SUFFIXES} ) - else() - find_library( FMOD_LIBRARY - NAMES ${FMOD_VERSIONS} - PATHS ${FMOD_LOCAL_LIB_DIRS} ) - endif() - - if( FMOD_LIBRARY ) - message( STATUS "FMOD library found at ${FMOD_LIBRARY}" ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FMOD_LIBRARY}" ) - else() - message( STATUS "Could not find FMOD library" ) - set( NO_FMOD ON ) - endif() -endif() - -if( NO_FMOD ) - add_definitions( -DNO_FMOD=1 ) -endif() if( NO_OPENAL ) add_definitions( -DNO_OPENAL=1 ) @@ -683,10 +537,9 @@ elseif( APPLE ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} ${PLAT_UNIX_SOURCES} ) endif() - set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_OSX_SOURCES} "${FMOD_LIBRARY}" ) + set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_OSX_SOURCES} ) set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) - set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks ) set_source_files_properties( posix/osx/iwadpicker_cocoa.mm PROPERTIES COMPILE_FLAGS -fobjc-exceptions ) else() set( SYSTEM_SOURCES_DIR posix posix/sdl ) @@ -901,7 +754,6 @@ set( FASTMATH_SOURCES swrenderer/r_all.cpp polyrenderer/poly_all.cpp sound/oplsynth/opl_mus_player.cpp - sound/fmodsound.cpp sound/mpg123_decoder.cpp sound/music_midi_base.cpp sound/oalsound.cpp @@ -1372,14 +1224,6 @@ if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) set( LINKERSTUFF "/MANIFEST:NO" ) - if( NOT NO_FMOD ) - if( FMOD_STUDIO ) - set( LINKERSTUFF "${LINKERSTUFF} /DELAYLOAD:\"fmod${X64}.dll\"" ) - else() - set( LINKERSTUFF "${LINKERSTUFF} /DELAYLOAD:\"fmodex${X64}.dll\"" ) - endif() - endif() - if( ZDOOM_GENERATE_MAPFILE ) set( LINKERSTUFF "${LINKERSTUFF} /MAP" ) endif() @@ -1418,26 +1262,6 @@ if( APPLE ) LINK_FLAGS "-framework AudioToolbox -framework AudioUnit -framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" ) - if( NOT NO_FMOD ) - if( FMOD_STUDIO ) - set( FMOD_DYLIB libfmod.dylib ) - else() - set( FMOD_DYLIB libfmodex.dylib ) - endif() - - # Fix fmod link so that it can be found in the app bundle. - find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) - find_program( INSTALL_NAME_TOOL install_name_tool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) - execute_process( COMMAND "${OTOOL}" -L "${FMOD_LIBRARY}" - COMMAND grep "${FMOD_DYLIB} (compat" - COMMAND head -n1 - COMMAND awk "{print $1}" - OUTPUT_VARIABLE FMOD_LINK - OUTPUT_STRIP_TRAILING_WHITESPACE ) - add_custom_command( TARGET zdoom POST_BUILD - COMMAND "${INSTALL_NAME_TOOL}" -change "${FMOD_LINK}" @executable_path/../Frameworks/${FMOD_DYLIB} "$" - COMMENT "Relinking FMOD Ex" ) - endif() endif() if( WIN32 ) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index a14ac25b3..d3a2ee49f 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -247,10 +247,6 @@ static bool CheckSkipOptionBlock(FScanner &sc) { filter |= IsOpenALPresent(); } - else if (sc.Compare("FModEx")) - { - filter |= IsFModExPresent(); - } } while (sc.CheckString(",")); sc.MustGetStringName(")"); diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 75f6a68a8..f5fc2ed13 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -140,6 +140,7 @@ CUSTOM_CVAR (Int, snd_channels, 128, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // number o if (self < 64) self = 64; } CVAR (Bool, snd_flipstereo, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR(Bool, snd_waterreverb, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // CODE -------------------------------------------------------------------- diff --git a/src/sound/fmod_wrap.h b/src/sound/fmod_wrap.h deleted file mode 100644 index 02d6a56ae..000000000 --- a/src/sound/fmod_wrap.h +++ /dev/null @@ -1,624 +0,0 @@ - -#ifndef FMOD_WRAP_H -#define FMOD_WRAP_H - -#ifndef NO_FMOD - -#if !defined(_WIN32) || defined(_MSC_VER) -// Use the real C++ interface if it's supported on this platform. -#include "fmod.hpp" -#else -// Use a wrapper C++ interface for non-Microsoft compilers on Windows. - -#include "fmod.h" - -// Create fake definitions for these structs so they can be subclassed. -struct FMOD_SYSTEM {}; -struct FMOD_SOUND {}; -struct FMOD_CHANNEL {}; -struct FMOD_CHANNELGROUP {}; -struct FMOD_SOUNDGROUP {}; -struct FMOD_REVERB {}; -struct FMOD_DSP {}; -struct FMOD_DSPCONNECTION {}; -struct FMOD_POLYGON {}; -struct FMOD_GEOMETRY {}; -struct FMOD_SYNCPOINT {}; -/* - Constant and defines -*/ - -/* - FMOD Namespace -*/ - -namespace FMOD -{ - - class System; - class Sound; - class Channel; - class ChannelGroup; - class SoundGroup; - class Reverb; - class DSP; - class DSPConnection; - class Geometry; - - /* - FMOD global system functions (optional). - */ - inline FMOD_RESULT Memory_Initialize(void *poolmem, int poollen, FMOD_MEMORY_ALLOCCALLBACK useralloc, FMOD_MEMORY_REALLOCCALLBACK userrealloc, FMOD_MEMORY_FREECALLBACK userfree, FMOD_MEMORY_TYPE memtypeflags = (FMOD_MEMORY_NORMAL | FMOD_MEMORY_XBOX360_PHYSICAL)) { return FMOD_Memory_Initialize(poolmem, poollen, useralloc, userrealloc, userfree, memtypeflags); } - //inline FMOD_RESULT Memory_GetStats (int *currentalloced, int *maxalloced) { return FMOD_Memory_GetStats(currentalloced, maxalloced); } - inline FMOD_RESULT Debug_SetLevel(FMOD_DEBUGLEVEL level) { return FMOD_Debug_SetLevel(level); } - inline FMOD_RESULT Debug_GetLevel(FMOD_DEBUGLEVEL *level) { return FMOD_Debug_GetLevel(level); } - inline FMOD_RESULT File_SetDiskBusy(int busy) { return FMOD_File_SetDiskBusy(busy); } - inline FMOD_RESULT File_GetDiskBusy(int *busy) { return FMOD_File_GetDiskBusy(busy); } - - /* - FMOD System factory functions. - */ - inline FMOD_RESULT System_Create(System **system) { return FMOD_System_Create((FMOD_SYSTEM **)system); } - - /* - 'System' API - */ - - class System : FMOD_SYSTEM - { - private: - - System(); /* Constructor made private so user cannot statically instance a System class. - System_Create must be used. */ - public: - - FMOD_RESULT release () { return FMOD_System_Release(this); } - - // Pre-init functions. - FMOD_RESULT setOutput (FMOD_OUTPUTTYPE output) { return FMOD_System_SetOutput(this, output); } - FMOD_RESULT getOutput (FMOD_OUTPUTTYPE *output) { return FMOD_System_GetOutput(this, output); } - FMOD_RESULT getNumDrivers (int *numdrivers) { return FMOD_System_GetNumDrivers(this, numdrivers); } - FMOD_RESULT getDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid) { return FMOD_System_GetDriverInfo(this, id, name, namelen, guid); } - FMOD_RESULT getDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode) { return FMOD_System_GetDriverCaps(this, id, caps, minfrequency, maxfrequency, controlpanelspeakermode); } - FMOD_RESULT setDriver (int driver) { return FMOD_System_SetDriver(this, driver); } - FMOD_RESULT getDriver (int *driver) { return FMOD_System_GetDriver(this, driver); } - FMOD_RESULT setHardwareChannels (int min2d, int max2d, int min3d, int max3d) { return FMOD_System_SetHardwareChannels(this, min2d, max2d, min3d, max3d); } - FMOD_RESULT setSoftwareChannels (int numsoftwarechannels) { return FMOD_System_SetSoftwareChannels(this, numsoftwarechannels); } - FMOD_RESULT getSoftwareChannels (int *numsoftwarechannels) { return FMOD_System_GetSoftwareChannels(this, numsoftwarechannels); } - FMOD_RESULT setSoftwareFormat (int samplerate, FMOD_SOUND_FORMAT format, int numoutputchannels, int maxinputchannels, FMOD_DSP_RESAMPLER resamplemethod) { return FMOD_System_SetSoftwareFormat(this, samplerate, format, numoutputchannels, maxinputchannels, resamplemethod); } - FMOD_RESULT getSoftwareFormat (int *samplerate, FMOD_SOUND_FORMAT *format, int *numoutputchannels, int *maxinputchannels, FMOD_DSP_RESAMPLER *resamplemethod, int *bits) { return FMOD_System_GetSoftwareFormat(this, samplerate, format, numoutputchannels, maxinputchannels, resamplemethod, bits); } - FMOD_RESULT setDSPBufferSize (unsigned int bufferlength, int numbuffers) { return FMOD_System_SetDSPBufferSize(this, bufferlength, numbuffers); } - FMOD_RESULT getDSPBufferSize (unsigned int *bufferlength, int *numbuffers) { return FMOD_System_GetDSPBufferSize(this, bufferlength, numbuffers); } - FMOD_RESULT setFileSystem (FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek, int blockalign) { return FMOD_System_SetFileSystem(this, useropen, userclose, userread, userseek, blockalign); } - FMOD_RESULT attachFileSystem (FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek) { return FMOD_System_AttachFileSystem(this, useropen, userclose, userread, userseek); } - FMOD_RESULT setAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings) { return FMOD_System_SetAdvancedSettings(this, settings); } - FMOD_RESULT getAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings) { return FMOD_System_GetAdvancedSettings(this, settings); } - FMOD_RESULT setSpeakerMode (FMOD_SPEAKERMODE speakermode) { return FMOD_System_SetSpeakerMode(this, speakermode); } - FMOD_RESULT getSpeakerMode (FMOD_SPEAKERMODE *speakermode) { return FMOD_System_GetSpeakerMode(this, speakermode); } - FMOD_RESULT setCallback (FMOD_SYSTEM_CALLBACK callback) { return FMOD_System_SetCallback(this, callback); } - - // Plug-in support - FMOD_RESULT setPluginPath (const char *path) { return FMOD_System_SetPluginPath(this, path); } - FMOD_RESULT loadPlugin (const char *filename, unsigned int *handle, unsigned int priority = 0) { return FMOD_System_LoadPlugin(this, filename, handle, priority); } - FMOD_RESULT unloadPlugin (unsigned int handle) { return FMOD_System_UnloadPlugin(this, handle); } - FMOD_RESULT getNumPlugins (FMOD_PLUGINTYPE plugintype, int *numplugins) { return FMOD_System_GetNumPlugins(this, plugintype, numplugins); } - FMOD_RESULT getPluginHandle (FMOD_PLUGINTYPE plugintype, int index, unsigned int *handle) { return FMOD_System_GetPluginHandle(this, plugintype, index, handle); } - FMOD_RESULT getPluginInfo (unsigned int handle, FMOD_PLUGINTYPE *plugintype, char *name, int namelen, unsigned int *version) { return FMOD_System_GetPluginInfo(this, handle, plugintype, name, namelen, version); } - FMOD_RESULT setOutputByPlugin (unsigned int handle) { return FMOD_System_SetOutputByPlugin(this, handle); } - FMOD_RESULT getOutputByPlugin (unsigned int *handle) { return FMOD_System_GetOutputByPlugin(this, handle); } - FMOD_RESULT createCodec (FMOD_CODEC_DESCRIPTION *description, unsigned int priority = 0) { return FMOD_System_CreateCodec(this, description, priority); } - - // Init/Close - FMOD_RESULT init (int maxchannels, FMOD_INITFLAGS flags, void *extradriverdata) { return FMOD_System_Init(this, maxchannels, flags, extradriverdata); } - FMOD_RESULT close () { return FMOD_System_Close(this); } - - // General post-init system functions - FMOD_RESULT update () /* IMPORTANT! CALL THIS ONCE PER FRAME! */ { return FMOD_System_Update(this); } - - FMOD_RESULT set3DSettings (float dopplerscale, float distancefactor, float rolloffscale) { return FMOD_System_Set3DSettings(this, dopplerscale, distancefactor, rolloffscale); } - FMOD_RESULT get3DSettings (float *dopplerscale, float *distancefactor, float *rolloffscale) { return FMOD_System_Get3DSettings(this, dopplerscale, distancefactor, rolloffscale); } - FMOD_RESULT set3DNumListeners (int numlisteners) { return FMOD_System_Set3DNumListeners(this, numlisteners); } - FMOD_RESULT get3DNumListeners (int *numlisteners) { return FMOD_System_Get3DNumListeners(this, numlisteners); } - FMOD_RESULT set3DListenerAttributes(int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up) { return FMOD_System_Set3DListenerAttributes(this, listener, pos, vel, forward, up); } - FMOD_RESULT get3DListenerAttributes(int listener, FMOD_VECTOR *pos, FMOD_VECTOR *vel, FMOD_VECTOR *forward, FMOD_VECTOR *up) { return FMOD_System_Get3DListenerAttributes(this, listener, pos, vel, forward, up); } - FMOD_RESULT set3DRolloffCallback (FMOD_3D_ROLLOFFCALLBACK callback) { return FMOD_System_Set3DRolloffCallback(this, callback); } - FMOD_RESULT set3DSpeakerPosition (FMOD_SPEAKER speaker, float x, float y, bool active) { return FMOD_System_Set3DSpeakerPosition(this, speaker, x, y, active); } - FMOD_RESULT get3DSpeakerPosition (FMOD_SPEAKER speaker, float *x, float *y, bool *active) { FMOD_BOOL b; FMOD_RESULT res = FMOD_System_Get3DSpeakerPosition(this, speaker, x, y, &b); *active = b; return res; } - - FMOD_RESULT setStreamBufferSize (unsigned int filebuffersize, FMOD_TIMEUNIT filebuffersizetype) { return FMOD_System_SetStreamBufferSize(this, filebuffersize, filebuffersizetype); } - FMOD_RESULT getStreamBufferSize (unsigned int *filebuffersize, FMOD_TIMEUNIT *filebuffersizetype) { return FMOD_System_GetStreamBufferSize(this, filebuffersize, filebuffersizetype); } - - // System information functions. - FMOD_RESULT getVersion (unsigned int *version) { return FMOD_System_GetVersion(this, version); } - FMOD_RESULT getOutputHandle (void **handle) { return FMOD_System_GetOutputHandle(this, handle); } - FMOD_RESULT getChannelsPlaying (int *channels) { return FMOD_System_GetChannelsPlaying(this, channels); } - FMOD_RESULT getHardwareChannels (int *num2d, int *num3d, int *total) { return FMOD_System_GetHardwareChannels(this, num2d, num3d, total); } -#if FMOD_VERSION < 0x42501 - FMOD_RESULT getCPUUsage (float *dsp, float *stream, float *update, float *total) { return FMOD_System_GetCPUUsage(this, dsp, stream, update, total); } -#else - FMOD_RESULT getCPUUsage (float *dsp, float *stream, float *geometry, float *update, float *total) { return FMOD_System_GetCPUUsage(this, dsp, stream, geometry, update, total); } -#endif - FMOD_RESULT getSoundRAM (int *currentalloced, int *maxalloced, int *total) { return FMOD_System_GetSoundRAM(this, currentalloced, maxalloced, total); } - FMOD_RESULT getNumCDROMDrives (int *numdrives) { return FMOD_System_GetNumCDROMDrives(this, numdrives); } - FMOD_RESULT getCDROMDriveName (int drive, char *drivename, int drivenamelen, char *scsiname, int scsinamelen, char *devicename, int devicenamelen) { return FMOD_System_GetCDROMDriveName(this, drive, drivename, drivenamelen, scsiname, scsinamelen, devicename, devicenamelen); } - FMOD_RESULT getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype) { return FMOD_System_GetSpectrum(this, spectrumarray, numvalues, channeloffset, windowtype); } - FMOD_RESULT getWaveData (float *wavearray, int numvalues, int channeloffset) { return FMOD_System_GetWaveData(this, wavearray, numvalues, channeloffset); } - - // Sound/DSP/Channel/FX creation and retrieval. - FMOD_RESULT createSound (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound) { return FMOD_System_CreateSound(this, name_or_data, mode, exinfo, (FMOD_SOUND **)sound); } - FMOD_RESULT createStream (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound) { return FMOD_System_CreateStream(this, name_or_data, mode, exinfo, (FMOD_SOUND **)sound); } - FMOD_RESULT createDSP (FMOD_DSP_DESCRIPTION *description, DSP **dsp) { return FMOD_System_CreateDSP(this, description, (FMOD_DSP **)dsp); } - FMOD_RESULT createDSPByType (FMOD_DSP_TYPE type, DSP **dsp) { return FMOD_System_CreateDSPByType(this, type, (FMOD_DSP **)dsp); } - FMOD_RESULT createChannelGroup (const char *name, ChannelGroup **channelgroup) { return FMOD_System_CreateChannelGroup(this, name, (FMOD_CHANNELGROUP **)channelgroup); } - FMOD_RESULT createSoundGroup (const char *name, SoundGroup **soundgroup) { return FMOD_System_CreateSoundGroup(this, name, (FMOD_SOUNDGROUP **)soundgroup); } - FMOD_RESULT createReverb (Reverb **reverb) { return FMOD_System_CreateReverb(this, (FMOD_REVERB **)reverb); } - - FMOD_RESULT playSound (FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel) { return FMOD_System_PlaySound(this, channelid, (FMOD_SOUND *)sound, paused, (FMOD_CHANNEL **)channel); } - FMOD_RESULT playDSP (FMOD_CHANNELINDEX channelid, DSP *dsp, bool paused, Channel **channel) { return FMOD_System_PlayDSP(this, channelid, (FMOD_DSP *)dsp, paused, (FMOD_CHANNEL **)channel); } - FMOD_RESULT getChannel (int channelid, Channel **channel) { return FMOD_System_GetChannel(this, channelid, (FMOD_CHANNEL **)channel); } - FMOD_RESULT getMasterChannelGroup (ChannelGroup **channelgroup) { return FMOD_System_GetMasterChannelGroup(this, (FMOD_CHANNELGROUP **)channelgroup); } - FMOD_RESULT getMasterSoundGroup (SoundGroup **soundgroup) { return FMOD_System_GetMasterSoundGroup(this, (FMOD_SOUNDGROUP **)soundgroup); } - - // Reverb API - FMOD_RESULT setReverbProperties (const FMOD_REVERB_PROPERTIES *prop) { return FMOD_System_SetReverbProperties(this, prop); } - FMOD_RESULT getReverbProperties (FMOD_REVERB_PROPERTIES *prop) { return FMOD_System_GetReverbProperties(this, prop); } - FMOD_RESULT setReverbAmbientProperties(FMOD_REVERB_PROPERTIES *prop) { return FMOD_System_SetReverbAmbientProperties(this, prop); } - FMOD_RESULT getReverbAmbientProperties(FMOD_REVERB_PROPERTIES *prop) { return FMOD_System_GetReverbAmbientProperties(this, prop); } - - // System level DSP access. - FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_System_GetDSPHead(this, (FMOD_DSP **)dsp); } - FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_System_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION**)dsp); } - FMOD_RESULT lockDSP () { return FMOD_System_LockDSP(this); } - FMOD_RESULT unlockDSP () { return FMOD_System_UnlockDSP(this); } - FMOD_RESULT getDSPClock (unsigned int *hi, unsigned int *lo) { return FMOD_System_GetDSPClock(this, hi, lo); } - - // Recording API. - FMOD_RESULT getRecordNumDrivers (int *numdrivers) { return FMOD_System_GetRecordNumDrivers(this, numdrivers); } - FMOD_RESULT getRecordDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid) { return FMOD_System_GetRecordDriverInfo(this, id, name, namelen, guid); } - FMOD_RESULT getRecordDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency) { return FMOD_System_GetRecordDriverCaps(this, id, caps, minfrequency, maxfrequency); } - FMOD_RESULT getRecordPosition (int id, unsigned int *position) { return FMOD_System_GetRecordPosition(this, id, position); } - - FMOD_RESULT recordStart (int id, Sound *sound, bool loop) { return FMOD_System_RecordStart(this, id, (FMOD_SOUND *)sound, loop); } - FMOD_RESULT recordStop (int id) { return FMOD_System_RecordStop(this, id); } - FMOD_RESULT isRecording (int id, bool *recording) { FMOD_BOOL b; FMOD_RESULT res = FMOD_System_IsRecording(this, id, &b); *recording = b; return res; } - - // Geometry API. - FMOD_RESULT createGeometry (int maxpolygons, int maxvertices, Geometry **geometry) { return FMOD_System_CreateGeometry(this, maxpolygons, maxvertices, (FMOD_GEOMETRY **)geometry); } - FMOD_RESULT setGeometrySettings (float maxworldsize) { return FMOD_System_SetGeometrySettings(this, maxworldsize); } - FMOD_RESULT getGeometrySettings (float *maxworldsize) { return FMOD_System_GetGeometrySettings(this, maxworldsize); } - FMOD_RESULT loadGeometry (const void *data, int datasize, Geometry **geometry) { return FMOD_System_LoadGeometry(this, data, datasize, (FMOD_GEOMETRY **)geometry); } - - // Network functions. - FMOD_RESULT setNetworkProxy (const char *proxy) { return FMOD_System_SetNetworkProxy(this, proxy); } - FMOD_RESULT getNetworkProxy (char *proxy, int proxylen) { return FMOD_System_GetNetworkProxy(this, proxy, proxylen); } - FMOD_RESULT setNetworkTimeout (int timeout) { return FMOD_System_SetNetworkTimeout(this, timeout); } - FMOD_RESULT getNetworkTimeout (int *timeout) { return FMOD_System_GetNetworkTimeout(this, timeout); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_System_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_System_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_System_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - /* - 'Sound' API - */ - class Sound : FMOD_SOUND - { - private: - - Sound(); /* Constructor made private so user cannot statically instance a Sound class. - Appropriate Sound creation or retrieval function must be used. */ - public: - - FMOD_RESULT release () { return FMOD_Sound_Release(this); } - FMOD_RESULT getSystemObject (System **system) { return FMOD_Sound_GetSystemObject(this, (FMOD_SYSTEM **)system); } - - // Standard sound manipulation functions. - FMOD_RESULT lock (unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2) { return FMOD_Sound_Lock(this, offset, length, ptr1, ptr2, len1, len2); } - FMOD_RESULT unlock (void *ptr1, void *ptr2, unsigned int len1, unsigned int len2) { return FMOD_Sound_Unlock(this, ptr1, ptr2, len1, len2); } - FMOD_RESULT setDefaults (float frequency, float volume, float pan, int priority) { return FMOD_Sound_SetDefaults(this, frequency, volume, pan, priority); } - FMOD_RESULT getDefaults (float *frequency, float *volume, float *pan, int *priority) { return FMOD_Sound_GetDefaults(this, frequency, volume, pan, priority); } - FMOD_RESULT setVariations (float frequencyvar, float volumevar, float panvar) { return FMOD_Sound_SetVariations(this, frequencyvar, volumevar, panvar); } - FMOD_RESULT getVariations (float *frequencyvar, float *volumevar, float *panvar) { return FMOD_Sound_GetVariations(this, frequencyvar, volumevar, panvar); } - FMOD_RESULT set3DMinMaxDistance (float min, float max) { return FMOD_Sound_Set3DMinMaxDistance(this, min, max); } - FMOD_RESULT get3DMinMaxDistance (float *min, float *max) { return FMOD_Sound_Get3DMinMaxDistance(this, min, max); } - FMOD_RESULT set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume) { return FMOD_Sound_Set3DConeSettings(this, insideconeangle, outsideconeangle, outsidevolume); } - FMOD_RESULT get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume) { return FMOD_Sound_Get3DConeSettings(this, insideconeangle, outsideconeangle, outsidevolume); } - FMOD_RESULT set3DCustomRolloff (FMOD_VECTOR *points, int numpoints) { return FMOD_Sound_Set3DCustomRolloff(this, points, numpoints); } - FMOD_RESULT get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints) { return FMOD_Sound_Get3DCustomRolloff(this, points, numpoints); } - FMOD_RESULT setSubSound (int index, Sound *subsound) { return FMOD_Sound_SetSubSound(this, index, subsound); } - FMOD_RESULT getSubSound (int index, Sound **subsound) { return FMOD_Sound_GetSubSound(this, index, (FMOD_SOUND **)subsound); } - FMOD_RESULT setSubSoundSentence (int *subsoundlist, int numsubsounds) { return FMOD_Sound_SetSubSoundSentence(this, subsoundlist, numsubsounds); } - FMOD_RESULT getName (char *name, int namelen) { return FMOD_Sound_GetName(this, name, namelen); } - FMOD_RESULT getLength (unsigned int *length, FMOD_TIMEUNIT lengthtype) { return FMOD_Sound_GetLength(this, length, lengthtype); } - FMOD_RESULT getFormat (FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits) { return FMOD_Sound_GetFormat(this, type, format, channels, bits); } - FMOD_RESULT getNumSubSounds (int *numsubsounds) { return FMOD_Sound_GetNumSubSounds(this, numsubsounds); } - FMOD_RESULT getNumTags (int *numtags, int *numtagsupdated) { return FMOD_Sound_GetNumTags(this, numtags, numtagsupdated); } - FMOD_RESULT getTag (const char *name, int index, FMOD_TAG *tag) { return FMOD_Sound_GetTag(this, name, index, tag); } - FMOD_RESULT getOpenState (FMOD_OPENSTATE *openstate, unsigned int *percentbuffered, bool *starving) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Sound_GetOpenState(this, openstate, percentbuffered, &b); *starving = b; return res; } - FMOD_RESULT readData (void *buffer, unsigned int lenbytes, unsigned int *read) { return FMOD_Sound_ReadData(this, buffer, lenbytes, read); } - FMOD_RESULT seekData (unsigned int pcm) { return FMOD_Sound_SeekData(this, pcm); } - - FMOD_RESULT setSoundGroup (SoundGroup *soundgroup) { return FMOD_Sound_SetSoundGroup(this, (FMOD_SOUNDGROUP *)soundgroup); } - FMOD_RESULT getSoundGroup (SoundGroup **soundgroup) { return FMOD_Sound_GetSoundGroup(this, (FMOD_SOUNDGROUP **)soundgroup); } - - // Synchronization point API. These points can come from markers embedded in wav files, and can also generate channel callbacks. - FMOD_RESULT getNumSyncPoints (int *numsyncpoints) { return FMOD_Sound_GetNumSyncPoints(this, numsyncpoints); } - FMOD_RESULT getSyncPoint (int index, FMOD_SYNCPOINT **point) { return FMOD_Sound_GetSyncPoint(this, index, point); } - FMOD_RESULT getSyncPointInfo (FMOD_SYNCPOINT *point, char *name, int namelen, unsigned int *offset, FMOD_TIMEUNIT offsettype) { return FMOD_Sound_GetSyncPointInfo(this, point, name, namelen, offset, offsettype); } - FMOD_RESULT addSyncPoint (unsigned int offset, FMOD_TIMEUNIT offsettype, const char *name, FMOD_SYNCPOINT **point) { return FMOD_Sound_AddSyncPoint(this, offset, offsettype, name, point); } - FMOD_RESULT deleteSyncPoint (FMOD_SYNCPOINT *point) { return FMOD_Sound_DeleteSyncPoint(this, point); } - - // Functions also in Channel class but here they are the 'default' to save having to change it in Channel all the time. - FMOD_RESULT setMode (FMOD_MODE mode) { return FMOD_Sound_SetMode(this, mode); } - FMOD_RESULT getMode (FMOD_MODE *mode) { return FMOD_Sound_GetMode(this, mode); } - FMOD_RESULT setLoopCount (int loopcount) { return FMOD_Sound_SetLoopCount(this, loopcount); } - FMOD_RESULT getLoopCount (int *loopcount) { return FMOD_Sound_GetLoopCount(this, loopcount); } - FMOD_RESULT setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype) { return FMOD_Sound_SetLoopPoints(this, loopstart, loopstarttype, loopend, loopendtype); } - FMOD_RESULT getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype) { return FMOD_Sound_GetLoopPoints(this, loopstart, loopstarttype, loopend, loopendtype); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_Sound_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_Sound_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_Sound_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - /* - 'Channel' API. - */ - class Channel : FMOD_CHANNEL - { - private: - - Channel(); /* Constructor made private so user cannot statically instance a Channel class. - Appropriate Channel creation or retrieval function must be used. */ - public: - - FMOD_RESULT getSystemObject (System **system) { return FMOD_Channel_GetSystemObject(this, (FMOD_SYSTEM **)system); } - - FMOD_RESULT stop () { return FMOD_Channel_Stop(this); } - FMOD_RESULT setPaused (bool paused) { return FMOD_Channel_SetPaused(this, paused); } - FMOD_RESULT getPaused (bool *paused) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_GetPaused(this, &b); *paused = b; return res; } - FMOD_RESULT setVolume (float volume) { return FMOD_Channel_SetVolume(this, volume); } - FMOD_RESULT getVolume (float *volume) { return FMOD_Channel_GetVolume(this, volume); } - FMOD_RESULT setFrequency (float frequency) { return FMOD_Channel_SetFrequency(this, frequency); } - FMOD_RESULT getFrequency (float *frequency) { return FMOD_Channel_GetFrequency(this, frequency); } - FMOD_RESULT setPan (float pan) { return FMOD_Channel_SetPan(this, pan); } - FMOD_RESULT getPan (float *pan) { return FMOD_Channel_GetPan(this, pan); } - FMOD_RESULT setDelay (FMOD_DELAYTYPE delaytype, unsigned int delayhi, unsigned int delaylo) { return FMOD_Channel_SetDelay(this, delaytype, delayhi, delaylo); } - FMOD_RESULT getDelay (FMOD_DELAYTYPE delaytype, unsigned int *delayhi, unsigned int *delaylo) { return FMOD_Channel_GetDelay(this, delaytype, delayhi, delaylo); } - FMOD_RESULT setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright) { return FMOD_Channel_SetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); } - FMOD_RESULT getSpeakerMix (float *frontleft, float *frontright, float *center, float *lfe, float *backleft, float *backright, float *sideleft, float *sideright) { return FMOD_Channel_GetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); } - FMOD_RESULT setSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_Channel_SetSpeakerLevels(this, speaker, levels, numlevels); } - FMOD_RESULT getSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_Channel_GetSpeakerLevels(this, speaker, levels, numlevels); } - FMOD_RESULT setInputChannelMix (float *levels, int numlevels) { return FMOD_Channel_SetInputChannelMix(this, levels, numlevels); } - FMOD_RESULT getInputChannelMix (float *levels, int numlevels) { return FMOD_Channel_GetInputChannelMix(this, levels, numlevels); } - FMOD_RESULT setMute (bool mute) { return FMOD_Channel_SetMute(this, mute); } - FMOD_RESULT getMute (bool *mute) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_GetMute(this, &b); *mute = b; return res; } - FMOD_RESULT setPriority (int priority) { return FMOD_Channel_SetPriority(this, priority); } - FMOD_RESULT getPriority (int *priority) { return FMOD_Channel_GetPriority(this, priority); } - FMOD_RESULT setPosition (unsigned int position, FMOD_TIMEUNIT postype) { return FMOD_Channel_SetPosition(this, position, postype); } - FMOD_RESULT getPosition (unsigned int *position, FMOD_TIMEUNIT postype) { return FMOD_Channel_GetPosition(this, position, postype); } - FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop) { return FMOD_Channel_SetReverbProperties(this, prop); } - FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop) { return FMOD_Channel_GetReverbProperties(this, prop); } - - FMOD_RESULT setChannelGroup (ChannelGroup *channelgroup) { return FMOD_Channel_SetChannelGroup(this, (FMOD_CHANNELGROUP *)channelgroup); } - FMOD_RESULT getChannelGroup (ChannelGroup **channelgroup) { return FMOD_Channel_GetChannelGroup(this, (FMOD_CHANNELGROUP **)channelgroup); } - FMOD_RESULT setCallback (FMOD_CHANNEL_CALLBACK callback) { return FMOD_Channel_SetCallback(this, callback); } - FMOD_RESULT setLowPassGain (float gain) { return FMOD_Channel_SetLowPassGain(this, gain); } - FMOD_RESULT getLowPassGain (float *gain) { return FMOD_Channel_GetLowPassGain(this, gain); } - - // 3D functionality. - FMOD_RESULT set3DAttributes (const FMOD_VECTOR *pos, const FMOD_VECTOR *vel) { return FMOD_Channel_Set3DAttributes(this, pos, vel); } - FMOD_RESULT get3DAttributes (FMOD_VECTOR *pos, FMOD_VECTOR *vel) { return FMOD_Channel_Get3DAttributes(this, pos, vel); } - FMOD_RESULT set3DMinMaxDistance (float mindistance, float maxdistance) { return FMOD_Channel_Set3DMinMaxDistance(this, mindistance, maxdistance); } - FMOD_RESULT get3DMinMaxDistance (float *mindistance, float *maxdistance) { return FMOD_Channel_Get3DMinMaxDistance(this, mindistance, maxdistance); } - FMOD_RESULT set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume) { return FMOD_Channel_Set3DConeSettings(this, insideconeangle, outsideconeangle, outsidevolume); } - FMOD_RESULT get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume) { return FMOD_Channel_Get3DConeSettings(this, insideconeangle, outsideconeangle, outsidevolume); } - FMOD_RESULT set3DConeOrientation (FMOD_VECTOR *orientation) { return FMOD_Channel_Set3DConeOrientation(this, orientation); } - FMOD_RESULT get3DConeOrientation (FMOD_VECTOR *orientation) { return FMOD_Channel_Get3DConeOrientation(this, orientation); } - FMOD_RESULT set3DCustomRolloff (FMOD_VECTOR *points, int numpoints) { return FMOD_Channel_Set3DCustomRolloff(this, points, numpoints); } - FMOD_RESULT get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints) { return FMOD_Channel_Get3DCustomRolloff(this, points, numpoints); } - FMOD_RESULT set3DOcclusion (float directocclusion, float reverbocclusion) { return FMOD_Channel_Set3DOcclusion(this, directocclusion, reverbocclusion); } - FMOD_RESULT get3DOcclusion (float *directocclusion, float *reverbocclusion) { return FMOD_Channel_Get3DOcclusion(this, directocclusion, reverbocclusion); } - FMOD_RESULT set3DSpread (float angle) { return FMOD_Channel_Set3DSpread(this, angle); } - FMOD_RESULT get3DSpread (float *angle) { return FMOD_Channel_Get3DSpread(this, angle); } - FMOD_RESULT set3DPanLevel (float level) { return FMOD_Channel_Set3DPanLevel(this, level); } - FMOD_RESULT get3DPanLevel (float *level) { return FMOD_Channel_Get3DPanLevel(this, level); } - FMOD_RESULT set3DDopplerLevel (float level) { return FMOD_Channel_Set3DDopplerLevel(this, level); } - FMOD_RESULT get3DDopplerLevel (float *level) { return FMOD_Channel_Get3DDopplerLevel(this, level); } - - // DSP functionality only for channels playing sounds created with FMOD_SOFTWARE. - FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_Channel_GetDSPHead(this, (FMOD_DSP **)dsp); } - FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_Channel_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); } - - // Information only functions. - FMOD_RESULT isPlaying (bool *isplaying) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_IsPlaying(this, &b); *isplaying = b; return res; } - FMOD_RESULT isVirtual (bool *isvirtual) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_IsVirtual(this, &b); *isvirtual = b; return res; } - FMOD_RESULT getAudibility (float *audibility) { return FMOD_Channel_GetAudibility(this, audibility); } - FMOD_RESULT getCurrentSound (Sound **sound) { return FMOD_Channel_GetCurrentSound(this, (FMOD_SOUND **)sound); } - FMOD_RESULT getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype) { return FMOD_Channel_GetSpectrum(this, spectrumarray, numvalues, channeloffset, windowtype); } - FMOD_RESULT getWaveData (float *wavearray, int numvalues, int channeloffset) { return FMOD_Channel_GetWaveData(this, wavearray, numvalues, channeloffset); } - FMOD_RESULT getIndex (int *index) { return FMOD_Channel_GetIndex(this, index); } - - // Functions also found in Sound class but here they can be set per channel. - FMOD_RESULT setMode (FMOD_MODE mode) { return FMOD_Channel_SetMode(this, mode); } - FMOD_RESULT getMode (FMOD_MODE *mode) { return FMOD_Channel_GetMode(this, mode); } - FMOD_RESULT setLoopCount (int loopcount) { return FMOD_Channel_SetLoopCount(this, loopcount); } - FMOD_RESULT getLoopCount (int *loopcount) { return FMOD_Channel_GetLoopCount(this, loopcount); } - FMOD_RESULT setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype) { return FMOD_Channel_SetLoopPoints(this, loopstart, loopstarttype, loopend, loopendtype); } - FMOD_RESULT getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype) { return FMOD_Channel_GetLoopPoints(this, loopstart, loopstarttype, loopend, loopendtype); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_Channel_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_Channel_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_Channel_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - /* - 'ChannelGroup' API - */ - class ChannelGroup : FMOD_CHANNELGROUP - { - private: - - ChannelGroup(); /* Constructor made private so user cannot statically instance a ChannelGroup class. - Appropriate ChannelGroup creation or retrieval function must be used. */ - public: - - FMOD_RESULT release () { return FMOD_ChannelGroup_Release(this); } - FMOD_RESULT getSystemObject (System **system) { return FMOD_ChannelGroup_GetSystemObject(this, (FMOD_SYSTEM **)system); } - - // Channelgroup scale values. (changes attributes relative to the channels, doesn't overwrite them) - FMOD_RESULT setVolume (float volume) { return FMOD_ChannelGroup_SetVolume(this, volume); } - FMOD_RESULT getVolume (float *volume) { return FMOD_ChannelGroup_GetVolume(this, volume); } - FMOD_RESULT setPitch (float pitch) { return FMOD_ChannelGroup_SetPitch(this, pitch); } - FMOD_RESULT getPitch (float *pitch) { return FMOD_ChannelGroup_GetPitch(this, pitch); } - FMOD_RESULT set3DOcclusion (float directocclusion, float reverbocclusion) { return FMOD_ChannelGroup_Set3DOcclusion(this, directocclusion, reverbocclusion); } - FMOD_RESULT get3DOcclusion (float *directocclusion, float *reverbocclusion) { return FMOD_ChannelGroup_Get3DOcclusion(this, directocclusion, reverbocclusion); } - FMOD_RESULT setPaused (bool paused) { return FMOD_ChannelGroup_SetPaused(this, paused); } - FMOD_RESULT getPaused (bool *paused) { FMOD_BOOL b; FMOD_RESULT res = FMOD_ChannelGroup_GetPaused(this, &b); *paused = b; return res; } - FMOD_RESULT setMute (bool mute) { return FMOD_ChannelGroup_SetMute(this, mute); } - FMOD_RESULT getMute (bool *mute) { FMOD_BOOL b; FMOD_RESULT res = FMOD_ChannelGroup_GetMute(this, &b); *mute = b; return res; } - - // Channelgroup override values. (recursively overwrites whatever settings the channels had) - FMOD_RESULT stop () { return FMOD_ChannelGroup_Stop(this); } - FMOD_RESULT overrideVolume (float volume) { return FMOD_ChannelGroup_OverrideVolume(this, volume); } - FMOD_RESULT overrideFrequency (float frequency) { return FMOD_ChannelGroup_OverrideFrequency(this, frequency); } - FMOD_RESULT overridePan (float pan) { return FMOD_ChannelGroup_OverridePan(this, pan); } - FMOD_RESULT overrideReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop) { return FMOD_ChannelGroup_OverrideReverbProperties(this, prop); } - FMOD_RESULT override3DAttributes (const FMOD_VECTOR *pos, const FMOD_VECTOR *vel) { return FMOD_ChannelGroup_Override3DAttributes(this, pos, vel); } - FMOD_RESULT overrideSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright) { return FMOD_ChannelGroup_OverrideSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); } - - // Nested channel groups. - FMOD_RESULT addGroup (ChannelGroup *group) { return FMOD_ChannelGroup_AddGroup(this, group); } - FMOD_RESULT getNumGroups (int *numgroups) { return FMOD_ChannelGroup_GetNumGroups(this, numgroups); } - FMOD_RESULT getGroup (int index, ChannelGroup **group) { return FMOD_ChannelGroup_GetGroup(this, index, (FMOD_CHANNELGROUP **)group); } - FMOD_RESULT getParentGroup (ChannelGroup **group) { return FMOD_ChannelGroup_GetParentGroup(this, (FMOD_CHANNELGROUP **)group); } - - // DSP functionality only for channel groups playing sounds created with FMOD_SOFTWARE. - FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_ChannelGroup_GetDSPHead(this, (FMOD_DSP **)dsp); } - FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_ChannelGroup_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); } - - // Information only functions. - FMOD_RESULT getName (char *name, int namelen) { return FMOD_ChannelGroup_GetName(this, name, namelen); } - FMOD_RESULT getNumChannels (int *numchannels) { return FMOD_ChannelGroup_GetNumChannels(this, numchannels); } - FMOD_RESULT getChannel (int index, Channel **channel) { return FMOD_ChannelGroup_GetChannel(this, index, (FMOD_CHANNEL **)channel); } - FMOD_RESULT getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype) { return FMOD_ChannelGroup_GetSpectrum(this, spectrumarray, numvalues, channeloffset, windowtype); } - FMOD_RESULT getWaveData (float *wavearray, int numvalues, int channeloffset) { return FMOD_ChannelGroup_GetWaveData(this, wavearray, numvalues, channeloffset) ;} - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_ChannelGroup_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_ChannelGroup_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_ChannelGroup_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - /* - 'SoundGroup' API - */ - class SoundGroup : FMOD_SOUNDGROUP - { - private: - - SoundGroup(); /* Constructor made private so user cannot statically instance a SoundGroup class. - Appropriate SoundGroup creation or retrieval function must be used. */ - public: - - FMOD_RESULT release () { return FMOD_SoundGroup_Release(this); } - FMOD_RESULT getSystemObject (System **system) { return FMOD_SoundGroup_GetSystemObject(this, (FMOD_SYSTEM **)system); } - - // SoundGroup control functions. - FMOD_RESULT setMaxAudible (int maxaudible) { return FMOD_SoundGroup_SetMaxAudible(this, maxaudible); } - FMOD_RESULT getMaxAudible (int *maxaudible) { return FMOD_SoundGroup_GetMaxAudible(this, maxaudible); } - FMOD_RESULT setMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR behavior) { return FMOD_SoundGroup_SetMaxAudibleBehavior(this, behavior); } - FMOD_RESULT getMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR *behavior) { return FMOD_SoundGroup_GetMaxAudibleBehavior(this, behavior); } - FMOD_RESULT setMuteFadeSpeed (float speed) { return FMOD_SoundGroup_SetMuteFadeSpeed(this, speed); } - FMOD_RESULT getMuteFadeSpeed (float *speed) { return FMOD_SoundGroup_GetMuteFadeSpeed(this, speed); } - FMOD_RESULT setVolume (float volume) { return FMOD_SoundGroup_SetVolume(this, volume); } - FMOD_RESULT getVolume (float *volume) { return FMOD_SoundGroup_GetVolume(this, volume); } - FMOD_RESULT stop () { return FMOD_SoundGroup_Stop(this); } - - // Information only functions. - FMOD_RESULT getName (char *name, int namelen) { return FMOD_SoundGroup_GetName(this, name, namelen); } - FMOD_RESULT getNumSounds (int *numsounds) { return FMOD_SoundGroup_GetNumSounds(this, numsounds); } - FMOD_RESULT getSound (int index, Sound **sound) { return FMOD_SoundGroup_GetSound(this, index, (FMOD_SOUND **)sound); } - FMOD_RESULT getNumPlaying (int *numplaying) { return FMOD_SoundGroup_GetNumPlaying(this, numplaying); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_SoundGroup_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_SoundGroup_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_SoundGroup_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - /* - 'DSP' API - */ - class DSP : FMOD_DSP - { - private: - - DSP(); /* Constructor made private so user cannot statically instance a DSP class. - Appropriate DSP creation or retrieval function must be used. */ - public: - - FMOD_RESULT release () { return FMOD_DSP_Release(this); } - FMOD_RESULT getSystemObject (System **system) { return FMOD_DSP_GetSystemObject(this, (FMOD_SYSTEM **)system); } - - // Connection / disconnection / input and output enumeration. - FMOD_RESULT addInput (DSP *target, DSPConnection **connection) { return FMOD_DSP_AddInput(this, target, (FMOD_DSPCONNECTION **)connection); } - FMOD_RESULT disconnectFrom (DSP *target) { return FMOD_DSP_DisconnectFrom(this, target); } - FMOD_RESULT disconnectAll (bool inputs, bool outputs) { return FMOD_DSP_DisconnectAll(this, inputs, outputs); } - FMOD_RESULT remove () { return FMOD_DSP_Remove(this); } - FMOD_RESULT getNumInputs (int *numinputs) { return FMOD_DSP_GetNumInputs(this, numinputs); } - FMOD_RESULT getNumOutputs (int *numoutputs) { return FMOD_DSP_GetNumOutputs(this, numoutputs); } - FMOD_RESULT getInput (int index, DSP **input, DSPConnection **inputconnection) { return FMOD_DSP_GetInput(this, index, (FMOD_DSP **)input, (FMOD_DSPCONNECTION **)inputconnection); } - FMOD_RESULT getOutput (int index, DSP **output, DSPConnection **outputconnection) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output, (FMOD_DSPCONNECTION **)outputconnection); } - - // DSP unit control. - FMOD_RESULT setActive (bool active) { return FMOD_DSP_SetActive(this, active); } - FMOD_RESULT getActive (bool *active) { FMOD_BOOL b; FMOD_RESULT res = FMOD_DSP_GetActive(this, &b); *active = b; return res; } - FMOD_RESULT setBypass (bool bypass) { return FMOD_DSP_SetBypass(this, bypass); } - FMOD_RESULT getBypass (bool *bypass) { FMOD_BOOL b; FMOD_RESULT res = FMOD_DSP_GetBypass(this, &b); *bypass = b; return res; } - FMOD_RESULT setSpeakerActive (FMOD_SPEAKER speaker, bool active) { return FMOD_DSP_SetSpeakerActive(this, speaker, active); } - FMOD_RESULT getSpeakerActive (FMOD_SPEAKER speaker, bool *active) { FMOD_BOOL b; FMOD_RESULT res = FMOD_DSP_GetSpeakerActive(this, speaker, &b); *active = b; return res; } - FMOD_RESULT reset () { return FMOD_DSP_Reset(this); } - - // DSP parameter control. - FMOD_RESULT setParameter (int index, float value) { return FMOD_DSP_SetParameter(this, index, value); } - FMOD_RESULT getParameter (int index, float *value, char *valuestr, int valuestrlen) { return FMOD_DSP_GetParameter(this, index, value, valuestr, valuestrlen); } - FMOD_RESULT getNumParameters (int *numparams) { return FMOD_DSP_GetNumParameters(this, numparams); } - FMOD_RESULT getParameterInfo (int index, char *name, char *label, char *description, int descriptionlen, float *min, float *max) { return FMOD_DSP_GetParameterInfo(this, index, name, label, description, descriptionlen, min, max); } - FMOD_RESULT showConfigDialog (void *hwnd, bool show) { return FMOD_DSP_ShowConfigDialog(this, hwnd, show); } - - // DSP attributes. - FMOD_RESULT getInfo (char *name, unsigned int *version, int *channels, int *configwidth, int *configheight) { return FMOD_DSP_GetInfo(this, name, version, channels, configwidth, configheight); } - FMOD_RESULT getType (FMOD_DSP_TYPE *type) { return FMOD_DSP_GetType(this, type); } - FMOD_RESULT setDefaults (float frequency, float volume, float pan, int priority) { return FMOD_DSP_SetDefaults(this, frequency, volume, pan, priority); } - FMOD_RESULT getDefaults (float *frequency, float *volume, float *pan, int *priority) { return FMOD_DSP_GetDefaults(this, frequency, volume, pan, priority) ;} - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_DSP_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_DSP_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_DSP_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - - /* - 'DSPConnection' API - */ - class DSPConnection : FMOD_DSPCONNECTION - { - private: - - DSPConnection(); /* Constructor made private so user cannot statically instance a DSPConnection class. - Appropriate DSPConnection creation or retrieval function must be used. */ - - public: - - FMOD_RESULT getInput (DSP **input) { return FMOD_DSPConnection_GetInput(this, (FMOD_DSP **)input); } - FMOD_RESULT getOutput (DSP **output) { return FMOD_DSPConnection_GetOutput(this, (FMOD_DSP **)output); } - FMOD_RESULT setMix (float volume) { return FMOD_DSPConnection_SetMix(this, volume); } - FMOD_RESULT getMix (float *volume) { return FMOD_DSPConnection_GetMix(this, volume); } - FMOD_RESULT setLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_SetLevels(this, speaker, levels, numlevels); } - FMOD_RESULT getLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_GetLevels(this, speaker, levels, numlevels); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_DSPConnection_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_DSPConnection_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_DSPConnection_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - - /* - 'Geometry' API - */ - class Geometry : FMOD_GEOMETRY - { - private: - - Geometry(); /* Constructor made private so user cannot statically instance a Geometry class. - Appropriate Geometry creation or retrieval function must be used. */ - - public: - - FMOD_RESULT release () { return FMOD_Geometry_Release(this); } - - // Polygon manipulation. - FMOD_RESULT addPolygon (float directocclusion, float reverbocclusion, bool doublesided, int numvertices, const FMOD_VECTOR *vertices, int *polygonindex) { return FMOD_Geometry_AddPolygon(this, directocclusion, reverbocclusion, doublesided, numvertices, vertices, polygonindex); } - FMOD_RESULT getNumPolygons (int *numpolygons) { return FMOD_Geometry_GetNumPolygons(this, numpolygons); } - FMOD_RESULT getMaxPolygons (int *maxpolygons, int *maxvertices) { return FMOD_Geometry_GetMaxPolygons(this, maxpolygons, maxvertices); } - FMOD_RESULT getPolygonNumVertices (int index, int *numvertices) { return FMOD_Geometry_GetPolygonNumVertices(this, index, numvertices); } - FMOD_RESULT setPolygonVertex (int index, int vertexindex, const FMOD_VECTOR *vertex) { return FMOD_Geometry_SetPolygonVertex(this, index, vertexindex, vertex); } - FMOD_RESULT getPolygonVertex (int index, int vertexindex, FMOD_VECTOR *vertex) { return FMOD_Geometry_GetPolygonVertex(this, index, vertexindex, vertex); } - FMOD_RESULT setPolygonAttributes (int index, float directocclusion, float reverbocclusion, bool doublesided) { return FMOD_Geometry_SetPolygonAttributes(this, index, directocclusion, reverbocclusion, doublesided); } - FMOD_RESULT getPolygonAttributes (int index, float *directocclusion, float *reverbocclusion, bool *doublesided) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Geometry_GetPolygonAttributes(this, index, directocclusion, reverbocclusion, &b); *doublesided = b; return res; } - - // Object manipulation. - FMOD_RESULT setActive (bool active) { return FMOD_Geometry_SetActive(this, active); } - FMOD_RESULT getActive (bool *active) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Geometry_GetActive(this, &b); *active = b; return res; } - FMOD_RESULT setRotation (const FMOD_VECTOR *forward, const FMOD_VECTOR *up) { return FMOD_Geometry_SetRotation(this, forward, up); } - FMOD_RESULT getRotation (FMOD_VECTOR *forward, FMOD_VECTOR *up) { return FMOD_Geometry_GetRotation(this, forward, up); } - FMOD_RESULT setPosition (const FMOD_VECTOR *position) { return FMOD_Geometry_SetPosition(this, position); } - FMOD_RESULT getPosition (FMOD_VECTOR *position) { return FMOD_Geometry_GetPosition(this, position); } - FMOD_RESULT setScale (const FMOD_VECTOR *scale) { return FMOD_Geometry_SetScale(this, scale); } - FMOD_RESULT getScale (FMOD_VECTOR *scale) { return FMOD_Geometry_GetScale(this, scale); } - FMOD_RESULT save (void *data, int *datasize) { return FMOD_Geometry_Save(this, data, datasize); } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_Geometry_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_Geometry_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_Geometry_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; - - - /* - 'Reverb' API - */ - class Reverb : FMOD_REVERB - { - private: - - Reverb(); /* Constructor made private so user cannot statically instance a Reverb class. - Appropriate Reverb creation or retrieval function must be used. */ - - public: - - FMOD_RESULT release () { return FMOD_Reverb_Release(this); } - - // Reverb manipulation. - FMOD_RESULT set3DAttributes (const FMOD_VECTOR *position, float mindistance, float maxdistance) { return FMOD_Reverb_Set3DAttributes(this, position, mindistance, maxdistance); } - FMOD_RESULT get3DAttributes (FMOD_VECTOR *position, float *mindistance, float *maxdistance) { return FMOD_Reverb_Get3DAttributes(this, position, mindistance, maxdistance); } - FMOD_RESULT setProperties (const FMOD_REVERB_PROPERTIES *properties) { return FMOD_Reverb_SetProperties(this, properties); } - FMOD_RESULT getProperties (FMOD_REVERB_PROPERTIES *properties) { return FMOD_Reverb_GetProperties(this, properties); } - FMOD_RESULT setActive (bool active) { return FMOD_Reverb_SetActive(this, active); } - FMOD_RESULT getActive (bool *active) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Reverb_GetActive(this, &b); *active = b; return res; } - - // Userdata set/get. - FMOD_RESULT setUserData (void *userdata) { return FMOD_Reverb_SetUserData(this, userdata); } - FMOD_RESULT getUserData (void **userdata) { return FMOD_Reverb_GetUserData(this, userdata); } - - FMOD_RESULT getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, unsigned int *memoryused_array) { return FMOD_Reverb_GetMemoryInfo(this, memorybits, event_memorybits, memoryused, memoryused_array); } - }; -} - -#endif - -// FMOD Ex vs FMOD Studio -#if FMOD_VERSION >= 0x00040000 && FMOD_VERSION <= 0x0004FFFF -#define FMOD_STUDIO 0 -#else -#define FMOD_STUDIO 1 -#define FMOD_SOFTWARE 0 -#endif - -#endif -#endif diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp deleted file mode 100644 index a5972dceb..000000000 --- a/src/sound/fmodsound.cpp +++ /dev/null @@ -1,3527 +0,0 @@ -/* -** fmodsound.cpp -** System interface for sound; uses FMOD Ex. -** -**--------------------------------------------------------------------------- -** Copyright 1998-2009 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -// HEADER FILES ------------------------------------------------------------ - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -extern HWND Window; -#else -#define FALSE 0 -#define TRUE 1 -#endif -#if defined(__FreeBSD__) || defined(__APPLE__) -#include -#elif __sun -#include -#else -#include -#endif - -#include "except.h" -#include "templates.h" -#include "fmodsound.h" -#include "c_cvars.h" -#include "i_system.h" -#include "i_music.h" -#include "v_text.h" -#include "v_video.h" -#include "v_palette.h" -#include "cmdlib.h" -#include "s_sound.h" -#include "files.h" -#include "i_musicinterns.h" - -#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43400 -#error You are trying to compile with an unsupported version of FMOD. -#endif - -// MACROS ------------------------------------------------------------------ - -// killough 2/21/98: optionally use varying pitched sounds -#define PITCH(freq,pitch) (snd_pitched ? ((freq)*(pitch))/128.f : float(freq)) - -// Just some extra for music and whatever -#define NUM_EXTRA_SOFTWARE_CHANNELS 1 - -#define MAX_CHANNELS 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; - } -} - -CUSTOM_CVAR (Int, snd_streambuffersize, 64, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < 16) - { - self = 16; - } - else if (self > 1024) - { - self = 1024; - } -} - -#ifndef NO_FMOD -#if !FMOD_STUDIO && FMOD_VERSION < 0x43400 -#define FMOD_OPENSTATE_PLAYING FMOD_OPENSTATE_STREAMING -#endif - -#if !FMOD_STUDIO -#define setParameterFloat setParameter -#endif - -// TYPES ------------------------------------------------------------------- - -struct FEnumList -{ - const char *Name; - int Value; -}; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static int Enum_NumForName(const FEnumList *list, const char *name); -static const char *Enum_NameForNum(const FEnumList *list, int num); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -EXTERN_CVAR (String, snd_output) -EXTERN_CVAR (Float, snd_sfxvolume) -EXTERN_CVAR (Float, snd_musicvolume) -EXTERN_CVAR (Int, snd_buffersize) -EXTERN_CVAR (Int, snd_samplerate) -EXTERN_CVAR (Bool, snd_pitched) -EXTERN_CVAR (Int, snd_channels) - -extern int sfx_empty; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static const ReverbContainer *PrevEnvironment; -static bool ShowedBanner; - -// The rolloff callback is called during FMOD::Sound::play, so we need this -// global variable to contain the sound info during that time for the -// callback. -static FRolloffInfo *GRolloff; -static float GDistScale; - -// In the below lists, duplicate entries are for user selection. When -// queried, only the first one for the particular value is shown. -static const FEnumList OutputNames[] = -{ - { "Auto", FMOD_OUTPUTTYPE_AUTODETECT }, - { "Default", FMOD_OUTPUTTYPE_AUTODETECT }, - { "No sound", FMOD_OUTPUTTYPE_NOSOUND }, - - // Windows - { "DirectSound", FMOD_OUTPUTTYPE_DSOUND }, - { "DSound", FMOD_OUTPUTTYPE_DSOUND }, - { "Windows Multimedia", FMOD_OUTPUTTYPE_WINMM }, - { "WinMM", FMOD_OUTPUTTYPE_WINMM }, - { "WaveOut", FMOD_OUTPUTTYPE_WINMM }, - { "WASAPI", FMOD_OUTPUTTYPE_WASAPI }, - { "ASIO", FMOD_OUTPUTTYPE_ASIO }, - -#if FMOD_STUDIO - //Android - - { "OPENSL", FMOD_OUTPUTTYPE_OPENSL }, - { "Android Audio Track", FMOD_OUTPUTTYPE_AUDIOTRACK }, -#endif - - // Linux -#if !FMOD_STUDIO - { "OSS", FMOD_OUTPUTTYPE_OSS }, -#endif - { "ALSA", FMOD_OUTPUTTYPE_ALSA }, -#if !FMOD_STUDIO - { "ESD", FMOD_OUTPUTTYPE_ESD }, -#endif -#if FMOD_STUDIO || FMOD_VERSION >= 0x43400 - { "PulseAudio", FMOD_OUTPUTTYPE_PULSEAUDIO }, - { "Pulse", FMOD_OUTPUTTYPE_PULSEAUDIO }, -#endif -#if !FMOD_STUDIO - { "SDL", 666 }, -#endif - - // Mac - { "Core Audio", FMOD_OUTPUTTYPE_COREAUDIO }, - - { NULL, 0 } -}; - -static const FEnumList SpeakerModeNames[] = -{ - { "Mono", FMOD_SPEAKERMODE_MONO }, - { "Stereo", FMOD_SPEAKERMODE_STEREO }, - { "Quad", FMOD_SPEAKERMODE_QUAD }, - { "Surround", FMOD_SPEAKERMODE_SURROUND }, - { "5.1", FMOD_SPEAKERMODE_5POINT1 }, - { "7.1", FMOD_SPEAKERMODE_7POINT1 }, -#if !FMOD_STUDIO && FMOD_VERSION < 0x44000 - { "Prologic", FMOD_SPEAKERMODE_PROLOGIC }, -#endif - { "1", FMOD_SPEAKERMODE_MONO }, - { "2", FMOD_SPEAKERMODE_STEREO }, - { "4", FMOD_SPEAKERMODE_QUAD }, - { NULL, 0 } -}; - -static const FEnumList ResamplerNames[] = -{ - { "No Interpolation", FMOD_DSP_RESAMPLER_NOINTERP }, - { "NoInterp", FMOD_DSP_RESAMPLER_NOINTERP }, - { "Linear", FMOD_DSP_RESAMPLER_LINEAR }, - // [BL] 64-bit versions of FMOD Ex between 4.24 and 4.26 crash with these resamplers. -#if FMOD_STUDIO || !(defined(_M_X64) || defined(__amd64__)) || !(FMOD_VERSION >= 0x42400 && FMOD_VERSION <= 0x426FF) - { "Cubic", FMOD_DSP_RESAMPLER_CUBIC }, - { "Spline", FMOD_DSP_RESAMPLER_SPLINE }, -#endif - { NULL, 0 } -}; - -static const FEnumList SoundFormatNames[] = -{ - { "None", FMOD_SOUND_FORMAT_NONE }, - { "PCM-8", FMOD_SOUND_FORMAT_PCM8 }, - { "PCM-16", FMOD_SOUND_FORMAT_PCM16 }, - { "PCM-24", FMOD_SOUND_FORMAT_PCM24 }, - { "PCM-32", FMOD_SOUND_FORMAT_PCM32 }, - { "PCM-Float", FMOD_SOUND_FORMAT_PCMFLOAT }, -#if FMOD_STUDIO && FMOD_VERSION < 0x10700 - { "GCADPCM", FMOD_SOUND_FORMAT_GCADPCM }, - { "IMAADPCM", FMOD_SOUND_FORMAT_IMAADPCM }, - { "VAG", FMOD_SOUND_FORMAT_VAG }, - { "XMA", FMOD_SOUND_FORMAT_XMA }, - { "MPEG", FMOD_SOUND_FORMAT_MPEG }, -#endif - { NULL, 0 } -}; - -static const char *OpenStateNames[] = -{ - "Ready", - "Loading", - "Error", - "Connecting", - "Buffering", - "Seeking", - "Streaming" -}; - -const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNames4[4] = { "L", "R", "BL", "BR" }; -const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNamesMore[8] = { "L", "R", "C", "LFE", "BL", "BR", "SL", "SR" }; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// Enum_NumForName -// -// Returns the value of an enum name, or -1 if not found. -// -//========================================================================== - -static int Enum_NumForName(const FEnumList *list, const char *name) -{ - while (list->Name != NULL) - { - if (stricmp(list->Name, name) == 0) - { - return list->Value; - } - list++; - } - return -1; -} - -//========================================================================== -// -// Enum_NameForNum -// -// Returns the name of an enum value. If there is more than one name for a -// value, on the first one in the list is returned. Returns NULL if there -// was no match. -// -//========================================================================== - -static const char *Enum_NameForNum(const FEnumList *list, int num) -{ - while (list->Name != NULL) - { - if (list->Value == num) - { - return list->Name; - } - list++; - } - return NULL; -} - -//========================================================================== -// -// The container for a streaming FMOD::Sound, for playing music. -// -//========================================================================== - -class FMODStreamCapsule : public SoundStream -{ -public: - FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, const char *url) - : Owner(owner), Stream(NULL), Channel(NULL), - UserData(NULL), Callback(NULL), Reader(NULL), URL(url), 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); - } - - FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner) - : Owner(owner), Stream(NULL), Channel(NULL), - UserData(udata), Callback(callback), Reader(NULL), Ended(false) - {} - - ~FMODStreamCapsule() - { - if (Channel != NULL) - { - Channel->stop(); - } - if (Stream != NULL) - { - Stream->release(); - } - if (Reader != NULL) - { - delete Reader; - } - } - - void SetStream(FMOD::Sound *stream) - { - float frequency; - - Stream = stream; - - // As this interface is for music, make it super-high priority. -#if FMOD_STUDIO - if (FMOD_OK == stream->getDefaults(&frequency, NULL)) - stream->setDefaults(frequency, 1); -#else - if (FMOD_OK == stream->getDefaults(&frequency, NULL, NULL, NULL)) - stream->setDefaults(frequency, 1, 0, 0); -#endif - } - - bool Play(bool looping, float volume) - { - FMOD_RESULT result; - - if (URL.IsNotEmpty()) - { // Net streams cannot be looped, because they cannot be seeked. - looping = false; - } - Stream->setMode((looping ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF) | FMOD_SOFTWARE | FMOD_2D); -#if FMOD_STUDIO - result = Owner->Sys->playSound(Stream,0, true, &Channel); -#else - result = Owner->Sys->playSound(FMOD_CHANNEL_FREE, Stream, true, &Channel); -#endif - if (result != FMOD_OK) - { - return false; - } - Channel->setChannelGroup(Owner->MusicGroup); -#if FMOD_STUDIO - Channel->setMixLevelsOutput(1, 1, 1, 1, 1, 1, 1, 1); -#else - Channel->setSpeakerMix(1, 1, 1, 1, 1, 1, 1, 1); -#endif - Channel->setVolume(volume); - // Ensure reverb is disabled. -#if FMOD_STUDIO - Channel->setReverbProperties(0,0.f); -#else - FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, }; - if (FMOD_OK == Channel->getReverbProperties(&reverb)) - { - reverb.Room = -10000; - Channel->setReverbProperties(&reverb); - } -#endif - Channel->setPaused(false); - Ended = false; - JustStarted = true; - Starved = false; - Loop = looping; - Volume = volume; - return true; - } - - void Stop() - { - if (Channel != NULL) - { - Channel->stop(); - Channel = NULL; - } - } - - bool SetPaused(bool paused) - { - if (Channel != NULL) - { - return FMOD_OK == Channel->setPaused(paused); - } - return false; - } - - unsigned int GetPosition() - { - unsigned int pos; - - if (Channel != NULL && FMOD_OK == Channel->getPosition(&pos, FMOD_TIMEUNIT_MS)) - { - return pos; - } - return 0; - } - - bool IsEnded() - { - bool is; - FMOD_OPENSTATE openstate = FMOD_OPENSTATE_MAX; - bool starving; -#if FMOD_STUDIO || FMOD_VERSION >= 0x43400 - bool diskbusy; -#endif - - if (Stream == NULL) - { - return true; - } -#if !FMOD_STUDIO && FMOD_VERSION < 0x43400 - if (FMOD_OK != Stream->getOpenState(&openstate, NULL, &starving)) -#else - if (FMOD_OK != Stream->getOpenState(&openstate, NULL, &starving, &diskbusy)) -#endif - { - openstate = FMOD_OPENSTATE_ERROR; - } - if (openstate == FMOD_OPENSTATE_ERROR) - { - if (Channel != NULL) - { - Channel->stop(); - Channel = NULL; - } - return true; - } - if (Channel != NULL && (FMOD_OK != Channel->isPlaying(&is) || is == false)) - { - return true; - } - if (Ended) - { - Channel->stop(); - Channel = NULL; - return true; - } - if (URL.IsNotEmpty() && !JustStarted && openstate == FMOD_OPENSTATE_READY) - { - // Reconnect the stream, since it seems to have stalled. - // The only way to do this appears to be to completely recreate it. - FMOD_RESULT result; - - Channel->stop(); - Stream->release(); - Channel = NULL; - Stream = NULL; - // Open the stream asynchronously, so we don't hang the game while trying to reconnect. - // (It would be nice to do the initial open asynchronously as well, but I'd need to rethink - // the music system design to pull that off.) - result = Owner->Sys->createSound(URL, (Loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF) | FMOD_SOFTWARE | FMOD_2D | - FMOD_CREATESTREAM | FMOD_NONBLOCKING, NULL, &Stream); - JustStarted = true; - return result != FMOD_OK; - } - if (JustStarted && openstate == FMOD_OPENSTATE_PLAYING) - { - JustStarted = false; - } - if (JustStarted && Channel == NULL && openstate == FMOD_OPENSTATE_READY) - { - return !Play(Loop, Volume); - } - if (starving != Starved) - { // Mute the sound if it's starving. - Channel->setVolume(starving ? 0 : Volume); - Starved = starving; - } - return false; - } - - void SetVolume(float volume) - { - if (Channel != NULL && !Starved) - { - Channel->setVolume(volume); - } - Volume = volume; - } - - // Sets the position in ms. - bool SetPosition(unsigned int ms_pos) - { - return FMOD_OK == Channel->setPosition(ms_pos, FMOD_TIMEUNIT_MS); - } - - // Sets the order number for MOD formats. - bool SetOrder(int order_pos) - { - return FMOD_OK == Channel->setPosition(order_pos, FMOD_TIMEUNIT_MODORDER); - } - - FString GetStats() - { - FString stats; - FMOD_OPENSTATE openstate; - unsigned int percentbuffered; - unsigned int position; - bool starving; -#if FMOD_STUDIO || FMOD_VERSION >= 0x43400 - bool diskbusy; -#endif - float volume; - float frequency; - bool paused; - bool isplaying; - -#if !FMOD_STUDIO && FMOD_VERSION < 0x43400 - if (FMOD_OK == Stream->getOpenState(&openstate, &percentbuffered, &starving)) -#else - if (FMOD_OK == Stream->getOpenState(&openstate, &percentbuffered, &starving, &diskbusy)) -#endif - { - stats = (openstate <= FMOD_OPENSTATE_PLAYING ? OpenStateNames[openstate] : "Unknown state"); - stats.AppendFormat(",%3d%% buffered, %s", percentbuffered, starving ? "Starving" : "Well-fed"); - } - if (Channel == NULL) - { - stats += ", not playing"; - } - if (Channel != NULL && FMOD_OK == Channel->getPosition(&position, FMOD_TIMEUNIT_MS)) - { - stats.AppendFormat(", %d", position); - if (FMOD_OK == Stream->getLength(&position, FMOD_TIMEUNIT_MS)) - { - stats.AppendFormat("/%d", position); - } - stats += " ms"; - } - if (Channel != NULL && FMOD_OK == Channel->getVolume(&volume)) - { - stats.AppendFormat(", %d%%", int(volume * 100)); - } - if (Channel != NULL && FMOD_OK == Channel->getPaused(&paused) && paused) - { - stats += ", paused"; - } - if (Channel != NULL && FMOD_OK == Channel->isPlaying(&isplaying) && isplaying) - { - stats += ", playing"; - } - if (Channel != NULL && FMOD_OK == Channel->getFrequency(&frequency)) - { - stats.AppendFormat(", %g Hz", frequency); - } - if (JustStarted) - { - stats += " JS"; - } - if (Ended) - { - stats += " XX"; - } - return stats; - } - - static FMOD_RESULT F_CALLBACK PCMReadCallback(FMOD_SOUND *sound, void *data, unsigned int datalen) - { - FMOD_RESULT result; - FMODStreamCapsule *self; - - result = ((FMOD::Sound *)sound)->getUserData((void **)&self); - if (result != FMOD_OK || self == NULL || self->Callback == NULL || self->Ended) - { - // Contrary to the docs, this return value is completely ignored. - return FMOD_OK; - } - if (!self->Callback(self, data, datalen, self->UserData)) - { - self->Ended = true; - } - return FMOD_OK; - } - - static FMOD_RESULT F_CALLBACK PCMSetPosCallback(FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype) - { - // This is useful if the user calls Channel::setPosition and you want - // to seek your data accordingly. - return FMOD_OK; - } - -private: - FMODSoundRenderer *Owner; - FMOD::Sound *Stream; - FMOD::Channel *Channel; - void *UserData; - SoundStreamCallback Callback; - FileReader *Reader; - FString URL; - bool Ended; - bool JustStarted; - bool Starved; - bool Loop; - float Volume; -}; - -//========================================================================== -// -// The interface the game uses to talk to FMOD. -// -//========================================================================== - -FMODSoundRenderer::FMODSoundRenderer() -{ - InitSuccess = Init(); -} - -FMODSoundRenderer::~FMODSoundRenderer() -{ - Shutdown(); -} - -bool FMODSoundRenderer::IsValid() -{ - return InitSuccess; -} - -//========================================================================== -// -// FMODSoundRenderer :: Init -// -//========================================================================== - -bool FMODSoundRenderer::Init() -{ - FMOD_RESULT result; - unsigned int version; - FMOD_SPEAKERMODE speakermode; - FMOD_SOUND_FORMAT format; - FMOD_DSP_RESAMPLER resampler; - FMOD_INITFLAGS initflags; - int samplerate; - int driver; - - int eval; - - SFXPaused = 0; - DSPLocked = false; - MusicGroup = NULL; - SfxGroup = NULL; - PausableSfx = NULL; - SfxConnection = NULL; - WaterLP = NULL; - WaterReverb = NULL; - PrevEnvironment = DefaultEnvironments[0]; - DSPClock.AsOne = 0; - ChannelGroupTargetUnit = NULL; - ChannelGroupTargetUnitOutput = NULL; - SfxReverbHooked = false; - SfxReverbPlaceholder = NULL; - OutputPlugin = 0; - - Printf("I_InitSound: Initializing FMOD\n"); - - // This is just for safety. Normally this should never be called if FMod Ex cannot be found. - if (!IsFModExPresent()) - { - Sys = NULL; - Printf(TEXTCOLOR_ORANGE"Failed to load fmodex" -#ifdef _WIN64 - "64" -#endif - ".dll\n"); - return false; - } - - // Create a System object and initialize. - result = FMOD::System_Create(&Sys); - if (result != FMOD_OK) - { - Sys = NULL; - Printf(TEXTCOLOR_ORANGE"Failed to create FMOD system object: Error %d\n", result); - return false; - } - - result = Sys->getVersion(&version); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_ORANGE"Could not validate FMOD version: Error %d\n", result); - return false; - } - - const char *wrongver = NULL; -#if FMOD_STUDIO - if (version < (FMOD_VERSION & 0xFFFF00)) -#elif FMOD_VERSION >= 0x43600 - if (version < 0x43600) -#else - if (version < 0x42000) -#endif - { - wrongver = "an old"; - } -#if !FMOD_STUDIO && FMOD_VERSION < 0x42700 - else if ((version & 0xFFFF00) > 0x42600) -#else - else if ((version & 0xFFFF00) > (FMOD_VERSION & 0xFFFF00)) -#endif - { - wrongver = "a new"; - } - if (wrongver != NULL) - { - Printf (" " TEXTCOLOR_ORANGE "Error! You are using %s version of FMOD (%x.%02x.%02x).\n" - " " TEXTCOLOR_ORANGE "This program was built for version %x.%02x.%02x\n", - wrongver, - version >> 16, (version >> 8) & 255, version & 255, - FMOD_VERSION >> 16, (FMOD_VERSION >> 8) & 255, FMOD_VERSION & 255); - return false; - } - ActiveFMODVersion = version; - - if (!ShowedBanner) - { - // '\xa9' is the copyright symbol in the Windows-1252 code page. - Printf("FMOD Sound System, copyright \xa9 Firelight Technologies Pty, Ltd., 1994-2009.\n"); - Printf("Loaded FMOD version %x.%02x.%02x\n", version >> 16, (version >> 8) & 255, version & 255); - ShowedBanner = true; - } -#if defined(_WIN32) && !FMOD_STUDIO - if (OSPlatform == os_WinNT4) - { - // The following was true as of FMOD 3. I don't know if it still - // applies to FMOD Ex, nor do I have an NT 4 install anymore, but - // there's no reason to get rid of it yet. - // - // If running Windows NT 4, we need to initialize DirectSound before - // using WinMM. If we don't, then FSOUND_Close will corrupt a - // heap. This might just be the Audigy's drivers--I don't know why - // it happens. At least the fix is simple enough. I only need to - // initialize DirectSound once, and then I can initialize/close - // WinMM as many times as I want. - // - // Yes, using WinMM under NT 4 is a good idea. I can get latencies as - // low as 20 ms with WinMM, but with DirectSound I need to have the - // latency as high as 120 ms to avoid crackling--quite the opposite - // from the other Windows versions with real DirectSound support. - - static bool inited_dsound = false; - - if (!inited_dsound) - { - if (Sys->setOutput(FMOD_OUTPUTTYPE_DSOUND) == FMOD_OK) - { - if (Sys->init(1, FMOD_INIT_NORMAL, 0) == FMOD_OK) - { - inited_dsound = true; - Sleep(50); - Sys->close(); - } - Sys->setOutput(FMOD_OUTPUTTYPE_WINMM); - } - } - } -#endif - -#if !defined _WIN32 && !defined __APPLE__ && !FMOD_STUDIO - // Try to load SDL output plugin - result = Sys->setPluginPath(progdir); // Should we really look for it in the program directory? - result = Sys->loadPlugin("liboutput_sdl.so", &OutputPlugin); - if (result != FMOD_OK) - { - OutputPlugin = 0; - } -#endif - - // Set the user specified output mode. - eval = Enum_NumForName(OutputNames, snd_output); - if (eval >= 0) - { - if (eval == 666 && OutputPlugin != 0) - { - result = Sys->setOutputByPlugin(OutputPlugin); - } - else - { - result = Sys->setOutput(FMOD_OUTPUTTYPE(eval)); - } - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Setting output type '%s' failed. Using default instead. (Error %d)\n", *snd_output, result); - eval = FMOD_OUTPUTTYPE_AUTODETECT; - Sys->setOutput(FMOD_OUTPUTTYPE_AUTODETECT); - } - } - - result = Sys->getNumDrivers(&driver); -#if defined(__unix__) && !FMOD_STUDIO - if (result == FMOD_OK) - { - // On Linux, FMOD defaults to OSS. If OSS is not present, it doesn't - // try ALSA; it just fails. We'll try for it, but only if OSS wasn't - // explicitly specified for snd_output. - if (driver == 0 && eval == FMOD_OUTPUTTYPE_AUTODETECT) - { - FMOD_OUTPUTTYPE output; - if (FMOD_OK == Sys->getOutput(&output)) - { - if (output == FMOD_OUTPUTTYPE_OSS) - { - Printf(TEXTCOLOR_BLUE"OSS could not be initialized. Trying ALSA.\n"); - Sys->setOutput(FMOD_OUTPUTTYPE_ALSA); - result = Sys->getNumDrivers(&driver); - } - } - } - } -#endif - if (result == FMOD_OK) - { - if (driver == 0) - { - Printf(TEXTCOLOR_ORANGE"No working sound devices found. Try a different snd_output?\n"); - return false; - } - if (snd_driver >= driver) - { - Printf(TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver); - driver = 0; - } - else - { - driver = snd_driver; - } - result = Sys->setDriver(driver); - } - result = Sys->getDriver(&driver); -#if FMOD_STUDIO - // We were built with an FMOD Studio that only returns the control panel frequency - result = Sys->getDriverInfo(driver, nullptr, 0, nullptr, &Driver_MinFrequency, &speakermode, nullptr); - Driver_MaxFrequency = Driver_MinFrequency; -#elif FMOD_VERSION >= 0x43600 - // We were built with an FMOD that only returns the control panel frequency - result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &speakermode); - Driver_MaxFrequency = Driver_MinFrequency; -#else - // We were built with an FMOD that returns a frequency range - result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode); -#endif - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result); - // Fill in some default to pretend it worked. (But as long as we specify a valid driver, - // can this call actually fail?) -#if !FMOD_STUDIO - Driver_Caps = 0; -#endif - Driver_MinFrequency = 4000; - Driver_MaxFrequency = 48000; - speakermode = FMOD_SPEAKERMODE_STEREO; - } - - // Set the user selected speaker mode. - eval = Enum_NumForName(SpeakerModeNames, snd_speakermode); - if (eval >= 0) - { - speakermode = FMOD_SPEAKERMODE(eval); - } -#if !FMOD_STUDIO - result = Sys->setSpeakerMode(speakermode); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Could not set speaker mode to '%s'. (Error %d)\n", *snd_speakermode, result); - } -#endif - - // Set software format - eval = Enum_NumForName(SoundFormatNames, snd_output_format); - format = eval >= 0 ? FMOD_SOUND_FORMAT(eval) : FMOD_SOUND_FORMAT_PCM16; - if (format == FMOD_SOUND_FORMAT_PCM8) - { - // PCM-8 sounds like garbage with anything but DirectSound. - FMOD_OUTPUTTYPE output; - if (FMOD_OK != Sys->getOutput(&output) || output != FMOD_OUTPUTTYPE_DSOUND) - { - format = FMOD_SOUND_FORMAT_PCM16; - } - } - eval = Enum_NumForName(ResamplerNames, snd_resampler); - resampler = eval >= 0 ? FMOD_DSP_RESAMPLER(eval) : FMOD_DSP_RESAMPLER_LINEAR; - // These represented the frequency limits for hardware channels, which we never used anyway. -// samplerate = clamp(snd_samplerate, Driver_MinFrequency, Driver_MaxFrequency); - samplerate = snd_samplerate; - if (samplerate == 0 || snd_samplerate == 0) - { // Creative's ASIO drivers report the only supported frequency as 0! -#if FMOD_STUDIO - if (FMOD_OK != Sys->getSoftwareFormat(&samplerate, NULL, NULL)) -#else - if (FMOD_OK != Sys->getSoftwareFormat(&samplerate, NULL, NULL, NULL, NULL, NULL)) -#endif - { - samplerate = 48000; - } - } - if (samplerate != snd_samplerate && snd_samplerate != 0) - { - Printf(TEXTCOLOR_BLUE"Sample rate %d is unsupported. Trying %d.\n", *snd_samplerate, samplerate); - } -#if FMOD_STUDIO - result = Sys->setSoftwareFormat(samplerate, speakermode, 0); -#else - result = Sys->setSoftwareFormat(samplerate, format, 0, 0, resampler); -#endif - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Could not set mixing format. Defaults will be used. (Error %d)\n", result); - } - -#if FMOD_STUDIO - FMOD_ADVANCEDSETTINGS advSettings = {}; - advSettings.cbSize = sizeof advSettings; - advSettings.resamplerMethod = resampler; - result = Sys->setAdvancedSettings(&advSettings); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Could not set resampler method. Defaults will be used. (Error %d)\n", result); - } -#endif - - // Set software channels according to snd_channels - result = Sys->setSoftwareChannels(snd_channels + NUM_EXTRA_SOFTWARE_CHANNELS); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Failed to set the preferred number of channels. (Error %d)\n", result); - } - -#if !FMOD_STUDIO - if (Driver_Caps & FMOD_CAPS_HARDWARE_EMULATED) - { // The user has the 'Acceleration' slider set to off! - // This is really bad for latency! - Printf (TEXTCOLOR_BLUE"Warning: The sound acceleration slider has been set to off.\n"); - Printf (TEXTCOLOR_BLUE"Please turn it back on if you want decent sound.\n"); - result = Sys->setDSPBufferSize(1024, 10); // At 48khz, the latency between issuing an fmod command and hearing it will now be about 213ms. - } - else -#endif - if (snd_buffersize != 0 || snd_buffercount != 0) - { - int buffersize = snd_buffersize ? snd_buffersize : 1024; - int buffercount = snd_buffercount ? snd_buffercount : 4; - result = Sys->setDSPBufferSize(buffersize, buffercount); - } - else - { - result = FMOD_OK; - } - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE"Setting DSP buffer size failed. (Error %d)\n", result); - } - - // Try to init - initflags = FMOD_INIT_NORMAL; - if (snd_hrtf) - { - // These flags are the same thing, just with different names. -#ifdef FMOD_INIT_CHANNEL_LOWPASS - initflags |= FMOD_INIT_CHANNEL_LOWPASS; -#elif defined(FMOD_INIT_SOFTWARE_HRTF) - initflags |= FMOD_INIT_SOFTWARE_HRTF; -#else - initflags |= FMOD_INIT_HRTF_LOWPASS; -#endif - } - if (snd_profile) - { -#ifdef FMOD_INIT_PROFILE_ENABLE - initflags |= FMOD_INIT_PROFILE_ENABLE; -#else - initflags |= FMOD_INIT_ENABLE_PROFILE; -#endif - } - for (;;) - { - result = Sys->init(MAX(*snd_channels, MAX_CHANNELS), initflags, 0); - if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) - { - // Possible causes of a buffer creation failure: - // 1. The speaker mode selected isn't supported by this soundcard. Force it to stereo. - // 2. The output format is unsupported. Force it to 16-bit PCM. - // 3. ??? -#if FMOD_STUDIO - result = Sys->getSoftwareFormat(nullptr, &speakermode, nullptr); -#else - result = Sys->getSpeakerMode(&speakermode); -#endif - if (result == FMOD_OK && - speakermode != FMOD_SPEAKERMODE_STEREO && -#if FMOD_STUDIO - FMOD_OK == Sys->setSoftwareFormat(samplerate, FMOD_SPEAKERMODE_STEREO, 0)) -#else - FMOD_OK == Sys->setSpeakerMode(FMOD_SPEAKERMODE_STEREO)) -#endif - { - Printf(TEXTCOLOR_RED" Buffer creation failed. Retrying with stereo output.\n"); - continue; - } -#if !FMOD_STUDIO - result = Sys->getSoftwareFormat(&samplerate, &format, NULL, NULL, &resampler, NULL); - if (result == FMOD_OK && - format != FMOD_SOUND_FORMAT_PCM16 && - FMOD_OK == Sys->setSoftwareFormat(samplerate, FMOD_SOUND_FORMAT_PCM16, 0, 0, resampler)) - { - Printf(TEXTCOLOR_RED" Buffer creation failed. Retrying with PCM-16 output.\n"); - continue; - } -#endif - } - else if (result == FMOD_ERR_NET_SOCKET_ERROR && -#ifdef FMOD_INIT_PROFILE_ENABLE - (initflags & FMOD_INIT_PROFILE_ENABLE)) -#else - (initflags & FMOD_INIT_ENABLE_PROFILE)) -#endif - { - Printf(TEXTCOLOR_RED" Could not create socket. Retrying without profiling.\n"); -#ifdef FMOD_INIT_PROFILE_ENABLE - initflags &= ~FMOD_INIT_PROFILE_ENABLE; -#else - initflags &= ~FMOD_INIT_ENABLE_PROFILE; -#endif - continue; - } -#ifdef _WIN32 - else if (result == FMOD_ERR_OUTPUT_INIT) - { - FMOD_OUTPUTTYPE output; - result = Sys->getOutput(&output); - if (result == FMOD_OK && output != FMOD_OUTPUTTYPE_DSOUND) - { - Printf(TEXTCOLOR_BLUE" Init failed for output type %s. Retrying with DirectSound.\n", - Enum_NameForNum(OutputNames, output)); - if (FMOD_OK == Sys->setOutput(FMOD_OUTPUTTYPE_DSOUND)) - { - continue; - } - } - } -#endif - break; - } - if (result != FMOD_OK) - { // Initializing FMOD failed. Cry cry. - Printf(TEXTCOLOR_ORANGE" System::init returned error code %d\n", result); - return false; - } - - // Create channel groups - result = Sys->createChannelGroup("Music", &MusicGroup); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_ORANGE" Could not create music channel group. (Error %d)\n", result); - return false; - } - - result = Sys->createChannelGroup("SFX", &SfxGroup); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_ORANGE" Could not create sfx channel group. (Error %d)\n", result); - return false; - } - - result = Sys->createChannelGroup("Pausable SFX", &PausableSfx); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_ORANGE" Could not create pausable sfx channel group. (Error %d)\n", result); - return false; - } - - result = SfxGroup->addGroup(PausableSfx); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE" Could not attach pausable sfx to sfx channel group. (Error %d)\n", result); - } - - // Create DSP units for underwater effect - result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE" Could not create underwater lowpass unit. (Error %d)\n", result); - } - else - { - result = Sys->createDSPByType(FMOD_DSP_TYPE_SFXREVERB, &WaterReverb); - if (result != FMOD_OK) - { - Printf(TEXTCOLOR_BLUE" Could not create underwater reverb unit. (Error %d)\n", result); - } - } - - // Connect underwater DSP unit between PausableSFX and SFX groups, while - // retaining the connection established by SfxGroup->addGroup(). - if (WaterLP != NULL) - { - FMOD::DSP *sfx_head, *pausable_head; - -#if FMOD_STUDIO - result = SfxGroup->getDSP(FMOD_CHANNELCONTROL_DSP_HEAD, &sfx_head); -#else - result = SfxGroup->getDSPHead(&sfx_head); -#endif - if (result == FMOD_OK) - { - result = sfx_head->getInput(0, &pausable_head, &SfxConnection); - if (result == FMOD_OK) - { - // The placeholder mixer is for reference to where to connect the SFX - // reverb unit once it gets created. - result = Sys->createDSPByType(FMOD_DSP_TYPE_MIXER, &SfxReverbPlaceholder); - if (result == FMOD_OK) - { - // Replace the PausableSFX->SFX connection with - // PausableSFX->ReverbPlaceholder->SFX. - result = SfxReverbPlaceholder->addInput(pausable_head, NULL); - if (result == FMOD_OK) - { - FMOD::DSPConnection *connection; - result = sfx_head->addInput(SfxReverbPlaceholder, &connection); - if (result == FMOD_OK) - { - sfx_head->disconnectFrom(pausable_head); - SfxReverbPlaceholder->setActive(true); - SfxReverbPlaceholder->setBypass(true); - // The placeholder now takes the place of the pausable_head - // for the following connections. - pausable_head = SfxReverbPlaceholder; - SfxConnection = connection; - } - } - else - { - SfxReverbPlaceholder->release(); - SfxReverbPlaceholder = NULL; - } - } - result = WaterLP->addInput(pausable_head, NULL); - WaterLP->setActive(false); - WaterLP->setParameterFloat(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp); - WaterLP->setParameterFloat(FMOD_DSP_LOWPASS_RESONANCE, 2); - - if (WaterReverb != NULL) - { - result = WaterReverb->addInput(WaterLP, NULL); - if (result == FMOD_OK) - { - result = sfx_head->addInput(WaterReverb, NULL); - if (result == FMOD_OK) - { -// WaterReverb->setParameter(FMOD_DSP_REVERB_ROOMSIZE, 0.001f); -// WaterReverb->setParameter(FMOD_DSP_REVERB_DAMP, 0.2f); - - // These parameters are entirely empirical and can probably - // stand some improvement, but it sounds remarkably close - // to the old reverb unit's output. -#if FMOD_STUDIO - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFFREQUENCY, 150); -#else - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_LFREFERENCE, 150); -#endif - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_HFREFERENCE, 10000); -#if !FMOD_STUDIO - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_ROOM, 0); - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_ROOMHF, -5000); -#endif - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_DRYLEVEL, 0); -#if FMOD_STUDIO - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_HFDECAYRATIO, 100); -#else - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_DECAYHFRATIO, 1); -#endif - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_DECAYTIME, 0.25f); - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_DENSITY, 100); - WaterReverb->setParameterFloat(FMOD_DSP_SFXREVERB_DIFFUSION, 100); - WaterReverb->setActive(false); - } - } - } - else - { - result = sfx_head->addInput(WaterLP, NULL); - } - } - } - } - LastWaterLP = snd_waterlp; - - // Find the FMOD Channel Group Target Unit. To completely eliminate sound - // while the program is deactivated, we can deactivate this DSP unit, and - // all audio processing will cease. This is not directly exposed by the - // API but can be easily located by getting the master channel group and - // tracing its single output, since it is known to hook up directly to the - // Channel Group Target Unit. (See FMOD Profiler for proof.) - FMOD::ChannelGroup *master_group; - result = Sys->getMasterChannelGroup(&master_group); - if (result == FMOD_OK) - { - FMOD::DSP *master_head; - -#if FMOD_STUDIO - result = master_group->getDSP(FMOD_CHANNELCONTROL_DSP_HEAD, &master_head); -#else - result = master_group->getDSPHead(&master_head); -#endif - if (result == FMOD_OK) - { - result = master_head->getOutput(0, &ChannelGroupTargetUnit, NULL); - if (result != FMOD_OK) - { - ChannelGroupTargetUnit = NULL; - } - else - { - FMOD::DSP *dontcare; - result = ChannelGroupTargetUnit->getOutput(0, &dontcare, &ChannelGroupTargetUnitOutput); - if (result != FMOD_OK) - { - ChannelGroupTargetUnitOutput = NULL; - } - } - } - } - -#if FMOD_STUDIO - if (FMOD_OK != Sys->getSoftwareFormat(&OutputRate, NULL, NULL)) -#else - if (FMOD_OK != Sys->getSoftwareFormat(&OutputRate, NULL, NULL, NULL, NULL, NULL)) -#endif - { - OutputRate = 48000; // Guess, but this should never happen. - } - Sys->set3DSettings(0.5f, 96.f, 1.f); - Sys->set3DRolloffCallback(RolloffCallback); - Sys->setStreamBufferSize(snd_streambuffersize * 1024, FMOD_TIMEUNIT_RAWBYTES); - snd_sfxvolume.Callback (); - return true; -} - -//========================================================================== -// -// FMODSoundRenderer :: Shutdown -// -//========================================================================== - -void FMODSoundRenderer::Shutdown() -{ - if (Sys != NULL) - { - if (MusicGroup != NULL) - { - MusicGroup->release(); - MusicGroup = NULL; - } - if (PausableSfx != NULL) - { - PausableSfx->release(); - PausableSfx = NULL; - } - if (SfxGroup != NULL) - { - SfxGroup->release(); - SfxGroup = NULL; - } - if (WaterLP != NULL) - { - WaterLP->release(); - WaterLP = NULL; - } - if (WaterReverb != NULL) - { - WaterReverb->release(); - WaterReverb = NULL; - } - if (SfxReverbPlaceholder != NULL) - { - SfxReverbPlaceholder->release(); - SfxReverbPlaceholder = NULL; - } - - Sys->close(); - if (OutputPlugin != 0) - { - Sys->unloadPlugin(OutputPlugin); - OutputPlugin = 0; - } - Sys->release(); - Sys = NULL; - } -} - -//========================================================================== -// -// FMODSoundRenderer :: GetOutputRate -// -//========================================================================== - -float FMODSoundRenderer::GetOutputRate() -{ - return (float)OutputRate; -} - -//========================================================================== -// -// FMODSoundRenderer :: PrintStatus -// -//========================================================================== - -void FMODSoundRenderer::PrintStatus() -{ - FMOD_OUTPUTTYPE output; - FMOD_SPEAKERMODE speakermode; - int driver; - int samplerate; - unsigned int bufferlength; - int numbuffers; - - Printf ("Loaded FMOD version: " TEXTCOLOR_GREEN "%x.%02x.%02x\n", ActiveFMODVersion >> 16, - (ActiveFMODVersion >> 8) & 255, ActiveFMODVersion & 255); - if (FMOD_OK == Sys->getOutput(&output)) - { - Printf ("Output type: " TEXTCOLOR_GREEN "%s\n", Enum_NameForNum(OutputNames, output)); - } -#if FMOD_STUDIO - if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &speakermode, nullptr)) - { - Printf ("Speaker mode: " TEXTCOLOR_GREEN "%s\n", Enum_NameForNum(SpeakerModeNames, speakermode)); - Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: " TEXTCOLOR_GREEN "%d\n", samplerate); - } -#else - if (FMOD_OK == Sys->getSpeakerMode(&speakermode)) - { - Printf ("Speaker mode: " TEXTCOLOR_GREEN "%s\n", Enum_NameForNum(SpeakerModeNames, speakermode)); - } -#endif - if (FMOD_OK == Sys->getDriver(&driver)) - { - char name[256]; -#if FMOD_STUDIO - if (FMOD_OK != Sys->getDriverInfo(driver, name, sizeof(name), nullptr, nullptr, nullptr, nullptr)) -#else - if (FMOD_OK != Sys->getDriverInfo(driver, name, sizeof(name), NULL)) -#endif - { - strcpy(name, "Unknown"); - } - Printf ("Driver: " TEXTCOLOR_GREEN "%d" TEXTCOLOR_NORMAL " (" TEXTCOLOR_ORANGE "%s" TEXTCOLOR_NORMAL ")\n", driver, name); -#if !FMOD_STUDIO - DumpDriverCaps(Driver_Caps, Driver_MinFrequency, Driver_MaxFrequency); -#endif - } -#if !FMOD_STUDIO - FMOD_SOUND_FORMAT format; - FMOD_DSP_RESAMPLER resampler; - int numoutputchannels; - if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &format, &numoutputchannels, NULL, &resampler, NULL)) - { - Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: " TEXTCOLOR_GREEN "%d\n", samplerate); - Printf (TEXTCOLOR_LIGHTBLUE "Software mixer format: " TEXTCOLOR_GREEN "%s\n", Enum_NameForNum(SoundFormatNames, format)); - Printf (TEXTCOLOR_LIGHTBLUE "Software mixer channels: " TEXTCOLOR_GREEN "%d\n", numoutputchannels); - Printf (TEXTCOLOR_LIGHTBLUE "Software mixer resampler: " TEXTCOLOR_GREEN "%s\n", Enum_NameForNum(ResamplerNames, resampler)); - } -#endif - if (FMOD_OK == Sys->getDSPBufferSize(&bufferlength, &numbuffers)) - { - Printf (TEXTCOLOR_LIGHTBLUE "DSP buffers: " TEXTCOLOR_GREEN "%u samples x %d\n", bufferlength, numbuffers); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DumpDriverCaps -// -//========================================================================== - -#if !FMOD_STUDIO -void FMODSoundRenderer::DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int maxfrequency) -{ - Printf (TEXTCOLOR_OLIVE " Min. frequency: " TEXTCOLOR_GREEN "%d\n", minfrequency); - Printf (TEXTCOLOR_OLIVE " Max. frequency: " TEXTCOLOR_GREEN "%d\n", maxfrequency); - Printf (" Features:\n"); - if (caps == 0) Printf(TEXTCOLOR_OLIVE " None\n"); - if (caps & FMOD_CAPS_HARDWARE) Printf(TEXTCOLOR_OLIVE " Hardware mixing\n"); - if (caps & FMOD_CAPS_HARDWARE_EMULATED) Printf(TEXTCOLOR_OLIVE " Hardware acceleration is turned off!\n"); - if (caps & FMOD_CAPS_OUTPUT_MULTICHANNEL) Printf(TEXTCOLOR_OLIVE " Multichannel\n"); - if (caps & FMOD_CAPS_OUTPUT_FORMAT_PCM8) Printf(TEXTCOLOR_OLIVE " PCM-8"); - if (caps & FMOD_CAPS_OUTPUT_FORMAT_PCM16) Printf(TEXTCOLOR_OLIVE " PCM-16"); - if (caps & FMOD_CAPS_OUTPUT_FORMAT_PCM24) Printf(TEXTCOLOR_OLIVE " PCM-24"); - if (caps & FMOD_CAPS_OUTPUT_FORMAT_PCM32) Printf(TEXTCOLOR_OLIVE " PCM-32"); - if (caps & FMOD_CAPS_OUTPUT_FORMAT_PCMFLOAT) Printf(TEXTCOLOR_OLIVE " PCM-Float"); - if (caps & (FMOD_CAPS_OUTPUT_FORMAT_PCM8 | FMOD_CAPS_OUTPUT_FORMAT_PCM16 | FMOD_CAPS_OUTPUT_FORMAT_PCM24 | FMOD_CAPS_OUTPUT_FORMAT_PCM32 | FMOD_CAPS_OUTPUT_FORMAT_PCMFLOAT)) - { - Printf("\n"); - } - if (caps & FMOD_CAPS_REVERB_LIMITED) Printf(TEXTCOLOR_OLIVE " Limited reverb\n"); -} -#endif - -//========================================================================== -// -// FMODSoundRenderer :: PrintDriversList -// -//========================================================================== - -void FMODSoundRenderer::PrintDriversList() -{ - int numdrivers; - int i; - char name[256]; - - if (FMOD_OK == Sys->getNumDrivers(&numdrivers)) - { - for (i = 0; i < numdrivers; ++i) - { -#if FMOD_STUDIO - if (FMOD_OK == Sys->getDriverInfo(i, name, sizeof(name), nullptr, nullptr, nullptr, nullptr)) -#else - if (FMOD_OK == Sys->getDriverInfo(i, name, sizeof(name), NULL)) -#endif - { - Printf("%d. %s\n", i, name); - } - } - } -} - -//========================================================================== -// -// FMODSoundRenderer :: GatherStats -// -//========================================================================== - -FString FMODSoundRenderer::GatherStats() -{ - int channels; - float dsp, stream, update, geometry, total; - FString out; - - channels = 0; - total = update = geometry = stream = dsp = 0; - Sys->getChannelsPlaying(&channels); -#if FMOD_STUDIO || FMOD_VERSION >= 0x42501 - // We were built with an FMOD with the geometry parameter. - if (ActiveFMODVersion >= 0x42501) - { // And we are running with an FMOD that includes it. - FMOD_System_GetCPUUsage((FMOD_SYSTEM *)Sys, &dsp, &stream, &geometry, &update, &total); - } - else - { // And we are running with an FMOD that does not include it. - // Cast the function to the appropriate type and call through the cast, - // since the headers are for the newer version. - ((FMOD_RESULT (F_API *)(FMOD_SYSTEM *, float *, float *, float *, float *)) - FMOD_System_GetCPUUsage)((FMOD_SYSTEM *)Sys, &dsp, &stream, &update, &total); - } -#else - // Same as above, except the headers we used do not include the geometry parameter. - if (ActiveFMODVersion >= 0x42501) - { - ((FMOD_RESULT (F_API *)(FMOD_SYSTEM *, float *, float *, float *, float *, float *)) - FMOD_System_GetCPUUsage)((FMOD_SYSTEM *)Sys, &dsp, &stream, &geometry, &update, &total); - } - else - { - FMOD_System_GetCPUUsage((FMOD_SYSTEM *)Sys, &dsp, &stream, &update, &total); - } -#endif - - out.Format ("%d channels," TEXTCOLOR_YELLOW "%5.2f" TEXTCOLOR_NORMAL "%% CPU " - "(DSP:" TEXTCOLOR_YELLOW "%5.2f" TEXTCOLOR_NORMAL "%% " - "Stream:" TEXTCOLOR_YELLOW "%5.2f" TEXTCOLOR_NORMAL "%% " - "Geometry:" TEXTCOLOR_YELLOW "%5.2f" TEXTCOLOR_NORMAL "%% " - "Update:" TEXTCOLOR_YELLOW "%5.2f" TEXTCOLOR_NORMAL "%%)", - channels, total, dsp, stream, geometry, update); - return out; -} - -//========================================================================== -// -// FMODSoundRenderer :: SetSfxVolume -// -//========================================================================== - -void FMODSoundRenderer::SetSfxVolume(float volume) -{ - SfxGroup->setVolume(volume); -} - -//========================================================================== -// -// FMODSoundRenderer :: SetMusicVolume -// -//========================================================================== - -void FMODSoundRenderer::SetMusicVolume(float volume) -{ - MusicGroup->setVolume(volume); -} - -//========================================================================== -// -// FMODSoundRenderer :: CreateStream -// -// Creates a streaming sound that receives PCM data through a callback. -// -//========================================================================== - -SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) -{ - FMODStreamCapsule *capsule; - FMOD::Sound *sound; - FMOD_RESULT result; - FMOD_CREATESOUNDEXINFO exinfo; - FMOD_MODE mode; - int sample_shift; - int channel_shift; - - InitCreateSoundExInfo(&exinfo); - capsule = new FMODStreamCapsule (userdata, callback, this); - - mode = FMOD_2D | FMOD_OPENUSER | FMOD_LOOP_NORMAL | FMOD_SOFTWARE | FMOD_CREATESTREAM | FMOD_OPENONLY; - sample_shift = (flags & (SoundStream::Bits32 | SoundStream::Float)) ? 2 : (flags & SoundStream::Bits8) ? 0 : 1; - channel_shift = (flags & SoundStream::Mono) ? 0 : 1; - - // Chunk size of stream update in samples. This will be the amount of data - // passed to the user callback. - exinfo.decodebuffersize = buffbytes >> (sample_shift + channel_shift); - - // Number of channels in the sound. - exinfo.numchannels = 1 << channel_shift; - - // Length of PCM data in bytes of whole song (for Sound::getLength). - // This pretends it's extremely long. - exinfo.length = ~0u; - - // Default playback rate of sound. */ - exinfo.defaultfrequency = samplerate; - - // Data format of sound. - if (flags & SoundStream::Float) - { - exinfo.format = FMOD_SOUND_FORMAT_PCMFLOAT; - } - else if (flags & SoundStream::Bits32) - { - exinfo.format = FMOD_SOUND_FORMAT_PCM32; - } - else if (flags & SoundStream::Bits8) - { - exinfo.format = FMOD_SOUND_FORMAT_PCM8; - } - else - { - exinfo.format = FMOD_SOUND_FORMAT_PCM16; - } - - // User callback for reading. - exinfo.pcmreadcallback = FMODStreamCapsule::PCMReadCallback; - - // User callback for seeking. - exinfo.pcmsetposcallback = FMODStreamCapsule::PCMSetPosCallback; - - // User data to be attached to the sound during creation. Access via Sound::getUserData. - exinfo.userdata = capsule; - - result = Sys->createSound(NULL, mode, &exinfo, &sound); - if (result != FMOD_OK) - { - delete capsule; - return NULL; - } - capsule->SetStream(sound); - return capsule; -} - -//========================================================================== -// -// GetTagData -// -// Checks for a string-type tag, and returns its data. -// -//========================================================================== - -const char *GetTagData(FMOD::Sound *sound, const char *tag_name) -{ - FMOD_TAG tag; - - if (FMOD_OK == sound->getTag(tag_name, 0, &tag) && - (tag.datatype == FMOD_TAGDATATYPE_STRING || tag.datatype == FMOD_TAGDATATYPE_STRING_UTF8)) - { - return (const char *)tag.data; - } - return NULL; -} - -//========================================================================== -// -// SetCustomLoopPts -// -// Sets up custom sound loops by checking for these tags: -// LOOP_START -// LOOP_END -// LOOP_BIDI -// -//========================================================================== - -static void SetCustomLoopPts(FMOD::Sound *sound) -{ -#if 0 - FMOD_TAG tag; - int numtags; - if (FMOD_OK == stream->getNumTags(&numtags, NULL)) - { - for (int i = 0; i < numtags; ++i) - { - if (FMOD_OK == sound->getTag(NULL, i, &tag)) - { - Printf("Tag %2d. %d %s = %s\n", i, tag.datatype, tag.name, tag.data); - } - } - } -#endif - const char *tag_data; - unsigned int looppt[2]; - bool looppt_as_samples[2], have_looppt[2] = { false }; - static const char *const loop_tags[2] = { "LOOP_START", "LOOP_END" }; - - for (int i = 0; i < 2; ++i) - { - if (NULL != (tag_data = GetTagData(sound, loop_tags[i]))) - { - if (S_ParseTimeTag(tag_data, &looppt_as_samples[i], &looppt[i])) - { - have_looppt[i] = true; - } - else - { - Printf("Invalid %s tag: '%s'\n", loop_tags[i], tag_data); - } - } - } - if (have_looppt[0] && !have_looppt[1]) - { // Have a start tag, but not an end tag: End at the end of the song. - have_looppt[1] = (FMOD_OK == sound->getLength(&looppt[1], FMOD_TIMEUNIT_PCM)); - looppt_as_samples[1] = true; - } - else if (!have_looppt[0] && have_looppt[1]) - { // Have an end tag, but no start tag: Start at beginning of the song. - looppt[0] = 0; - looppt_as_samples[0] = true; - have_looppt[0] = true; - } - if (have_looppt[0] && have_looppt[1]) - { // Have both loop points: Try to set the loop. - FMOD_RESULT res = sound->setLoopPoints( - looppt[0], looppt_as_samples[0] ? FMOD_TIMEUNIT_PCM : FMOD_TIMEUNIT_MS, - looppt[1] - 1, looppt_as_samples[1] ? FMOD_TIMEUNIT_PCM : FMOD_TIMEUNIT_MS); - if (res != FMOD_OK) - { - Printf("Setting custom loop points failed. Error %d\n", res); - } - } - // Check for a bi-directional loop. - if (NULL != (tag_data = GetTagData(sound, "LOOP_BIDI")) && - (stricmp(tag_data, "on") == 0 || - stricmp(tag_data, "true") == 0 || - stricmp(tag_data, "yes") == 0 || - stricmp(tag_data, "1") == 0)) - { - FMOD_MODE mode; - if (FMOD_OK == (sound->getMode(&mode))) - { - sound->setMode((mode & ~(FMOD_LOOP_OFF | FMOD_LOOP_NORMAL)) | FMOD_LOOP_BIDI); - } - } -} - -//========================================================================== -// -// open_reader_callback -// close_reader_callback -// read_reader_callback -// seek_reader_callback -// -// FMOD_CREATESOUNDEXINFO callbacks to handle reading resource data from a -// FileReader. -// -//========================================================================== - -#if FMOD_STUDIO -static FMOD_RESULT F_CALLBACK open_reader_callback(const char *name, unsigned int *filesize, void **handle, void *userdata) -#else -static FMOD_RESULT F_CALLBACK open_reader_callback(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata) -#endif -{ - 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; -#if !FMOD_STUDIO - *userdata = reader; -#endif - 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(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(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_CREATESOUNDEXINFO exinfo; - FMOD::Sound *stream; - FMOD_RESULT result; - FString patches; - FString name; - - InitCreateSoundExInfo(&exinfo); -#if FMOD_STUDIO - exinfo.fileuseropen = open_reader_callback; - exinfo.fileuserclose = close_reader_callback; - exinfo.fileuserread = read_reader_callback; - exinfo.fileuserseek = seek_reader_callback; -#else - exinfo.useropen = open_reader_callback; - exinfo.userclose = close_reader_callback; - exinfo.userread = read_reader_callback; - exinfo.userseek = seek_reader_callback; -#endif - - 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; - } - - name.Format("_FileReader_%p", reader); - result = Sys->createSound(name, mode, &exinfo, &stream); - if(result == FMOD_ERR_FORMAT && exinfo.dlsname != NULL) - { - // FMOD_ERR_FORMAT could refer to either the main sound file or - // to the DLS instrument set. Try again without special DLS - // instruments to see if that lets it succeed. - exinfo.dlsname = NULL; - result = Sys->createSound(name, mode, &exinfo, &stream); - if (result == FMOD_OK) - { - 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; - } - - 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) - { - Printf("%s is an unsupported format.\n", *snd_midipatchset); - } - } - - if(result != FMOD_OK) - return NULL; - - SetCustomLoopPts(stream); - return new FMODStreamCapsule(stream, this, url); -} - -//========================================================================== -// -// FMODSoundRenderer :: StartSound -// -//========================================================================== - -FISoundChannel *FMODSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int flags, FISoundChannel *reuse_chan) -{ - FMOD_RESULT result; - FMOD_MODE mode; - FMOD::Channel *chan; - float freq; - -#if FMOD_STUDIO - if (FMOD_OK == ((FMOD::Sound *)sfx.data)->getDefaults(&freq, NULL)) -#else - if (FMOD_OK == ((FMOD::Sound *)sfx.data)->getDefaults(&freq, NULL, NULL, NULL)) -#endif - { - freq = PITCH(freq, pitch); - } - else - { - freq = 0; - } - - GRolloff = NULL; // Do 2D sounds need rolloff? -#if FMOD_STUDIO - result = Sys->playSound((FMOD::Sound *)sfx.data, (flags & SNDF_NOPAUSE) ? SfxGroup : PausableSfx, true, &chan); -#else - result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx.data, true, &chan); -#endif - if (FMOD_OK == result) - { - result = chan->getMode(&mode); - - if (result != FMOD_OK) - { - assert(0); - mode = FMOD_SOFTWARE; - } - mode = (mode & ~FMOD_3D) | FMOD_2D; - if (flags & SNDF_LOOP) - { - mode &= ~FMOD_LOOP_OFF; - if (!(mode & (FMOD_LOOP_NORMAL | FMOD_LOOP_BIDI))) - { - mode |= FMOD_LOOP_NORMAL; - } - } - else - { - mode |= FMOD_LOOP_OFF; - } - chan->setMode(mode); -#if !FMOD_STUDIO - chan->setChannelGroup((flags & SNDF_NOPAUSE) ? SfxGroup : PausableSfx); -#endif - if (freq != 0) - { - chan->setFrequency(freq); - } - chan->setVolume(vol); - if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) - { - chan->stop(); - return NULL; - } - if (flags & SNDF_NOREVERB) - { -#if FMOD_STUDIO - chan->setReverbProperties(0,0.f); -#else - FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, }; - if (FMOD_OK == chan->getReverbProperties(&reverb)) - { - reverb.Room = -10000; - chan->setReverbProperties(&reverb); - } -#endif - } - chan->setPaused(false); - return CommonChannelSetup(chan, reuse_chan); - } - - //DPrintf (DMSG_WARNING, "Sound %s failed to play: %d\n", sfx->name.GetChars(), result); - return NULL; -} - -//========================================================================== -// -// FMODSoundRenderer :: StartSound3D -// -//========================================================================== - -FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, - FRolloffInfo *rolloff, float distscale, - int pitch, int priority, const FVector3 &pos, const FVector3 &vel, - int channum, int flags, FISoundChannel *reuse_chan) -{ - FMOD_RESULT result; - FMOD_MODE mode; - FMOD::Channel *chan; - float freq; - float def_freq; -#if !FMOD_STUDIO - float def_vol, def_pan; -#endif - int numchans; - int def_priority; - -#if FMOD_STUDIO - if (FMOD_OK == ((FMOD::Sound *)sfx.data)->getDefaults(&def_freq, &def_priority)) -#else - if (FMOD_OK == ((FMOD::Sound *)sfx.data)->getDefaults(&def_freq, &def_vol, &def_pan, &def_priority)) -#endif - { - freq = PITCH(def_freq, pitch); - // Change the sound's default priority before playing it. -#if FMOD_STUDIO - ((FMOD::Sound *)sfx.data)->setDefaults(def_freq, clamp(def_priority - priority, 1, 256)); -#else - ((FMOD::Sound *)sfx.data)->setDefaults(def_freq, def_vol, def_pan, clamp(def_priority - priority, 1, 256)); -#endif - } - else - { - freq = 0; - def_priority = -1; - } - - // Play it. - GRolloff = rolloff; - GDistScale = distscale; - - // Experiments indicate that playSound will ignore priorities and always succeed - // as long as the parameters are set properly. It will first try to kick out sounds - // with the same priority level but has no problem with kicking out sounds at - // higher priority levels if it needs to. -#if FMOD_STUDIO - result = Sys->playSound((FMOD::Sound *)sfx.data, (flags & SNDF_NOPAUSE) ? SfxGroup : PausableSfx, true, &chan); -#else - result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx.data, true, &chan); -#endif - - // Then set the priority back. - if (def_priority >= 0) - { -#if FMOD_STUDIO - ((FMOD::Sound *)sfx.data)->setDefaults(def_freq, def_priority); -#else - ((FMOD::Sound *)sfx.data)->setDefaults(def_freq, def_vol, def_pan, def_priority); -#endif - } - - if (FMOD_OK == result) - { - result = chan->getMode(&mode); - if (result != FMOD_OK) - { - mode = FMOD_3D | FMOD_SOFTWARE; - } - if (flags & SNDF_LOOP) - { - mode &= ~FMOD_LOOP_OFF; - if (!(mode & (FMOD_LOOP_NORMAL | FMOD_LOOP_BIDI))) - { - mode |= FMOD_LOOP_NORMAL; - } - } - else - { - // FMOD_LOOP_OFF overrides FMOD_LOOP_NORMAL and FMOD_LOOP_BIDI - mode |= FMOD_LOOP_OFF; - } - mode = SetChanHeadSettings(listener, chan, pos, !!(flags & SNDF_AREA), mode); - chan->setMode(mode); -#if !FMOD_STUDIO - chan->setChannelGroup((flags & SNDF_NOPAUSE) ? SfxGroup : PausableSfx); -#endif - - if (mode & FMOD_3D) - { - // Reduce volume of stereo sounds, because each channel will be summed together - // and is likely to be very similar, resulting in an amplitude twice what it - // would have been had it been mixed to mono. - if (FMOD_OK == ((FMOD::Sound *)sfx.data)->getFormat(NULL, NULL, &numchans, NULL)) - { - if (numchans > 1) - { - vol *= 0.5f; - } - } - } - if (freq != 0) - { - chan->setFrequency(freq); - } - chan->setVolume(vol); - if (mode & FMOD_3D) - { - chan->set3DAttributes((FMOD_VECTOR *)&pos[0], (FMOD_VECTOR *)&vel[0]); - } - if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) - { - // FMOD seems to get confused if you stop a channel right after - // starting it, so hopefully this function will never fail. - // (Presumably you need an update between them, but I haven't - // tested this hypothesis.) - chan->stop(); - return NULL; - } - if (flags & SNDF_NOREVERB) - { -#if FMOD_STUDIO - chan->setReverbProperties(0,0.f); -#else - FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, }; - if (FMOD_OK == chan->getReverbProperties(&reverb)) - { - reverb.Room = -10000; - chan->setReverbProperties(&reverb); - } -#endif - } - chan->setPaused(false); - chan->getPriority(&def_priority); - FISoundChannel *schan = CommonChannelSetup(chan, reuse_chan); - schan->Rolloff = *rolloff; - return schan; - } - - GRolloff = NULL; - //DPrintf (DMSG_WARNING, "Sound %s failed to play: %d\n", sfx->name.GetChars(), result); - return 0; -} - -//========================================================================== -// -// FMODSoundRenderer :: MarkStartTime -// -// Marks a channel's start time without actually playing it. -// -//========================================================================== - -void FMODSoundRenderer::MarkStartTime(FISoundChannel *chan) -{ -#if FMOD_STUDIO - uint64_t dsp_time; - ((FMOD::Channel *)chan->SysChannel)->getDSPClock(&dsp_time,NULL); - chan->StartTime.Lo = dsp_time & 0xFFFFFFFF; - chan->StartTime.Hi = dsp_time >> 32; -#else - Sys->getDSPClock(&chan->StartTime.Hi, &chan->StartTime.Lo); -#endif -} - -//========================================================================== -// -// FMODSoundRenderer :: HandleChannelDelay -// -// If the sound is restarting, seek it to its proper place. Returns false -// if the sound would have ended. -// -// Otherwise, record its starting time, and return true. -// -//========================================================================== - -bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, int flags, float freq) const -{ - if (reuse_chan != NULL) - { // Sound is being restarted, so seek it to the position - // it would be in now if it had never been evicted. - QWORD_UNION nowtime; -#if FMOD_STUDIO - uint64_t delay; - chan->getDelay(&delay,NULL,NULL); - nowtime.Lo = delay & 0xFFFFFFFF; - nowtime.Hi = delay >> 32; -#else - chan->getDelay(FMOD_DELAYTYPE_DSPCLOCK_START, &nowtime.Hi, &nowtime.Lo); -#endif - - // If abstime is set, the sound is being restored, and - // the channel's start time is actually its seek position. - if (flags & SNDF_ABSTIME) - { - unsigned int seekpos = reuse_chan->StartTime.Lo; - if (seekpos > 0) - { - chan->setPosition(seekpos, FMOD_TIMEUNIT_PCM); - } - reuse_chan->StartTime.AsOne = uint64_t(nowtime.AsOne - seekpos * OutputRate / freq); - } - else if (reuse_chan->StartTime.AsOne != 0) - { - uint64_t difftime = nowtime.AsOne - reuse_chan->StartTime.AsOne; - if (difftime > 0) - { - // Clamp the position of looping sounds to be within the sound. - // If we try to start it several minutes past its normal end, - // FMOD doesn't like that. - // FIXME: Clamp this right for loops that don't cover the whole sound. - if (flags & SNDF_LOOP) - { - FMOD::Sound *sound; - if (FMOD_OK == chan->getCurrentSound(&sound)) - { - unsigned int len; - if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_MS) && len != 0) - { - difftime %= len; - } - } - } - return chan->setPosition((unsigned int)(difftime / OutputRate), FMOD_TIMEUNIT_MS) == FMOD_OK; - } - } - } - else - { -// chan->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, DSPClock.Hi, DSPClock.Lo); - } - return true; -} - -//========================================================================== -// -// FMODSoundRenderer :: SetChanHeadSettings -// -// If this sound is played at the same coordinates as the listener, make -// it head relative. Also, area sounds should use no 3D panning if close -// enough to the listener. -// -//========================================================================== - -FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(SoundListener *listener, FMOD::Channel *chan, - const FVector3 &pos, bool areasound, - FMOD_MODE oldmode) const -{ - if (!listener->valid) - { - return oldmode; - } - FVector3 cpos, mpos; - - cpos = listener->position; - - if (areasound) - { - float level, old_level; - - // How far are we from the perceived sound origin? Within a certain - // short distance, we interpolate between 2D panning and full 3D panning. - const double interp_range = 32.0; - double dist_sqr = (cpos - pos).LengthSquared(); - - if (dist_sqr == 0) - { - level = 0; - } - else if (dist_sqr <= interp_range * interp_range) - { // Within interp_range: Interpolate between none and full 3D panning. - level = float(1 - (interp_range - sqrt(dist_sqr)) / interp_range); - } - else - { // Beyond interp_range: Normal 3D panning. - level = 1; - } -#if FMOD_STUDIO - if (chan->get3DLevel(&old_level) == FMOD_OK && old_level != level) - { // Only set it if it's different. - chan->set3DLevel(level); -#else - if (chan->get3DPanLevel(&old_level) == FMOD_OK && old_level != level) - { // Only set it if it's different. - chan->set3DPanLevel(level); -#endif - if (level < 1) - { // Let the noise come from all speakers, not just the front ones. - // A centered 3D sound does not play at full volume, so neither should the 2D-panned one. - // This is sqrt(0.5), which is the result for a centered equal power panning. -#if FMOD_STUDIO - chan->setMixLevelsOutput(0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f); -#else - chan->setSpeakerMix(0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f,0.70711f); -#endif - } - } - return oldmode; - } - else if ((cpos - pos).LengthSquared() < (0.0004 * 0.0004)) - { // Head relative - return (oldmode & ~FMOD_3D) | FMOD_2D; - } - // World relative - return (oldmode & ~FMOD_2D) | FMOD_3D; -} - -//========================================================================== -// -// FMODSoundRenderer :: CommonChannelSetup -// -// Assign an end callback to the channel and allocates a game channel for -// it. -// -//========================================================================== - -FISoundChannel *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, FISoundChannel *reuse_chan) const -{ - FISoundChannel *schan; - - if (reuse_chan != NULL) - { - schan = reuse_chan; - schan->SysChannel = chan; - } - else - { - schan = S_GetChannel(chan); -#if FMOD_STUDIO - uint64_t time; - chan->getDelay(&time,NULL,NULL); - schan->StartTime.Lo = time & 0xFFFFFFFF; - schan->StartTime.Hi = time >> 32; -#else - chan->getDelay(FMOD_DELAYTYPE_DSPCLOCK_START, &schan->StartTime.Hi, &schan->StartTime.Lo); -#endif - } - chan->setUserData(schan); - chan->setCallback(ChannelCallback); - GRolloff = NULL; - return schan; -} - -//========================================================================== -// -// FMODSoundRenderer :: StopChannel -// -//========================================================================== - -void FMODSoundRenderer::StopChannel(FISoundChannel *chan) -{ - if (chan != NULL && chan->SysChannel != NULL) - { - if (((FMOD::Channel *)chan->SysChannel)->stop() == FMOD_ERR_INVALID_HANDLE) - { // The channel handle was invalid; pretend it ended. - S_ChannelEnded(chan); - } - } -} - -//========================================================================== -// -// FMODSoundRenderer :: ChannelVolume -// -//========================================================================== - -void FMODSoundRenderer::ChannelVolume(FISoundChannel *chan, float volume) -{ - if (chan != NULL && chan->SysChannel != NULL) - { - ((FMOD::Channel *)chan->SysChannel)->setVolume(volume); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: GetPosition -// -// Returns position of sound on this channel, in samples. -// -//========================================================================== - -unsigned int FMODSoundRenderer::GetPosition(FISoundChannel *chan) -{ - unsigned int pos; - - if (chan == NULL || chan->SysChannel == NULL) - { - return 0; - } - ((FMOD::Channel *)chan->SysChannel)->getPosition(&pos, FMOD_TIMEUNIT_PCM); - return pos; -} - -//========================================================================== -// -// FMODSoundRenderer :: GetAudibility -// -// Returns the audible volume of the channel, after rollof and any other -// factors are applied. -// -//========================================================================== - -float FMODSoundRenderer::GetAudibility(FISoundChannel *chan) -{ - float aud; - - if (chan == NULL || chan->SysChannel == NULL) - { - return 0; - } - ((FMOD::Channel *)chan->SysChannel)->getAudibility(&aud); - return aud; -} - -//========================================================================== -// -// FMODSoundRenderer :: SetSfxPaused -// -//========================================================================== - -void FMODSoundRenderer::SetSfxPaused(bool paused, int slot) -{ - int oldslots = SFXPaused; - - if (paused) - { - SFXPaused |= 1 << slot; - } - else - { - SFXPaused &= ~(1 << slot); - } - //Printf("%d\n", SFXPaused); - if (oldslots != 0 && SFXPaused == 0) - { - PausableSfx->setPaused(false); - } - else if (oldslots == 0 && SFXPaused != 0) - { - PausableSfx->setPaused(true); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: SetInactive -// -// This is similar to SetSfxPaused but will *pause* everything, including -// the global reverb effect. This is meant to be used only when the -// game is deactivated, not for general sound pausing. -// -//========================================================================== - -void FMODSoundRenderer::SetInactive(SoundRenderer::EInactiveState inactive) -{ - float mix; - bool active; - - if (inactive == INACTIVE_Active) - { - mix = 1; - active = true; - } - else if (inactive == INACTIVE_Complete) - { - mix = 1; - active = false; - } - else // inactive == INACTIVE_Mute - { - mix = 0; - active = true; - } - if (ChannelGroupTargetUnitOutput != NULL) - { - ChannelGroupTargetUnitOutput->setMix(mix); - } - if (ChannelGroupTargetUnit != NULL) - { - ChannelGroupTargetUnit->setActive(active); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: UpdateSoundParams3D -// -//========================================================================== - -void FMODSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel) -{ - if (chan == NULL || chan->SysChannel == NULL) - return; - - FMOD::Channel *fchan = (FMOD::Channel *)chan->SysChannel; - FMOD_MODE oldmode, mode; - - if (fchan->getMode(&oldmode) != FMOD_OK) - { - oldmode = FMOD_3D | FMOD_SOFTWARE; - } - mode = SetChanHeadSettings(listener, fchan, pos, areasound, oldmode); - if (mode != oldmode) - { // Only set the mode if it changed. - fchan->setMode(mode); - } - fchan->set3DAttributes((FMOD_VECTOR *)&pos[0], (FMOD_VECTOR *)&vel[0]); -} - -//========================================================================== -// -// FMODSoundRenderer :: UpdateListener -// -//========================================================================== - -void FMODSoundRenderer::UpdateListener(SoundListener *listener) -{ - FMOD_VECTOR pos, vel; - FMOD_VECTOR forward; - FMOD_VECTOR up; - - if (!listener->valid) - { - return; - } - - // Set velocity to 0 to prevent crazy doppler shifts just from running. - - vel.x = listener->velocity.X; - vel.y = listener->velocity.Y; - vel.z = listener->velocity.Z; - pos.x = listener->position.X; - pos.y = listener->position.Y; - pos.z = listener->position.Z; - - float angle = listener->angle; - forward.x = cosf(angle); - forward.y = 0; - forward.z = sinf(angle); - - up.x = 0; - up.y = 1; - up.z = 0; - - Sys->set3DListenerAttributes(0, &pos, &vel, &forward, &up); - - bool underwater = false; - const ReverbContainer *env; - - underwater = (listener->underwater && snd_waterlp); - if (ForcedEnvironment) - { - env = ForcedEnvironment; - } - else - { - env = listener->Environment; - if (env == NULL) - { - env = DefaultEnvironments[0]; - } - } - if (env != PrevEnvironment || env->Modified) - { - DPrintf (DMSG_NOTIFY, "Reverb Environment %s\n", env->Name); - const_cast(env)->Modified = false; - SetSystemReverbProperties(&env->Properties); - PrevEnvironment = env; - - if (!SfxReverbHooked) - { - SfxReverbHooked = ReconnectSFXReverbUnit(); - } - } - - if (underwater || env->SoftwareWater) - { - //PausableSfx->setPitch(0.64171f); // This appears to be what Duke 3D uses - PausableSfx->setPitch(0.7937005f); // Approx. 4 semitones lower; what Nash suggested - if (WaterLP != NULL) - { - if (LastWaterLP != snd_waterlp) - { - LastWaterLP = snd_waterlp; - WaterLP->setParameterFloat(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp); - } - WaterLP->setActive(true); - if (WaterReverb != NULL && snd_waterreverb) - { - WaterReverb->setActive(true); - WaterReverb->setBypass(false); - SfxConnection->setMix(0); - } - else - { - // Let some of the original mix through so that high frequencies are - // not completely lost. The reverb unit has its own connection and - // preserves dry sounds itself if used. - SfxConnection->setMix(0.1f); - if (WaterReverb != NULL) - { - WaterReverb->setActive(true); - WaterReverb->setBypass(true); - } - } - } - } - else - { - PausableSfx->setPitch(1); - if (WaterLP != NULL) - { - SfxConnection->setMix(1); - WaterLP->setActive(false); - if (WaterReverb != NULL) - { - WaterReverb->setActive(false); - } - } - } -} - -//========================================================================== -// -// FMODSoundRenderer :: ReconnectSFXReverbUnit -// -// Locates the DSP unit responsible for software 3D reverb. There is only -// one, and it by default is connected directly to the ChannelGroup Target -// Unit. Older versions of FMOD created this at startup; newer versions -// delay creating it until the first call to setReverbProperties, at which -// point it persists until the system is closed. -// -// Upon locating the proper DSP unit, reconnects it to serve as an input to -// our water DSP chain after the Pausable SFX ChannelGroup. -// -//========================================================================== - -bool FMODSoundRenderer::ReconnectSFXReverbUnit() -{ - FMOD::DSP *unit; - FMOD_DSP_TYPE type; - int numinputs, i; - - if (ChannelGroupTargetUnit == NULL || SfxReverbPlaceholder == NULL) - { - return false; - } - // Look for SFX Reverb unit - if (FMOD_OK != ChannelGroupTargetUnit->getNumInputs(&numinputs)) - { - return false; - } - for (i = numinputs - 1; i >= 0; --i) - { - if (FMOD_OK == ChannelGroupTargetUnit->getInput(i, &unit, NULL) && - FMOD_OK == unit->getType(&type)) - { - if (type == FMOD_DSP_TYPE_SFXREVERB) - { - break; - } - } - } - if (i < 0) - { - return false; - } - - // Found it! Now move it in the DSP graph to be done before the water - // effect. - if (FMOD_OK != ChannelGroupTargetUnit->disconnectFrom(unit)) - { - return false; - } - if (FMOD_OK != SfxReverbPlaceholder->addInput(unit, NULL)) - { - return false; - } - return true; -} - -//========================================================================== -// -// FMODSoundRenderer :: Sync -// -// Used by the save/load code to restart sounds at the same position they -// were in at the time of saving. Must not be nested. -// -//========================================================================== - -void FMODSoundRenderer::Sync(bool sync) -{ - DSPLocked = sync; - if (sync) - { - Sys->lockDSP(); -#if FMOD_STUDIO - uint64_t clock; - SfxGroup->getDSPClock(&clock,NULL); - DSPClock.Lo = clock & 0xFFFFFFFF; - DSPClock.Hi = clock >> 32; -#else - Sys->getDSPClock(&DSPClock.Hi, &DSPClock.Lo); -#endif - } - else - { - Sys->unlockDSP(); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: UpdateSounds -// -//========================================================================== - -void FMODSoundRenderer::UpdateSounds() -{ - // Any sounds played between now and the next call to this function - // will start exactly one tic from now. -#if FMOD_STUDIO - uint64_t clock; - SfxGroup->getDSPClock(&clock,NULL); - DSPClock.Lo = clock & 0xFFFFFFFF; - DSPClock.Hi = clock >> 32; -#else - Sys->getDSPClock(&DSPClock.Hi, &DSPClock.Lo); -#endif - DSPClock.AsOne += OutputRate / TICRATE; - Sys->update(); -} - -//========================================================================== -// -// FMODSoundRenderer :: LoadSoundRaw -// -//========================================================================== - -std::pair FMODSoundRenderer::LoadSoundRaw(uint8_t *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) -{ - FMOD_CREATESOUNDEXINFO exinfo; - SoundHandle retval = { NULL }; - int numsamples; - - if (length <= 0) - { - return std::make_pair(retval, true); - } - - InitCreateSoundExInfo(&exinfo); - exinfo.length = length; - exinfo.numchannels = channels; - exinfo.defaultfrequency = frequency; - switch (bits) - { -#if FMOD_STUDIO - case -8: - // Need to convert sample data from signed to unsigned. - for (int i = 0; i < length; i++) - { - sfxdata[i] ^= 0x80; - } - - case 8: -#else // !FMOD_STUDIO - case 8: - // Need to convert sample data from unsigned to signed. - for (int i = 0; i < length; ++i) - { - sfxdata[i] = sfxdata[i] - 128; - } - - case -8: -#endif // FMOD_STUDIO - exinfo.format = FMOD_SOUND_FORMAT_PCM8; - numsamples = length; - break; - - case 16: - exinfo.format = FMOD_SOUND_FORMAT_PCM16; - numsamples = length >> 1; - break; - - case 32: - exinfo.format = FMOD_SOUND_FORMAT_PCM32; - numsamples = length >> 2; - break; - - default: - return std::make_pair(retval, true); - } - - const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_OPENRAW; - FMOD::Sound *sample; - FMOD_RESULT result; - - result = Sys->createSound((char *)sfxdata, samplemode, &exinfo, &sample); - if (result != FMOD_OK) - { - DPrintf(DMSG_ERROR, "Failed to allocate sample: Error %d\n", result); - return std::make_pair(retval, true); - } - - if (loopstart >= 0) - { - if (loopend == -1) - loopend = numsamples - 1; - sample->setLoopPoints(loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM); - } - - retval.data = sample; - return std::make_pair(retval, true); -} - -//========================================================================== -// -// FMODSoundRenderer :: LoadSound -// -//========================================================================== - -std::pair FMODSoundRenderer::LoadSound(uint8_t *sfxdata, int length, bool monoize) -{ - FMOD_CREATESOUNDEXINFO exinfo; - SoundHandle retval = { NULL }; - - if (length == 0) return std::make_pair(retval, true); - - InitCreateSoundExInfo(&exinfo); - exinfo.length = length; - - const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE; - FMOD::Sound *sample; - FMOD_RESULT result; - - result = Sys->createSound((char *)sfxdata, samplemode, &exinfo, &sample); - if (result != FMOD_OK) - { - DPrintf(DMSG_ERROR, "Failed to allocate sample: Error %d\n", result); - return std::make_pair(retval, true); - } - SetCustomLoopPts(sample); - retval.data = sample; - return std::make_pair(retval, true); -} - -//========================================================================== -// -// FMODSoundRenderer :: UnloadSound -// -//========================================================================== - -void FMODSoundRenderer::UnloadSound(SoundHandle sfx) -{ - if (sfx.data != NULL) - { - ((FMOD::Sound *)sfx.data)->release(); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: GetMSLength -// -//========================================================================== - -unsigned int FMODSoundRenderer::GetMSLength(SoundHandle sfx) -{ - if (sfx.data != NULL) - { - unsigned int length; - - if (((FMOD::Sound *)sfx.data)->getLength(&length, FMOD_TIMEUNIT_MS) == FMOD_OK) - { - return length; - } - } - return 0; // Don't know. -} - - -//========================================================================== -// -// FMODSoundRenderer :: GetMSLength -// -//========================================================================== - -unsigned int FMODSoundRenderer::GetSampleLength(SoundHandle sfx) -{ - if (sfx.data != NULL) - { - unsigned int length; - - if (((FMOD::Sound *)sfx.data)->getLength(&length, FMOD_TIMEUNIT_PCM) == FMOD_OK) - { - return length; - } - } - return 0; // Don't know. -} - - -//========================================================================== -// -// FMODSoundRenderer :: ChannelCallback static -// -// Handles when a channel finishes playing. This is only called when -// System::update is called and is therefore asynchronous with the actual -// end of the channel. -// -//========================================================================== - -FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelCallback -#if FMOD_STUDIO - (FMOD_CHANNELCONTROL *channel, FMOD_CHANNELCONTROL_TYPE controltype, FMOD_CHANNELCONTROL_CALLBACK_TYPE type, void *data1, void *data2) -#else - (FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *data1, void *data2) -#endif -{ -#if FMOD_STUDIO - FMOD::ChannelControl *chan = (FMOD::ChannelControl *)channel; -#else - FMOD::Channel *chan = (FMOD::Channel *)channel; -#endif - FISoundChannel *schan; - - if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) - { -#if FMOD_STUDIO - if (type == FMOD_CHANNELCONTROL_CALLBACK_END) -#else - if (type == FMOD_CHANNEL_CALLBACKTYPE_END) -#endif - { - S_ChannelEnded(schan); - } -#if FMOD_STUDIO - else if (type == FMOD_CHANNELCONTROL_CALLBACK_VIRTUALVOICE) -#else - else if (type == FMOD_CHANNEL_CALLBACKTYPE_VIRTUALVOICE) -#endif - { - S_ChannelVirtualChanged(schan, data1 != 0); - } - } - return FMOD_OK; -} - - -//========================================================================== -// -// FMODSoundRenderer :: RolloffCallback static -// -// Calculates a volume for the sound based on distance. -// -//========================================================================== - -#if FMOD_STUDIO -float F_CALLBACK FMODSoundRenderer::RolloffCallback(FMOD_CHANNELCONTROL *channel, float distance) -#else -float F_CALLBACK FMODSoundRenderer::RolloffCallback(FMOD_CHANNEL *channel, float distance) -#endif -{ -#if FMOD_STUDIO - FMOD::ChannelControl *chan = (FMOD::ChannelControl *)channel; -#else - FMOD::Channel *chan = (FMOD::Channel *)channel; -#endif - FISoundChannel *schan; - - if (GRolloff != NULL) - { - return S_GetRolloff(GRolloff, distance * GDistScale, true); - } - else if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) - { - return S_GetRolloff(&schan->Rolloff, distance * schan->DistanceScale, true); - } - else - { - return 0; - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawWaveDebug -// -// Bit 0: ( 1) Show oscilloscope for sfx. -// Bit 1: ( 2) Show spectrum for sfx. -// Bit 2: ( 4) Show oscilloscope for music. -// Bit 3: ( 8) Show spectrum for music. -// Bit 4: (16) Show oscilloscope for all sounds. -// Bit 5: (32) Show spectrum for all sounds. -// -//========================================================================== - -void FMODSoundRenderer::DrawWaveDebug(int mode) -{ - const int window_height = 100; - int window_size; - int numoutchans; - int y, yy; - const spk *labels; - int labelcount; - -#if FMOD_STUDIO - if (FMOD_OK != Sys->getSoftwareFormat(NULL, NULL, &numoutchans)) -#else - if (FMOD_OK != Sys->getSoftwareFormat(NULL, NULL, &numoutchans, NULL, NULL, NULL)) -#endif - { - return; - } - - // Decide on which set of labels to use. - labels = (numoutchans == 4) ? SpeakerNames4 : SpeakerNamesMore; - labelcount = MIN(numoutchans, countof(SpeakerNamesMore)); - - // Scale all the channel windows so one group fits completely on one row, with - // 16 pixels of padding between each window. - window_size = (screen->GetWidth() - 16) / numoutchans - 16; - - float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float)); - y = 16; - - yy = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode); - if (y != yy) - { - DrawSpeakerLabels(labels, yy-14, window_size, labelcount); - } - y = DrawChannelGroupOutput(MusicGroup, wavearray, window_size, window_height, yy, mode >> 2); - if (y != yy) - { - DrawSpeakerLabels(labels, y-14, window_size, labelcount); - } - yy = DrawSystemOutput(wavearray, window_size, window_height, y, mode >> 4); - if (y != yy) - { - DrawSpeakerLabels(labels, yy-14, window_size, labelcount); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawSpeakerLabels -// -//========================================================================== - -void FMODSoundRenderer::DrawSpeakerLabels(const spk *labels, int y, int width, int count) -{ - if (labels == NULL) - { - return; - } - for (int i = 0, x = 16; i < count; ++i) - { - screen->DrawText(SmallFont, CR_LIGHTBLUE, x, y, labels[i], TAG_DONE); - x += width + 16; - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawChannelGroupOutput -// -// Draws an oscilloscope and/or a spectrum for a channel group. -// -//========================================================================== - -int FMODSoundRenderer::DrawChannelGroupOutput(FMOD::ChannelGroup *group, float *wavearray, int width, int height, int y, int mode) -{ - int y1, y2; - - switch (mode & 0x03) - { - case 0x01: // Oscilloscope only - return DrawChannelGroupWaveData(group, wavearray, width, height, y, false); - - case 0x02: // Spectrum only - return DrawChannelGroupSpectrum(group, wavearray, width, height, y, false); - - case 0x03: // Oscilloscope + Spectrum - width = (width + 16) / 2 - 16; - y1 = DrawChannelGroupSpectrum(group, wavearray, width, height, y, true); - y2 = DrawChannelGroupWaveData(group, wavearray, width, height, y, true); - return MAX(y1, y2); - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawSystemOutput -// -// Like DrawChannelGroupOutput(), but uses the system object. -// -//========================================================================== - -int FMODSoundRenderer::DrawSystemOutput(float *wavearray, int width, int height, int y, int mode) -{ - int y1, y2; - - switch (mode & 0x03) - { - case 0x01: // Oscilloscope only - return DrawSystemWaveData(wavearray, width, height, y, false); - - case 0x02: // Spectrum only - return DrawSystemSpectrum(wavearray, width, height, y, false); - - case 0x03: // Oscilloscope + Spectrum - width = (width + 16) / 2 - 16; - y1 = DrawSystemSpectrum(wavearray, width, height, y, true); - y2 = DrawSystemWaveData(wavearray, width, height, y, true); - return MAX(y1, y2); - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawChannelGroupWaveData -// -// Draws all the output channels for a specified channel group. -// Setting skip to true causes it to skip every other window. -// -//========================================================================== - -int FMODSoundRenderer::DrawChannelGroupWaveData(FMOD::ChannelGroup *group, float *wavearray, int width, int height, int y, bool skip) -{ - int drawn = 0; - int x = 16; - -#if !FMOD_STUDIO - while (FMOD_OK == group->getWaveData(wavearray, width, drawn)) - { - drawn++; - DrawWave(wavearray, x, y, width, height); - x += (width + 16) << int(skip); - } -#endif - if (drawn) - { - y += height + 16; - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer::DrawSystemWaveData -// -// Like DrawChannelGroupWaveData, but it uses the system object to get the -// complete output. -// -//========================================================================== - -int FMODSoundRenderer::DrawSystemWaveData(float *wavearray, int width, int height, int y, bool skip) -{ - int drawn = 0; - int x = 16; - -#if !FMOD_STUDIO - while (FMOD_OK == Sys->getWaveData(wavearray, width, drawn)) - { - drawn++; - DrawWave(wavearray, x, y, width, height); - x += (width + 16) << int(skip); - } -#endif - if (drawn) - { - y += height + 16; - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawWave -// -// Draws an oscilloscope at the specified coordinates on the screen. Each -// entry in the wavearray buffer has its own column. IOW, there are -// entries in wavearray. -// -//========================================================================== - -void FMODSoundRenderer::DrawWave(float *wavearray, int x, int y, int width, int height) -{ - float scale = height / 2.f; - float mid = y + scale; - int i; - - // Draw a box around the oscilloscope. - screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200)); - - // Draw the actual oscilloscope. - if (screen->Accel2D) - { // Drawing this with lines is super-slow without hardware acceleration, at least with - // the debug build. - float lasty = mid - wavearray[0] * scale; - float newy; - for (i = 1; i < width; ++i) - { - newy = mid - wavearray[i] * scale; - screen->DrawLine(x + i - 1, int(lasty), x + i, int(newy), -1, MAKEARGB(255,255,248,248)); - lasty = newy; - } - } - else - { - for (i = 0; i < width; ++i) - { - float y = wavearray[i] * scale + mid; - screen->DrawPixel(x + i, int(y), -1, MAKEARGB(255,255,255,255)); - } - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawChannelGroupSpectrum -// -// Draws all the spectrum for a specified channel group. -// Setting skip to true causes it to skip every other window, starting at -// the second one. -// -//========================================================================== - -int FMODSoundRenderer::DrawChannelGroupSpectrum(FMOD::ChannelGroup *group, float *spectrumarray, int width, int height, int y, bool skip) -{ - int drawn = 0; - int x = 16; - - if (skip) - { - x += width + 16; - } - // TODO: FMOD Studio: Grab from DSP -#if !FMOD_STUDIO - while (FMOD_OK == group->getSpectrum(spectrumarray, SPECTRUM_SIZE, drawn, FMOD_DSP_FFT_WINDOW_TRIANGLE)) - { - drawn++; - DrawSpectrum(spectrumarray, x, y, width, height); - x += (width + 16) << int(skip); - } -#endif - if (drawn) - { - y += height + 16; - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer::DrawSystemSpectrum -// -// Like DrawChannelGroupSpectrum, but it uses the system object to get the -// complete output. -// -//========================================================================== - -int FMODSoundRenderer::DrawSystemSpectrum(float *spectrumarray, int width, int height, int y, bool skip) -{ - int drawn = 0; - int x = 16; - - if (skip) - { - x += width + 16; - } - // TODO: FMOD Studio: Grab from DSP -#if !FMOD_STUDIO - while (FMOD_OK == Sys->getSpectrum(spectrumarray, SPECTRUM_SIZE, drawn, FMOD_DSP_FFT_WINDOW_TRIANGLE)) - { - drawn++; - DrawSpectrum(spectrumarray, x, y, width, height); - x += (width + 16) << int(skip); - } -#endif - if (drawn) - { - y += height + 16; - } - return y; -} - -//========================================================================== -// -// FMODSoundRenderer :: DrawSpectrum -// -// Draws a spectrum at the specified coordinates on the screen. -// -//========================================================================== - -void FMODSoundRenderer::DrawSpectrum(float *spectrumarray, int x, int y, int width, int height) -{ - float scale = height / 2.f; - float mid = y + scale; - float db; - int top; - - // Draw a border and dark background for the spectrum. - screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200)); - screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200)); - screen->Dim(MAKERGB(0,0,0), 0.3f, x, y, width, height); - - // Draw the actual spectrum. - for (int i = 0; i < width; ++i) - { - db = spectrumarray[i * (SPECTRUM_SIZE - 2) / width + 1]; - db = MAX(-150.f, 10 * log10f(db) * 2); // Convert to decibels and clamp - db = 1.f - (db / -150.f); - db *= height; - top = (int)db; - if (top >= height) - { - top = height - 1; - } -// screen->Clear(x + i, int(y + height - db), x + i + 1, y + height, -1, MAKEARGB(255, 255, 255, 40)); - screen->Dim(MAKERGB(255,255,40), 0.65f, x + i, y + height - top, 1, top); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: DecodeSample -// -// Uses FMOD to decode a compressed sample to a 16-bit buffer. This is used -// by the DUMB XM reader to handle FMOD's OggMods. -// -//========================================================================== - -short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type) -{ - FMOD_CREATESOUNDEXINFO exinfo; - FMOD::Sound *sound; - FMOD_SOUND_FORMAT format; - int channels; - unsigned int len, amt_read; - FMOD_RESULT result; - short *outbuf; - - InitCreateSoundExInfo(&exinfo); - if (type == CODEC_Vorbis) - { - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; - } - exinfo.length = sizebytes; - result = Sys->createSound((const char *)coded, - FMOD_2D | FMOD_SOFTWARE | FMOD_CREATESTREAM | - FMOD_OPENMEMORY_POINT | FMOD_OPENONLY | FMOD_LOWMEM, - &exinfo, &sound); - if (result != FMOD_OK) - { - return NULL; - } - result = sound->getFormat(NULL, &format, &channels, NULL); - // TODO: Handle more formats if it proves necessary. - if (result != FMOD_OK || format != FMOD_SOUND_FORMAT_PCM16 || channels != 1) - { - sound->release(); - return NULL; - } - len = outlen; - // Must be malloc'ed for DUMB, which is C. - outbuf = (short *)malloc(len); - result = sound->readData(outbuf, len, &amt_read); - sound->release(); - if (result == FMOD_ERR_FILE_EOF) - { - memset((uint8_t *)outbuf + amt_read, 0, len - amt_read); - } - else if (result != FMOD_OK || amt_read != len) - { - free(outbuf); - return NULL; - } - return outbuf; -} - -//========================================================================== -// -// FMODSoundRenderer :: InitCreateSoundExInfo -// -// Allow for compiling with 4.26 APIs while still running with older DLLs. -// -//========================================================================== - -void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const -{ - memset(exinfo, 0, sizeof(*exinfo)); -#if !FMOD_STUDIO && FMOD_VERSION >= 0x42600 && FMOD_VERSION < 0x43800 - if (ActiveFMODVersion < 0x42600) - { - // This parameter was added for 4.26.00, and trying to pass it to older - // DLLs will fail. - exinfo->cbsize = myoffsetof(FMOD_CREATESOUNDEXINFO, ignoresetfilesystem); - } - else -#endif - { - exinfo->cbsize = sizeof(*exinfo); - } -} - -//========================================================================== -// -// FMODSoundRenderer :: SetSystemReverbProperties -// -// Set the global reverb properties. -// -//========================================================================== - -FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES *props) -{ -#if !FMOD_STUDIO && FMOD_VERSION < 0x43600 - return Sys->setReverbProperties((const FMOD_REVERB_PROPERTIES *)props); -#else - // The reverb format changed when hardware mixing support was dropped, because - // all EAX-only properties were removed from the structure. - FMOD_REVERB_PROPERTIES fr; - -#if FMOD_STUDIO - const float LateEarlyRatio = powf(10.f, (props->Reverb - props->Reflections)/2000.f); - const float EarlyAndLatePower = powf(10.f, props->Reflections/1000.f) + powf(10, props->Reverb/1000.f); - const float HFGain = powf(10.f, props->RoomHF/2000.f); - fr.DecayTime = props->DecayTime*1000.f; - fr.EarlyDelay = props->ReflectionsDelay*1000.f; - fr.LateDelay = props->ReverbDelay*1000.f; - fr.HFReference = props->HFReference; - fr.HFDecayRatio = clamp(props->DecayHFRatio*100.f, 0.f, 100.f); - fr.Diffusion = props->Diffusion; - fr.Density = props->Density; - fr.LowShelfFrequency = props->DecayLFRatio; - fr.LowShelfGain = clamp(props->RoomLF/100.f, -48.f, 12.f); - fr.HighCut = clamp(props->RoomLF < 0 ? props->HFReference/sqrtf((1.f-HFGain)/HFGain) : 20000.f, 20.f, 20000.f); - fr.EarlyLateMix = props->Reflections > -10000.f ? LateEarlyRatio/(LateEarlyRatio + 1)*100.f : 100.f; - fr.WetLevel = clamp(10*log10f(EarlyAndLatePower)+props->Room/100.f, -80.f, 20.f); - - return Sys->setReverbProperties(0, &fr); -#else - fr.Instance = props->Instance; - fr.Environment = props->Environment; - fr.EnvDiffusion = props->EnvDiffusion; - fr.Room = props->Room; - fr.RoomHF = props->RoomHF; - fr.RoomLF = props->RoomLF; - fr.DecayTime = props->DecayTime; - fr.DecayHFRatio = props->DecayHFRatio; - fr.DecayLFRatio = props->DecayLFRatio; - fr.Reflections = props->Reflections; - fr.ReflectionsDelay = props->ReflectionsDelay; - fr.Reverb = props->Reverb; - fr.ReverbDelay = props->ReverbDelay; - fr.ModulationTime = props->ModulationTime; - fr.ModulationDepth = props->ModulationDepth; - fr.HFReference = props->HFReference; - fr.LFReference = props->LFReference; - fr.Diffusion = props->Diffusion; - fr.Density = props->Density; - fr.Flags = props->Flags; - - return Sys->setReverbProperties(&fr); -#endif -#endif -} - -MIDIDevice* FMODSoundRenderer::CreateMIDIDevice() const -{ - return new SndSysMIDIDevice; -} - -#endif // NO_FMOD - - -//========================================================================== -// -// IsFModExPresent -// -// Check if FMod can be used -// -//========================================================================== - -bool IsFModExPresent() -{ -#ifdef NO_FMOD - return false; -#elif !defined _MSC_VER - return true; // on non-MSVC 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 -} diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h deleted file mode 100644 index d80423ebd..000000000 --- a/src/sound/fmodsound.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef FMODSOUND_H -#define FMODSOUND_H - -#include "i_sound.h" - -#ifndef NO_FMOD -#include "fmod_wrap.h" - -class FMODSoundRenderer : public SoundRenderer -{ -public: - FMODSoundRenderer (); - ~FMODSoundRenderer (); - bool IsValid (); - - void SetSfxVolume (float volume); - void SetMusicVolume (float volume); - std::pair LoadSound(uint8_t *sfxdata, int length, bool monoize); - std::pair LoadSoundRaw(uint8_t *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false); - void UnloadSound (SoundHandle sfx); - unsigned int GetMSLength(SoundHandle sfx); - unsigned int GetSampleLength(SoundHandle sfx); - float GetOutputRate(); - - // Streaming sounds. - SoundStream *CreateStream (SoundStreamCallback callback, int buffsamples, int flags, int samplerate, void *userdata); - SoundStream *OpenStream (FileReader *reader, int flags); - SoundStream *OpenStream (const char *url, int flags); - - // Starts a sound. - FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan); - 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); - - // Stops a sound channel. - void StopChannel (FISoundChannel *chan); - - // Changes a channel's volume. - void ChannelVolume (FISoundChannel *chan, float volume); - - // Marks a channel's start time without actually playing it. - void MarkStartTime (FISoundChannel *chan); - - // Returns position of sound on this channel, in samples. - unsigned int GetPosition(FISoundChannel *chan); - - // Gets a channel's audibility (real volume). - float GetAudibility(FISoundChannel *chan); - - // Synchronizes following sound startups. - void Sync (bool sync); - - // Pauses or resumes all sound effect channels. - void SetSfxPaused (bool paused, int slot); - - // Pauses or resumes *every* channel, including environmental reverb. - void SetInactive (EInactiveState inactive); - - // Updates the position of a sound channel. - void UpdateSoundParams3D (SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel); - - void UpdateListener (SoundListener *listener); - void UpdateSounds (); - - void PrintStatus (); - void PrintDriversList (); - FString GatherStats (); - short *DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type); - - void DrawWaveDebug(int mode); - - virtual MIDIDevice* CreateMIDIDevice() const override; - -private: - uint32_t ActiveFMODVersion; - int SFXPaused; - bool InitSuccess; - bool DSPLocked; - QWORD_UNION DSPClock; - int OutputRate; - -#if FMOD_STUDIO - static FMOD_RESULT F_CALLBACK ChannelCallback(FMOD_CHANNELCONTROL *channel, FMOD_CHANNELCONTROL_TYPE controltype, FMOD_CHANNELCONTROL_CALLBACK_TYPE type, void *data1, void *data2); - static float F_CALLBACK RolloffCallback(FMOD_CHANNELCONTROL *channel, float distance); -#else - static FMOD_RESULT F_CALLBACK ChannelCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *data1, void *data2); - static float F_CALLBACK RolloffCallback(FMOD_CHANNEL *channel, float distance); -#endif - - bool HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, int flags, float freq) const; - FISoundChannel *CommonChannelSetup(FMOD::Channel *chan, FISoundChannel *reuse_chan) const; - FMOD_MODE SetChanHeadSettings(SoundListener *listener, FMOD::Channel *chan, const FVector3 &pos, bool areasound, FMOD_MODE oldmode) const; - - bool ReconnectSFXReverbUnit(); - void InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const; - FMOD_RESULT SetSystemReverbProperties(const REVERB_PROPERTIES *props); - - bool Init (); - void Shutdown (); -#if !FMOD_STUDIO - void DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int maxfrequency); -#endif - - int DrawChannelGroupOutput(FMOD::ChannelGroup *group, float *wavearray, int width, int height, int y, int mode); - int DrawSystemOutput(float *wavearray, int width, int height, int y, int mode); - - int DrawChannelGroupWaveData(FMOD::ChannelGroup *group, float *wavearray, int width, int height, int y, bool skip); - int DrawSystemWaveData(float *wavearray, int width, int height, int y, bool skip); - void DrawWave(float *wavearray, int x, int y, int width, int height); - - int DrawChannelGroupSpectrum(FMOD::ChannelGroup *group, float *wavearray, int width, int height, int y, bool skip); - int DrawSystemSpectrum(float *wavearray, int width, int height, int y, bool skip); - void DrawSpectrum(float *spectrumarray, int x, int y, int width, int height); - - typedef char spk[4]; - static const spk SpeakerNames4[4], SpeakerNamesMore[8]; - void DrawSpeakerLabels(const spk *labels, int y, int width, int count); - - FMOD::System *Sys; - FMOD::ChannelGroup *SfxGroup, *PausableSfx; - FMOD::ChannelGroup *MusicGroup; - FMOD::DSP *WaterLP, *WaterReverb; - FMOD::DSPConnection *SfxConnection; - FMOD::DSPConnection *ChannelGroupTargetUnitOutput; - FMOD::DSP *ChannelGroupTargetUnit; - FMOD::DSP *SfxReverbPlaceholder; - bool SfxReverbHooked; - float LastWaterLP; - unsigned int OutputPlugin; - - // Just for snd_status display - int Driver_MinFrequency; - int Driver_MaxFrequency; -#if !FMOD_STUDIO - FMOD_CAPS Driver_Caps; -#endif - - friend class FMODStreamCapsule; -}; - -#endif -#endif diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index af848cbeb..a31c4de74 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -184,9 +184,6 @@ void I_ShutdownMusic(bool onexit) } Timidity::FreeAll(); if (onexit) WildMidi_Shutdown(); -#ifdef _WIN32 - I_ShutdownMusicWin32(); -#endif // _WIN32 } void I_ShutdownMusicExit() diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 227464c11..6cb2e05a2 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -10,7 +10,6 @@ #include "wildmidi/wildmidi_lib.h" void I_InitMusicWin32 (); -void I_ShutdownMusicWin32 (); extern float relative_volume; diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 42e5a8d7d..74445a98c 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -39,7 +39,6 @@ #include "doomtype.h" #include -#include "fmodsound.h" #include "oalsound.h" #include "mpg123_decoder.h" @@ -68,9 +67,7 @@ CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -#ifndef NO_FMOD -#define DEF_BACKEND "fmod" -#elif !defined(NO_OPENAL) +#if !defined(NO_OPENAL) #define DEF_BACKEND "openal" #else #define DEF_BACKEND "null" @@ -259,29 +256,10 @@ void I_InitSound () 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; - } - #endif - #ifndef NO_OPENAL - if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent()) - { - Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n"); - I_CloseSound(); - GSnd = new OpenALSoundRenderer; - snd_backend = "openal"; - } - #endif - } else if(stricmp(snd_backend, "openal") == 0) { #ifndef NO_OPENAL @@ -290,15 +268,6 @@ void I_InitSound () GSnd = new OpenALSoundRenderer; } #endif - #ifndef NO_FMOD - if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent()) - { - Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n"); - I_CloseSound(); - GSnd = new FMODSoundRenderer; - snd_backend = "fmod"; - } - #endif } else { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 5f1917d68..97d81d9dc 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -177,7 +177,6 @@ FISoundChannel *S_GetChannel(void *syschan); extern ReverbContainer *DefaultEnvironments[26]; -bool IsFModExPresent(); bool IsOpenALPresent(); #endif diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index 4e3708eb4..42e8ab863 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -96,23 +96,6 @@ void I_InitMusicWin32 () snd_mididevice.Callback (); } -void I_ShutdownMusicWin32 () -{ - // Ancient bug a saw on NT 4.0 and an old version of FMOD 3: If waveout - // is used for sound and a MIDI is also played, then when I quit, the OS - // tells me a free block was modified after being freed. This is - // apparently a synchronization issue between two threads, because if I - // put this Sleep here after stopping the music but before shutting down - // the entire sound system, the error does not happen. Observed with a - // Vortex 2 (may Aureal rest in peace) and an Audigy (damn you, Creative!). - // I no longer have a system with NT4 drivers, so I don't know if this - // workaround is still needed or not. - if (OSPlatform == os_WinNT4) - { - Sleep(50); - } -} - void I_BuildMIDIMenuList (FOptionValues *opt) { AddDefaultMidiDevices(opt); diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index d38435be1..f173903ec 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -630,7 +630,7 @@ public: }; -extern ReverbContainer *ForcedEnvironment; +ReverbContainer *ForcedEnvironment; #define AREA_SOUND_RADIUS (32.f) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 550a94634..8e8572b2f 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2128,23 +2128,11 @@ SNDMNU_UNDERWATERREVERB = "Underwater reverb"; SNDMNU_RANDOMIZEPITCHES = "Randomize pitches"; SNDMNU_CHANNELS = "Sound channels"; SNDMNU_BACKEND = "Sound backend"; -SNDMNU_FMOD = "FMOD options"; SNDMNU_OPENAL = "OpenAL options"; SNDMNU_RESTART = "Restart sound"; SNDMNU_ADVANCED = "Advanced options"; SNDMNU_MODREPLAYER = "Module replayer options"; -// Fmod Options -FMODMNU_TITLE = "FMOD OPTIONS"; -FMODMNU_WATERCUTOFF = "Underwater cutoff"; -FMODMNU_OUTPUTSYSTEM = "Output system"; -FMODMNU_OUTPUTFORMAT = "Output format"; -FMODMNU_SPEAKERMODE = "Speaker mode"; -FMODMNU_RESAMPLER = "Resampler"; -FMODMNU_HRTFFILTER = "HRTF filter"; -FMODMNU_BUFFERSIZE = "Buffer size"; -FMODMNU_BUFFERCOUNT = "Buffer count"; - // OpenAL Options OPENALMNU_TITLE = "OPENAL OPTIONS"; OPENALMNU_PLAYBACKDEVICE = "Playback device"; @@ -2428,7 +2416,6 @@ OPTSTR_5POINT1 = "5.1 speakers"; OPTSTR_7POINT1 = "7.1 speakers"; OPTSTR_NOINTERPOLATION = "No interpolation"; OPTSTR_SPLINE = "Spline"; -OPTSTR_FMOD = "FMOD Ex"; OPTSTR_OPENAL = "OpenAL"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 3c9c88759..c5e3820af 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1557,51 +1557,12 @@ OptionString Resamplers } -OptionString SoundBackends -{ - "fmod", "$OPTSTR_FMOD" - "openal", "$OPTSTR_OPENAL" - "null", "$OPTSTR_NOSOUND" -} - -OptionString SoundBackendsFModOnly -{ - "fmod", "$OPTSTR_FMOD" - "null", "$OPTSTR_NOSOUND" -} - OptionString SoundBackendsOpenALOnly { "openal", "$OPTSTR_OPENAL" "null", "$OPTSTR_NOSOUND" } -OptionMenu FMODSoundItems -{ - Title "$FMODMNU_TITLE" - Slider "$FMODMNU_WATERCUTOFF", "snd_waterlp", 0.0, 2000.0, 50.0, 0 - IfOption(Windows) - { - Option "$FMODMNU_OUTPUTSYSTEM", "snd_output", "SoundOutputsWindows" - } - IfOption(Unix) - { - Option "$FMODMNU_OUTPUTSYSTEM", "snd_output", "SoundOutputsUnix" - } - IfOption(Mac) - { - Option "$FMODMNU_OUTPUTSYSTEM", "snd_output", "SoundOutputsMac" - } - Option "$FMODMNU_OUTPUTFORMAT", "snd_output_format", "OutputFormats" - Option "$FMODMNU_SPEAKERMODE", "snd_speakermode", "SpeakerModes" - Option "$FMODMNU_RESAMPLER", "snd_resampler", "Resamplers" - Option "$FMODMNU_HRTFFILTER", "snd_hrtf", "OnOff" - StaticText " " - Option "$FMODMNU_BUFFERSIZE", "snd_buffersize", "BufferSizes" - Option "$FMODMNU_BUFFERCOUNT", "snd_buffercount", "BufferCounts" -} - - OptionMenu OpenALSoundItems { Title "$OPENALMNU_TITLE" @@ -1628,31 +1589,9 @@ OptionMenu SoundOptions Slider "$SNDMNU_CHANNELS", "snd_channels", 64, 256, 8, 0 StaticText " " - ifoption(fmodex) - { - ifoption(openal) - { - Option "$SNDMNU_BACKEND", "snd_backend", "SoundBackends" - } - else - { - Option "$SNDMNU_BACKEND", "snd_backend", "SoundBackendsFModOnly" - } - } - else - { - ifoption(openal) - { - Option "$SNDMNU_BACKEND", "snd_backend", "SoundBackendsOpenALOnly" - } - } - - ifoption(fmodex) - { - Submenu "$SNDMNU_FMOD", "FMODSoundItems" - } ifoption(openal) { + Option "$SNDMNU_BACKEND", "snd_backend", "SoundBackendsOpenALOnly" Submenu "$SNDMNU_OPENAL", "OpenALSoundItems" } StaticText " "