diff options
Diffstat (limited to 'indra')
28 files changed, 1269 insertions, 1503 deletions
| diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index a21fa90950..88e1f4a686 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -29,7 +29,8 @@ set(cmake_SOURCE_FILES      FindAutobuild.cmake      FindBerkeleyDB.cmake      FindCARes.cmake -    FindFMOD.cmake +    FindELFIO.cmake +    FindFMODEX.cmake      FindGLH.cmake      FindGoogleBreakpad.cmake      FindGooglePerfTools.cmake @@ -40,6 +41,7 @@ set(cmake_SOURCE_FILES      FindSCP.cmake      FindXmlRpcEpi.cmake      FindZLIB.cmake +    FMODEX.cmake      FreeType.cmake      GLEXT.cmake      GLH.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 338da4743e..ef529c32d3 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -62,10 +62,9 @@ if(WINDOWS)        set(release_files ${release_files} libtcmalloc_minimal.dll)      endif(USE_TCMALLOC) -    if (FMOD) -      set(debug_files ${debug_files} fmod.dll) -      set(release_files ${release_files} fmod.dll) -    endif (FMOD) +    if (FMODEX) +      set(release_files ${release_files} fmodex.dll) +    endif (FMODEX)  #*******************************  # Copy MS C runtime dlls, required for packaging. @@ -222,8 +221,10 @@ elseif(DARWIN)          libcollada14dom.dylib         ) -    # fmod is statically linked on darwin -    set(fmod_files "") +    if (FMODEX) +      set(debug_files ${debug_files} libfmodexL.dylib) +      set(release_files ${release_files} libfmodex.dylib) +    endif (FMODEX)  elseif(LINUX)      # linux is weird, multiple side by side configurations aren't supported @@ -288,9 +289,9 @@ elseif(LINUX)        set(release_files ${release_files} "libtcmalloc_minimal.so")      endif (USE_TCMALLOC) -    if (FMOD) -      set(release_files ${release_files} "libfmod-3.75.so") -    endif (FMOD) +    if (FMODEX) +      set(release_file ${release_files} "libfmodex.so") +    endif (FMODEX)  else(WINDOWS)      message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") @@ -305,8 +306,6 @@ else(WINDOWS)      set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/release")      set(release_files "") -    set(fmod_files "") -      set(debug_llkdu_src "")      set(debug_llkdu_dst "")      set(release_llkdu_src "") @@ -369,30 +368,6 @@ copy_if_different(      )  set(third_party_targets ${third_party_targets} ${out_targets}) -if (FMOD_SDK_DIR) -    copy_if_different( -        ${FMOD_SDK_DIR}  -        "${CMAKE_CURRENT_BINARY_DIR}/Debug" -        out_targets  -        ${fmod_files} -        ) -    set(all_targets ${all_targets} ${out_targets}) -    copy_if_different( -        ${FMOD_SDK_DIR}  -        "${CMAKE_CURRENT_BINARY_DIR}/Release" -        out_targets  -        ${fmod_files} -        ) -    set(all_targets ${all_targets} ${out_targets}) -    copy_if_different( -        ${FMOD_SDK_DIR}  -        "${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo" -        out_targets  -        ${fmod_files} -        ) -    set(all_targets ${all_targets} ${out_targets}) -endif (FMOD_SDK_DIR) -  if(NOT STANDALONE)    add_custom_target(        stage_third_party_libs ALL diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake deleted file mode 100644 index 3586c1160a..0000000000 --- a/indra/cmake/FMOD.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# -*- cmake -*- - -# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON -# When building using proprietary binaries though (i.e. having access to LL private servers), -# we always build with FMOD. -# Open source devs should use the -DFMOD:BOOL=ON then if they want to build with FMOD, whether -# they are using STANDALONE or not. -if (INSTALL_PROPRIETARY) -  set(FMOD ON CACHE BOOL "Use FMOD sound library.") -endif (INSTALL_PROPRIETARY) - -if (FMOD) -  if (STANDALONE) -    # In that case, we use the version of the library installed on the system -    set(FMOD_FIND_REQUIRED ON) -    include(FindFMOD) -  else (STANDALONE) -    if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) -      # If the path have been specified in the arguments, use that -      set(FMOD_LIBRARIES ${FMOD_LIBRARY}) -      MESSAGE(STATUS "Using FMOD path: ${FMOD_LIBRARIES}, ${FMOD_INCLUDE_DIR}") -    else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) -      # If not, we're going to try to get the package listed in autobuild.xml -      # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)  -      # as accessing the private LL location will fail if you don't have the credential -      include(Prebuilt) -      use_prebuilt_binary(fmod)     -      if (WINDOWS) -        set(FMOD_LIBRARY fmod) -      elseif (DARWIN) -        set(FMOD_LIBRARY fmod) -      elseif (LINUX) -        set(FMOD_LIBRARY fmod-3.75) -      endif (WINDOWS) -      set(FMOD_LIBRARIES ${FMOD_LIBRARY}) -      set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) -    endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) -  endif (STANDALONE) -endif (FMOD) diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake new file mode 100644 index 0000000000..448392437a --- /dev/null +++ b/indra/cmake/FMODEX.cmake @@ -0,0 +1,45 @@ +# -*- cmake -*- + +# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with FMODEX. +# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether +# they are using STANDALONE or not. +if (INSTALL_PROPRIETARY) +  set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.") +endif (INSTALL_PROPRIETARY) + +if (FMODEX) +  if (STANDALONE) +    # In that case, we use the version of the library installed on the system +    set(FMODEX_FIND_REQUIRED ON) +    include(FindFMODEX) +  else (STANDALONE) +    if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +      # If the path have been specified in the arguments, use that +      set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) +      MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}") +    else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +      # If not, we're going to try to get the package listed in autobuild.xml +      # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)  +      # as accessing the private LL location will fail if you don't have the credential +      include(Prebuilt) +      use_prebuilt_binary(fmodex)     +      if (WINDOWS) +        set(FMODEX_LIBRARY  +            debug fmodexL_vc +            optimized fmodex_vc) +      elseif (DARWIN) +        set(FMODEX_LIBRARY  +            debug fmodexL +            optimized fmodex) +      elseif (LINUX) +        set(FMODEX_LIBRARY  +            debug fmodexL +            optimized fmodex) +      endif (WINDOWS) +      set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) +      set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex) +    endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +  endif (STANDALONE) +endif (FMODEX)
\ No newline at end of file diff --git a/indra/cmake/FindFMOD.cmake b/indra/cmake/FindFMOD.cmake deleted file mode 100644 index 1ebbc8c96e..0000000000 --- a/indra/cmake/FindFMOD.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# -*- cmake -*- - -# - Find FMOD -# Find the FMOD includes and library -# This module defines -#  FMOD_INCLUDE_DIR, where to find fmod.h and fmod_errors.h -#  FMOD_LIBRARIES, the libraries needed to use FMOD. -#  FMOD, If false, do not try to use FMOD. -# also defined, but not for general use are -#  FMOD_LIBRARY, where to find the FMOD library. - -FIND_PATH(FMOD_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod) - -SET(FMOD_NAMES ${FMOD_NAMES} fmod fmodvc fmodex fmod-3.75) -FIND_LIBRARY(FMOD_LIBRARY -  NAMES ${FMOD_NAMES} -  PATH_SUFFIXES fmod -  ) - -IF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) -  SET(FMOD_LIBRARIES ${FMOD_LIBRARY}) -  SET(FMOD_FOUND "YES") -ELSE (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) -  SET(FMOD_FOUND "NO") -ENDIF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - -IF (FMOD_FOUND) -  IF (NOT FMOD_FIND_QUIETLY) -    MESSAGE(STATUS "Found FMOD: ${FMOD_LIBRARIES}") -  ENDIF (NOT FMOD_FIND_QUIETLY) -ELSE (FMOD_FOUND) -  IF (FMOD_FIND_REQUIRED) -    MESSAGE(FATAL_ERROR "Could not find FMOD library") -  ENDIF (FMOD_FIND_REQUIRED) -ENDIF (FMOD_FOUND) - -# Deprecated declarations. -SET (NATIVE_FMOD_INCLUDE_PATH ${FMOD_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_FMOD_LIB_PATH ${FMOD_LIBRARY} PATH) - -MARK_AS_ADVANCED( -  FMOD_LIBRARY -  FMOD_INCLUDE_DIR -  ) diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake new file mode 100644 index 0000000000..9b9b85d73e --- /dev/null +++ b/indra/cmake/FindFMODEX.cmake @@ -0,0 +1,66 @@ +# -*- cmake -*- + +# - Find FMODEX +# Find the FMODEX includes and library +# This module defines +#  FMODEX_INCLUDE_DIR, where to find fmod.h and fmod_errors.h +#  FMODEX_LIBRARIES, the libraries needed to use FMODEX. +#  FMODEX, If false, do not try to use FMODEX. +# also defined, but not for general use are +#  FMODEX_LIBRARY, where to find the FMODEX library. + +FIND_PATH(FMODEX_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod) + +SET(FMODEX_NAMES ${FMODEX_NAMES} fmodex fmodvc fmodexL_vc) +FIND_LIBRARY(FMODEX_LIBRARY +  NAMES ${FMODEX_NAMES} +  PATH_SUFFIXES fmodex +  ) + +IF (FMODEX_SDK_DIR OR WINDOWS) +    if(WINDOWS) +        set(FMODEX_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODEX") +        STRING(REGEX REPLACE "\\\\" "/" FMODEX_SDK_DIR ${FMODEX_SDK_DIR})  +    endif(WINDOWS) +    find_library(FMODEX_LIBRARY +             fmodex_vc fmodexL_vc  +             PATHS +             ${FMODEX_SDK_DIR}/api/lib +             ${FMODEX_SDK_DIR}/api +             ${FMODEX_SDK_DIR} +             ) +    find_path(FMODEX_INCLUDE_DIR fmod.h +        ${FMODEX_SDK_DIR}/api/inc +        ${FMODEX_SDK_DIR}/api +        ${FMODEX_SDK_DIR} +      ) +    find_path(FMODEX_INCLUDE_DIR fmod.h +        ${FMODEX_SDK_DIR}/api/inc +        ${FMODEX_SDK_DIR}/api +        ${FMODEX_SDK_DIR} +      ) +    IF (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +      SET(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) +      SET(FMODEX_FOUND "YES") +    endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +ENDIF (FMODEX_SDK_DIR OR WINDOWS) + +IF (FMODEX_FOUND) +  IF (NOT FMODEX_FIND_QUIETLY) +    MESSAGE(STATUS "Found FMODEX: ${FMODEX_LIBRARIES}") +  ENDIF (NOT FMODEX_FIND_QUIETLY) +ELSE (FMODEX_FOUND) +  IF (FMODEX_FIND_REQUIRED) +    MESSAGE(FATAL_ERROR "Could not find FMODEX library") +  ENDIF (FMODEX_FIND_REQUIRED) +ENDIF (FMODEX_FOUND) + +# Deprecated declarations. +SET (NATIVE_FMODEX_INCLUDE_PATH ${FMODEX_INCLUDE_DIR} ) +GET_FILENAME_COMPONENT (NATIVE_FMODEX_LIB_PATH ${FMODEX_LIBRARY} PATH) + +MARK_AS_ADVANCED( +  FMODEX_LIBRARY +  FMODEX_INCLUDE_DIR +  ) +  
\ No newline at end of file diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 24d2531106..1b2bdb9888 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -5,7 +5,7 @@ project(llaudio)  include(00-Common)  include(Audio)  include(LLAudio) -include(FMOD) +include(FMODEX)  include(OPENAL)  include(LLCommon)  include(LLMath) @@ -24,7 +24,6 @@ include_directories(      ${VORBIS_INCLUDE_DIRS}      ${OPENAL_LIB_INCLUDE_DIRS}      ${FREEAULT_LIB_INCLUDE_DIRS} -    ${FMOD_INCLUDE_DIR}      )  set(llaudio_SOURCE_FILES @@ -44,29 +43,22 @@ set(llaudio_HEADER_FILES      llwindgen.h      ) -if (FMOD) +if (FMODEX)      include_directories( -        ${FMOD_INCLUDE_DIR} +        ${FMODEX_INCLUDE_DIR}          ) -      list(APPEND llaudio_SOURCE_FILES -         llaudioengine_fmod.cpp -         lllistener_fmod.cpp -         llstreamingaudio_fmod.cpp +         llaudioengine_fmodex.cpp +         lllistener_fmodex.cpp +         llstreamingaudio_fmodex.cpp           )      list(APPEND llaudio_HEADER_FILES -         llaudioengine_fmod.h -         lllistener_fmod.h -         llstreamingaudio_fmod.h +         llaudioengine_fmodex.h +         lllistener_fmodex.h +         llstreamingaudio_fmodex.h           ) - -    if (LINUX OR DARWIN) -      set_source_files_properties(llaudioengine_fmod.cpp -                                  llstreamingaudio_fmod.cpp -                                  COMPILE_FLAGS -Wno-write-strings) -    endif (LINUX OR DARWIN) -endif (FMOD) +endif (FMODEX)  if (OPENAL)    list(APPEND llaudio_SOURCE_FILES diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 99b96c3c38..da1629a1db 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -42,7 +42,6 @@  #include "lllistener.h"  const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; -const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f;			//  How much sounds are weaker under water  const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;  const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f; diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp deleted file mode 100644 index a40de9fa68..0000000000 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ /dev/null @@ -1,781 +0,0 @@ -/**  - * @file audioengine_fmod.cpp - * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llstreamingaudio.h" -#include "llstreamingaudio_fmod.h" - -#include "llaudioengine_fmod.h" -#include "lllistener_fmod.h" - -#include "llerror.h" -#include "llmath.h" -#include "llrand.h" - -#include "fmod.h" -#include "fmod_errors.h" -#include "lldir.h" -#include "llapr.h" - -#include "sound_ids.h" - - -extern "C" { -	void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); -} - - -LLAudioEngine_FMOD::LLAudioEngine_FMOD() -{ -	mInited = false; -	mWindGen = NULL; -	mWindDSP = NULL; -} - - -LLAudioEngine_FMOD::~LLAudioEngine_FMOD() -{ -} - - -bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) -{ -	LLAudioEngine::init(num_channels, userdata); - -	// Reserve one extra channel for the http stream. -	if (!FSOUND_SetMinHardwareChannels(num_channels + 1)) -	{ -		LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -	} - -	LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL; - -	F32 version = FSOUND_GetVersion(); -	if (version < FMOD_VERSION) -	{ -		LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version -			<< ")!  You should be using FMOD " << FMOD_VERSION << LL_ENDL; -		//return false; -	} - -	U32 fmod_flags = 0x0; - -#if LL_WINDOWS -	// Windows needs to know which window is frontmost. -	// This must be called before FSOUND_Init() per the FMOD docs. -	// This could be used to let FMOD handle muting when we lose focus, -	// but we don't actually want to do that because we want to distinguish -	// between minimized and not-focused states. -	if (!FSOUND_SetHWND(userdata)) -	{ -		LL_WARNS("AppInit") << "Error setting FMOD window: " -			<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -		return false; -	} -	// Play audio when we don't have focus. -	// (For example, IM client on top of us.) -	// This means we also try to play audio when minimized, -	// so we manually handle muting in that case. JC -	fmod_flags |= FSOUND_INIT_GLOBALFOCUS; -#endif - -#if LL_LINUX -	// initialize the FMOD engine - -	// This is a hack to use only FMOD's basic FPU mixer -	// when the LL_VALGRIND environmental variable is set, -	// otherwise valgrind will fall over on FMOD's MMX detection -	if (getenv("LL_VALGRIND"))		/*Flawfinder: ignore*/ -	{ -		LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL; -		FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU); -	} - -	// If we don't set an output method, Linux FMOD always -	// decides on OSS and fails otherwise.  So we'll manually -	// try ESD, then OSS, then ALSA. -	// Why this order?  See SL-13250, but in short, OSS emulated -	// on top of ALSA is ironically more reliable than raw ALSA. -	// Ack, and ESD has more reliable failure modes - but has worse -	// latency - than all of them, so wins for now. -	bool audio_ok = false; - -	if (!audio_ok) -	{ -		if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/ -		{ -			LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; -			if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) && -			   FSOUND_Init(44100, num_channels, fmod_flags)) -			{ -				LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" -					<< LL_ENDL; -				audio_ok = true; -			} else { -				LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " -					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -			} -		} else { -			LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL; -		} -	} -	if (!audio_ok) -	{ -		if (NULL == getenv("LL_BAD_FMOD_OSS")) 	 /*Flawfinder: ignore*/ -		{ -			LL_DEBUGS("AppInit") << "Trying OSS audio output..."	<< LL_ENDL; -			if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) && -			   FSOUND_Init(44100, num_channels, fmod_flags)) -			{ -				LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; -				audio_ok = true; -			} else { -				LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " -					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -			} -		} else { -			LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; -		} -	} -	if (!audio_ok) -	{ -		if (NULL == getenv("LL_BAD_FMOD_ALSA"))		/*Flawfinder: ignore*/ -		{ -			LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; -			if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) && -			   FSOUND_Init(44100, num_channels, fmod_flags)) -			{ -				LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; -				audio_ok = true; -			} else { -				LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " -					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -			} -		} else { -			LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; -		} -	} -	if (!audio_ok) -	{ -		LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; -		return false; -	} - -	// On Linux, FMOD causes a SIGPIPE for some netstream error -	// conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us. -	// NOW FIXED in FMOD 3.x since 2006-10-01. -	//signal(SIGPIPE, SIG_IGN); - -	// We're interested in logging which output method we -	// ended up with, for QA purposes. -	switch (FSOUND_GetOutput()) -	{ -	case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; -	case FSOUND_OUTPUT_OSS:	LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break; -	case FSOUND_OUTPUT_ESD:	LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break; -	case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; -	default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; -	}; - -#else // LL_LINUX - -	// initialize the FMOD engine -	if (!FSOUND_Init(44100, num_channels, fmod_flags)) -	{ -		LL_WARNS("AppInit") << "Error initializing FMOD: " -			<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -		return false; -	} -	 -#endif - -	// set up our favourite FMOD-native streaming audio implementation if none has already been added -	if (!getStreamingAudioImpl()) // no existing implementation added -		setStreamingAudioImpl(new LLStreamingAudio_FMOD()); - -	LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; - -	mInited = true; - -	return true; -} - - -std::string LLAudioEngine_FMOD::getDriverName(bool verbose) -{ -	if (verbose) -	{ -		F32 version = FSOUND_GetVersion(); -		return llformat("FMOD version %f", version); -	} -	else -	{ -		return "FMOD"; -	} -} - - -void LLAudioEngine_FMOD::allocateListener(void) -{	 -	mListenerp = (LLListener *) new LLListener_FMOD(); -	if (!mListenerp) -	{ -		llwarns << "Listener creation failed" << llendl; -	} -} - - -void LLAudioEngine_FMOD::shutdown() -{ -	if (mWindDSP) -	{ -		FSOUND_DSP_SetActive(mWindDSP,false); -		FSOUND_DSP_Free(mWindDSP); -	} - -	stopInternetStream(); - -	LLAudioEngine::shutdown(); -	 -	llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl; -	FSOUND_Close(); -	llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl; - -	delete mListenerp; -	mListenerp = NULL; -} - - -LLAudioBuffer * LLAudioEngine_FMOD::createBuffer() -{ -	return new LLAudioBufferFMOD(); -} - - -LLAudioChannel * LLAudioEngine_FMOD::createChannel() -{ -	return new LLAudioChannelFMOD(); -} - - -bool LLAudioEngine_FMOD::initWind() -{ -	if (!mWindGen) -	{ -		bool enable; -		 -		switch (FSOUND_GetMixer()) -		{ -			case FSOUND_MIXER_MMXP5: -			case FSOUND_MIXER_MMXP6: -			case FSOUND_MIXER_QUALITY_MMXP5: -			case FSOUND_MIXER_QUALITY_MMXP6: -				enable = (typeid(MIXBUFFERFORMAT) == typeid(S16)); -				break; -			case FSOUND_MIXER_BLENDMODE: -				enable = (typeid(MIXBUFFERFORMAT) == typeid(S32)); -				break; -			case FSOUND_MIXER_QUALITY_FPU: -				enable = (typeid(MIXBUFFERFORMAT) == typeid(F32)); -				break; -			default: -				// FSOUND_GetMixer() does not return a valid mixer type on Darwin -				LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL; -				enable = true; -				break; -		} -		 -		if (enable) -		{ -			mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate()); -		} -		else -		{ -			LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL; -		} -	} - -	mNextWindUpdate = 0.0; - -	if (mWindGen && !mWindDSP) -	{ -		mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); -	} -	if (mWindDSP) -	{ -		FSOUND_DSP_SetActive(mWindDSP, true); -		return true; -	} -	 -	return false; -} - - -void LLAudioEngine_FMOD::cleanupWind() -{ -	if (mWindDSP) -	{ -		FSOUND_DSP_SetActive(mWindDSP, false); -		FSOUND_DSP_Free(mWindDSP); -		mWindDSP = NULL; -	} - -	delete mWindGen; -	mWindGen = NULL; -} - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) -{ -	LLVector3 wind_pos; -	F64 pitch; -	F64 center_freq; - -	if (!mEnableWind) -	{ -		return; -	} -	 -	if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) -	{ -		 -		// wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) -		// need to convert this to the conventional orientation DS3D and OpenAL use -		// where +X = right, +Y = up, +Z = backwards - -		wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - -		// cerr << "Wind update" << endl; - -		pitch = 1.0 + mapWindVecToPitch(wind_vec); -		center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); -		 -		mWindGen->mTargetFreq = (F32)center_freq; -		mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; -		mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); -  	} -} - -/* -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance) -{ -	if (!mInited) -	{ -		return; -	} -	if (mBuffer[source_num]) -	{ -		mMinDistance[source_num] = (F32) distance; -		if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) -		{ -			llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -	} -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance) -{ -	if (!mInited) -	{ -		return; -	} -	if (mBuffer[source_num]) -	{ -		mMaxDistance[source_num] = (F32) distance; -		if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) -		{ -			llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -	} -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist) -{ -	*volume = 0; -	*freq = 0; -	*inside = 0; -	*outside = 0; -	*orient = LLVector3::zero; -	*out_volume = 0; -	*min_dist = 0.f; -	*max_dist = 0.f; -} - -*/ - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setInternalGain(F32 gain) -{ -	if (!mInited) -	{ -		return; -	} - -	gain = llclamp( gain, 0.0f, 1.0f ); -	FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); - -	LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); -	if ( saimpl ) -	{ -		// fmod likes its streaming audio channel gain re-asserted after -		// master volume change. -		saimpl->setGain(saimpl->getGain()); -	} -} - -// -// LLAudioChannelFMOD implementation -// - -LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0) -{ -} - - -LLAudioChannelFMOD::~LLAudioChannelFMOD() -{ -	cleanup(); -} - - -bool LLAudioChannelFMOD::updateBuffer() -{ -	if (LLAudioChannel::updateBuffer()) -	{ -		// Base class update returned true, which means that we need to actually -		// set up the channel for a different buffer. - -		LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); - -		// Grab the FMOD sample associated with the buffer -		FSOUND_SAMPLE *samplep = bufferp->getSample(); -		if (!samplep) -		{ -			// This is bad, there should ALWAYS be a sample associated with a legit -			// buffer. -			llerrs << "No FMOD sample!" << llendl; -			return false; -		} - - -		// Actually play the sound.  Start it off paused so we can do all the necessary -		// setup. -		mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true); - -		//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; -	} - -	// If we have a source for the channel, we need to update its gain. -	if (mCurrentSourcep) -	{ -		// SJB: warnings can spam and hurt framerate, disabling -		if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f))) -		{ -// 			llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -		 -		if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF)) -		{ -// 			llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID() -// 					<< " at " << mCurrentSourcep->getPositionGlobal() << llendl; -// 			llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -	} - -	return true; -} - - -void LLAudioChannelFMOD::update3DPosition() -{ -	if (!mChannelID) -	{ -		// We're not actually a live channel (i.e., we're not playing back anything) -		return; -	} - -	LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp; -	if (!bufferp) -	{ -		// We don't have a buffer associated with us (should really have been picked up -		// by the above if. -		return; -	} - -	if (mCurrentSourcep->isAmbient()) -	{ -		// Ambient sound, don't need to do any positional updates. -		bufferp->set3DMode(false); -	} -	else -	{ -		// Localized sound.  Update the position and velocity of the sound. -		bufferp->set3DMode(true); - -		LLVector3 float_pos; -		float_pos.setVec(mCurrentSourcep->getPositionGlobal()); -		if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV)) -		{ -			LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; -		} -	} -} - - -void LLAudioChannelFMOD::updateLoop() -{ -	if (!mChannelID) -	{ -		// May want to clear up the loop/sample counters. -		return; -	} - -	// -	// Hack:  We keep track of whether we looped or not by seeing when the -	// sample position looks like it's going backwards.  Not reliable; may -	// yield false negatives. -	// -	U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); -	if (cur_pos < (U32)mLastSamplePos) -	{ -		mLoopedThisFrame = true; -	} -	mLastSamplePos = cur_pos; -} - - -void LLAudioChannelFMOD::cleanup() -{ -	if (!mChannelID) -	{ -		//llinfos << "Aborting cleanup with no channelID." << llendl; -		return; -	} - -	//llinfos << "Cleaning up channel: " << mChannelID << llendl; -	if (!FSOUND_StopSound(mChannelID)) -	{ -		LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -	} - -	mCurrentBufferp = NULL; -	mChannelID = 0; -} - - -void LLAudioChannelFMOD::play() -{ -	if (!mChannelID) -	{ -		llwarns << "Playing without a channelID, aborting" << llendl; -		return; -	} - -	if (!FSOUND_SetPaused(mChannelID, false)) -	{ -		llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -	} -	getSource()->setPlayedOnce(true); -} - - -void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp) -{ -	LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp; -	if (!(fmod_channelp->mChannelID && mChannelID)) -	{ -		// Don't have channels allocated to both the master and the slave -		return; -	} - -	U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength(); -	// Try to match the position of our sync master -	if (!FSOUND_SetCurrentPosition(mChannelID, position)) -	{ -		llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl; -	} - -	// Start us playing -	play(); -} - - -bool LLAudioChannelFMOD::isPlaying() -{ -	if (!mChannelID) -	{ -		return false; -	} - -	return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); -} - - - -// -// LLAudioBufferFMOD implementation -// - - -LLAudioBufferFMOD::LLAudioBufferFMOD() -{ -	mSamplep = NULL; -} - - -LLAudioBufferFMOD::~LLAudioBufferFMOD() -{ -	if (mSamplep) -	{ -		// Clean up the associated FMOD sample if it exists. -		FSOUND_Sample_Free(mSamplep); -		mSamplep = NULL; -	} -} - - -bool LLAudioBufferFMOD::loadWAV(const std::string& filename) -{ -	// Try to open a wav file from disk.  This will eventually go away, as we don't -	// really want to block doing this. -	if (filename.empty()) -	{ -		// invalid filename, abort. -		return false; -	} - -	if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) -	{ -		// File not found, abort. -		return false; -	} -	 -	if (mSamplep) -	{ -		// If there's already something loaded in this buffer, clean it up. -		FSOUND_Sample_Free(mSamplep); -		mSamplep = NULL; -	} - -	// Load up the wav file into an fmod sample -#if LL_WINDOWS -	// MikeS. - Loading the sound file manually and then handing it over to FMOD, -	//	since FMOD uses posix IO internally, -	// which doesn't work with unicode file paths. -	LLFILE* sound_file = LLFile::fopen(filename,"rb");	/* Flawfinder: ignore */ -	if (sound_file) -	{ -		fseek(sound_file,0,SEEK_END); -		U32	file_length = ftell(sound_file);	//Find the length of the file by seeking to the end and getting the offset -		size_t	read_count; -		fseek(sound_file,0,SEEK_SET);	//Seek back to the beginning -		char*	buffer = new char[file_length]; -		llassert(buffer); -		read_count = fread((void*)buffer,file_length,1,sound_file);//Load it.. -		if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size... -			unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY; -									//FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL; -			mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length); -		} -		delete[] buffer; -		fclose(sound_file); -	} -#else -	mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0); -#endif - -	if (!mSamplep) -	{ -		// We failed to load the file for some reason. -		llwarns << "Could not load data '" << filename << "': " -				<< FMOD_ErrorString(FSOUND_GetError()) << llendl; - -		// -		// If we EVER want to load wav files provided by end users, we need -		// to rethink this! -		// -		// file is probably corrupt - remove it. -		LLFile::remove(filename); -		return false; -	} - -	// Everything went well, return true -	return true; -} - - -U32 LLAudioBufferFMOD::getLength() -{ -	if (!mSamplep) -	{ -		return 0; -	} - -	return FSOUND_Sample_GetLength(mSamplep); -} - - -void LLAudioBufferFMOD::set3DMode(bool use3d) -{ -	U16 current_mode = FSOUND_Sample_GetMode(mSamplep); -	 -	if (use3d) -	{ -		if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D)))) -		{ -			llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -	} -	else -	{ -		if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D)) -		{ -			llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; -		} -	} -} - - -void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) -{ -	// originalbuffer = fmod's original mixbuffer. -	// newbuffer = the buffer passed from the previous DSP unit. -	// length = length in samples at this mix time. -	// userdata = user parameter passed through in FSOUND_DSP_Create. - -	LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen = -		(LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata; -	 -	newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length); - -	return newbuffer; -} diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp new file mode 100644 index 0000000000..40a43884a1 --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -0,0 +1,746 @@ +/**  + * @file audioengine_fmodex.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio  + * support as a FMODEX implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llstreamingaudio.h" +#include "llstreamingaudio_fmodex.h" + +#include "llaudioengine_fmodex.h" +#include "lllistener_fmodex.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmod.hpp" +#include "fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); + +FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; + +LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler) +{ +	mInited = false; +	mWindGen = NULL; +	mWindDSP = NULL; +	mSystem = NULL; +	mEnableProfiler = enable_profiler; +} + + +LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX() +{ +} + + +inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) +{ +	if(result == FMOD_OK) +		return false; +	llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl; +	return true; +} + +void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ +	if(type & FMOD_MEMORY_STREAM_DECODE) +	{ +		llinfos << "Decode buffer size: " << size << llendl; +	} +	else if(type & FMOD_MEMORY_STREAM_FILE) +	{ +		llinfos << "Strean buffer size: " << size << llendl; +	} +	return new char[size]; +} +void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ +	memset(ptr,0,size); +	return ptr; +} +void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ +	delete[] (char*)ptr; +} + +bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) +{ +	U32 version; +	FMOD_RESULT result; + +	LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; + +	//result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE); +	//if(Check_FMOD_Error(result, "FMOD::Memory_Initialize")) +	//	return false; + +	result = FMOD::System_Create(&mSystem); +	if(Check_FMOD_Error(result, "FMOD::System_Create")) +		return false; + +	//will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer. +	LLAudioEngine::init(num_channels, userdata);	 +	 +	result = mSystem->getVersion(&version); +	Check_FMOD_Error(result, "FMOD::System::getVersion"); + +	if (version < FMOD_VERSION) +	{ +		LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version +			<< ")!  You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; +	} + +	result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); +	Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); + +	// In this case, all sounds, PLUS wind and stream will be software. +	result = mSystem->setSoftwareChannels(num_channels + 2); +	Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); + +	U32 fmod_flags = FMOD_INIT_NORMAL; +	if(mEnableProfiler) +	{ +		fmod_flags |= FMOD_INIT_ENABLE_PROFILE; +		mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]); +		mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]); +		mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]); +		mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]); +	} + +#if LL_LINUX +	bool audio_ok = false; + +	if (!audio_ok) +	{ +		if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ +		{ +			LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; +			if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && +				(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) +			{ +				LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY"	<< LL_ENDL; +				audio_ok = true; +			} +			else  +			{ +				Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); +			} +		}  +		else  +		{ +			LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; +		}	 +	} +	if (!audio_ok) +	{ +		if (NULL == getenv("LL_BAD_FMOD_ALSA"))		/*Flawfinder: ignore*/ +		{ +			LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; +			if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && +			    (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) +			{ +				LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; +				audio_ok = true; +			}  +			else  +			{ +				Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); +			} +		}  +		else  +		{ +			LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; +		} +	} +	if (!audio_ok) +	{ +		if (NULL == getenv("LL_BAD_FMOD_OSS")) 	 /*Flawfinder: ignore*/ +		{ +			LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; +			if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && +			    (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) +			{ +				LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; +				audio_ok = true; +			} +			else +			{ +				Check_FMOD_Error(result, "OSS audio output FAILED to initialize"); +			} +		} +		else  +		{ +			LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; +		} +	} +	if (!audio_ok) +	{ +		LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; +		return false; +	} + +	// We're interested in logging which output method we +	// ended up with, for QA purposes. +	FMOD_OUTPUTTYPE output_type; +	mSystem->getOutput(&output_type); +	switch (output_type) +	{ +		case FMOD_OUTPUTTYPE_NOSOUND:  +			LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; +		case FMOD_OUTPUTTYPE_PULSEAUDIO:	 +			LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; +		case FMOD_OUTPUTTYPE_ALSA:  +			LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; +		case FMOD_OUTPUTTYPE_OSS:	 +			LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; +		default: +			LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; +	}; +#else // LL_LINUX + +	// initialize the FMOD engine +	result = mSystem->init( num_channels + 2, fmod_flags, 0); +	if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) +	{ +		/* +		Ok, the speaker mode selected isn't supported by this soundcard. Switch it +		back to stereo... +		*/ +		result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); +		Check_FMOD_Error(result,"Error falling back to stereo mode"); +		/* +		... and re-init. +		*/ +		result = mSystem->init( num_channels + 2, fmod_flags, 0); +	} +	if(Check_FMOD_Error(result, "Error initializing FMOD Ex")) +		return false; +#endif + +	// set up our favourite FMOD-native streaming audio implementation if none has already been added +	if (!getStreamingAudioImpl()) // no existing implementation added +		setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); + +	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL; + +	int r_numbuffers, r_samplerate, r_channels, r_bits; +	unsigned int r_bufferlength; +	char r_name[256]; +	mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); +	mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits); +	mSystem->getDriverInfo(0, r_name, 255, 0); +	r_name[255] = '\0'; +	int latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); + +	LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n" +		<< "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n" +		<< "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL; + +	mInited = true; + +	return true; +} + + +std::string LLAudioEngine_FMODEX::getDriverName(bool verbose) +{ +	llassert_always(mSystem); +	if (verbose) +	{ +		U32 version; +		if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) +		{ +			return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); +		} +	} +	return "FMODEx"; +} + + +void LLAudioEngine_FMODEX::allocateListener(void) +{	 +	mListenerp = (LLListener *) new LLListener_FMODEX(mSystem); +	if (!mListenerp) +	{ +		llwarns << "Listener creation failed" << llendl; +	} +} + + +void LLAudioEngine_FMODEX::shutdown() +{ +	stopInternetStream(); + +	llinfos << "About to LLAudioEngine::shutdown()" << llendl; +	LLAudioEngine::shutdown(); +	 +	llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl; +	mSystem->close(); +	mSystem->release(); +	llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl; + +	delete mListenerp; +	mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer() +{ +	return new LLAudioBufferFMODEX(mSystem); +} + + +LLAudioChannel * LLAudioEngine_FMODEX::createChannel() +{ +	return new LLAudioChannelFMODEX(mSystem); +} + +bool LLAudioEngine_FMODEX::initWind() +{ +	mNextWindUpdate = 0.0; + +	if (!mWindDSP) +	{ +		FMOD_DSP_DESCRIPTION dspdesc; +		memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION));	//Set everything to zero +		strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name));	//Set name to "Wind Unit" +		dspdesc.channels=2; +		dspdesc.read = &windCallback; //Assign callback. +		if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP")) +			return false; + +		if(mWindGen) +			delete mWindGen; +	 +		float frequency = 44100; +		mWindDSP->getDefaults(&frequency,0,0,0); +		mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); +		mWindDSP->setUserData((void*)mWindGen); +	} + +	if (mWindDSP) +	{ +		mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0); +		return true; +	} +	return false; +} + + +void LLAudioEngine_FMODEX::cleanupWind() +{ +	if (mWindDSP) +	{ +		mWindDSP->remove(); +		mWindDSP->release(); +		mWindDSP = NULL; +	} + +	delete mWindGen; +	mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) +{ +	LLVector3 wind_pos; +	F64 pitch; +	F64 center_freq; + +	if (!mEnableWind) +	{ +		return; +	} +	 +	if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) +	{ +		 +		// wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) +		// need to convert this to the conventional orientation DS3D and OpenAL use +		// where +X = right, +Y = up, +Z = backwards + +		wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + +		// cerr << "Wind update" << endl; + +		pitch = 1.0 + mapWindVecToPitch(wind_vec); +		center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); +		 +		mWindGen->mTargetFreq = (F32)center_freq; +		mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; +		mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); +  	} +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODEX::setInternalGain(F32 gain) +{ +	if (!mInited) +	{ +		return; +	} + +	gain = llclamp( gain, 0.0f, 1.0f ); + +	FMOD::ChannelGroup *master_group; +	mSystem->getMasterChannelGroup(&master_group); + +	master_group->setVolume(gain); + +	LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); +	if ( saimpl ) +	{ +		// fmod likes its streaming audio channel gain re-asserted after +		// master volume change. +		saimpl->setGain(saimpl->getGain()); +	} +} + +// +// LLAudioChannelFMODEX implementation +// + +LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMODEX::~LLAudioChannelFMODEX() +{ +	cleanup(); +} + +bool LLAudioChannelFMODEX::updateBuffer() +{ +	if (LLAudioChannel::updateBuffer()) +	{ +		// Base class update returned true, which means that we need to actually +		// set up the channel for a different buffer. + +		LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer(); + +		// Grab the FMOD sample associated with the buffer +		FMOD::Sound *soundp = bufferp->getSound(); +		if (!soundp) +		{ +			// This is bad, there should ALWAYS be a sound associated with a legit +			// buffer. +			llerrs << "No FMOD sound!" << llendl; +			return false; +		} + + +		// Actually play the sound.  Start it off paused so we can do all the necessary +		// setup. +		if(!mChannelp) +		{ +			FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); +			Check_FMOD_Error(result, "FMOD::System::playSound"); +		} + +		//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; +	} + +	// If we have a source for the channel, we need to update its gain. +	if (mCurrentSourcep) +	{ +		// SJB: warnings can spam and hurt framerate, disabling +		FMOD_RESULT result; + +		result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); +		//Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + +		result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); +		/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) +		{ +			S32 index; +			mChannelp->getIndex(&index); + 			llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() + 					<< " at " << mCurrentSourcep->getPositionGlobal() << llendl;		 +		}*/ +	} + +	return true; +} + + +void LLAudioChannelFMODEX::update3DPosition() +{ +	if (!mChannelp) +	{ +		// We're not actually a live channel (i.e., we're not playing back anything) +		return; +	} + +	LLAudioBufferFMODEX  *bufferp = (LLAudioBufferFMODEX  *)mCurrentBufferp; +	if (!bufferp) +	{ +		// We don't have a buffer associated with us (should really have been picked up +		// by the above if. +		return; +	} + +	if (mCurrentSourcep->isAmbient()) +	{ +		// Ambient sound, don't need to do any positional updates. +		set3DMode(false); +	} +	else +	{ +		// Localized sound.  Update the position and velocity of the sound. +		set3DMode(true); + +		LLVector3 float_pos; +		float_pos.setVec(mCurrentSourcep->getPositionGlobal()); +		FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); +		Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); +	} +} + + +void LLAudioChannelFMODEX::updateLoop() +{ +	if (!mChannelp) +	{ +		// May want to clear up the loop/sample counters. +		return; +	} + +	// +	// Hack:  We keep track of whether we looped or not by seeing when the +	// sample position looks like it's going backwards.  Not reliable; may +	// yield false negatives. +	// +	U32 cur_pos; +	mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES); + +	if (cur_pos < (U32)mLastSamplePos) +	{ +		mLoopedThisFrame = true; +	} +	mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMODEX::cleanup() +{ +	if (!mChannelp) +	{ +		//llinfos << "Aborting cleanup with no channel handle." << llendl; +		return; +	} + +	//llinfos << "Cleaning up channel: " << mChannelID << llendl; +	Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); + +	mCurrentBufferp = NULL; +	mChannelp = NULL; +} + + +void LLAudioChannelFMODEX::play() +{ +	if (!mChannelp) +	{ +		llwarns << "Playing without a channel handle, aborting" << llendl; +		return; +	} + +	Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + +	getSource()->setPlayedOnce(true); + +	if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) +		mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]); +} + + +void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp) +{ +	LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp; +	if (!(fmod_channelp->mChannelp && mChannelp)) +	{ +		// Don't have channels allocated to both the master and the slave +		return; +	} + +	U32 cur_pos; +	if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) +		return; + +	cur_pos %= mCurrentBufferp->getLength(); +	 +	// Try to match the position of our sync master +	Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position"); + +	// Start us playing +	play(); +} + + +bool LLAudioChannelFMODEX::isPlaying() +{ +	if (!mChannelp) +	{ +		return false; +	} + +	bool paused, playing; +	mChannelp->getPaused(&paused); +	mChannelp->isPlaying(&playing); +	return !paused && playing; +} + + +// +// LLAudioChannelFMODEX implementation +// + + +LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +{ +} + + +LLAudioBufferFMODEX::~LLAudioBufferFMODEX() +{ +	if(mSoundp) +	{ +		mSoundp->release(); +		mSoundp = NULL; +	} +} + + +bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) +{ +	// Try to open a wav file from disk.  This will eventually go away, as we don't +	// really want to block doing this. +	if (filename.empty()) +	{ +		// invalid filename, abort. +		return false; +	} + +	if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) +	{ +		// File not found, abort. +		return false; +	} +	 +	if (mSoundp) +	{ +		// If there's already something loaded in this buffer, clean it up. +		mSoundp->release(); +		mSoundp = NULL; +	} + +	FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE; +	FMOD_CREATESOUNDEXINFO exinfo; +	memset(&exinfo,0,sizeof(exinfo)); +	exinfo.cbsize = sizeof(exinfo); +	exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV;	//Hint to speed up loading. +	// Load up the wav file into an fmod sample +#if LL_WINDOWS +	FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp); +#else +	FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); +#endif + +	if (result != FMOD_OK) +	{ +		// We failed to load the file for some reason. +		llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl; + +		// +		// If we EVER want to load wav files provided by end users, we need +		// to rethink this! +		// +		// file is probably corrupt - remove it. +		LLFile::remove(filename); +		return false; +	} + +	// Everything went well, return true +	return true; +} + + +U32 LLAudioBufferFMODEX::getLength() +{ +	if (!mSoundp) +	{ +		return 0; +	} + +	U32 length; +	mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); +	return length; +} + + +void LLAudioChannelFMODEX::set3DMode(bool use3d) +{ +	FMOD_MODE current_mode; +	if(mChannelp->getMode(¤t_mode) != FMOD_OK) +		return; +	FMOD_MODE new_mode = current_mode;	 +	new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); +	new_mode |= use3d ? FMOD_3D : FMOD_2D; + +	if(current_mode != new_mode) +	{ +		mChannelp->setMode(new_mode); +	} +} + + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels) +{ +	// originalbuffer = fmod's original mixbuffer. +	// newbuffer = the buffer passed from the previous DSP unit. +	// length = length in samples at this mix time. +	// userdata = user parameter passed through in FSOUND_DSP_Create. +	 +	LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen; +	FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + +	thisdsp->getUserData((void **)&windgen); +	S32 channels, configwidth, configheight; +	thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight); +	 +	windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); + +	return FMOD_OK; +} diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmodex.h index 4582a5d57e..415a9ed0ef 100644 --- a/indra/llaudio/llaudioengine_fmod.h +++ b/indra/llaudio/llaudioengine_fmodex.h @@ -1,7 +1,7 @@  /**  - * @file audioengine_fmod.h - * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMOD 3D implementation + * @file audioengine_fmodex.h + * @brief Definition of LLAudioEngine class abstracting the audio  + * support as a FMODEX implementation   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code @@ -25,26 +25,33 @@   * $/LicenseInfo$   */ -#ifndef LL_AUDIOENGINE_FMOD_H -#define LL_AUDIOENGINE_FMOD_H +#ifndef LL_AUDIOENGINE_FMODEX_H +#define LL_AUDIOENGINE_FMODEX_H  #include "llaudioengine.h" -#include "lllistener_fmod.h"  #include "llwindgen.h" -#include "fmod.h" - -class LLAudioStreamManagerFMOD; - -class LLAudioEngine_FMOD : public LLAudioEngine  +//Stubs +class LLAudioStreamManagerFMODEX; +namespace FMOD +{ +	class System; +	class Channel; +	class ChannelGroup; +	class Sound; +	class DSP; +} + +//Interfaces +class LLAudioEngine_FMODEX : public LLAudioEngine   {  public: -	LLAudioEngine_FMOD(); -	virtual ~LLAudioEngine_FMOD(); +	LLAudioEngine_FMODEX(bool enable_profiler); +	virtual ~LLAudioEngine_FMODEX();  	// initialization/startup/shutdown  	virtual bool init(const S32 num_channels, void *user_data); -       	virtual std::string getDriverName(bool verbose); +	virtual std::string getDriverName(bool verbose);  	virtual void allocateListener();  	virtual void shutdown(); @@ -54,38 +61,33 @@ public:  	/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); -#if LL_DARWIN -	typedef S32 MIXBUFFERFORMAT; -#else -	typedef S16 MIXBUFFERFORMAT; -#endif +	typedef F32 MIXBUFFERFORMAT; +	FMOD::System *getSystem()				const {return mSystem;}  protected:  	/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.  	/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.  	/*virtual*/ void setInternalGain(F32 gain); -protected: -	static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); - -	//F32 mMinDistance[MAX_BUFFERS]; -	//F32 mMaxDistance[MAX_BUFFERS];  	bool mInited; -	// On Windows, userdata is the HWND of the application window. -	void* mUserData; -  	LLWindGen<MIXBUFFERFORMAT> *mWindGen; -	FSOUND_DSPUNIT *mWindDSP; + +	FMOD::DSP *mWindDSP; +	FMOD::System *mSystem; +	bool mEnableProfiler; + +public: +	static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];  }; -class LLAudioChannelFMOD : public LLAudioChannel +class LLAudioChannelFMODEX : public LLAudioChannel  {  public: -	LLAudioChannelFMOD(); -	virtual ~LLAudioChannelFMOD(); +	LLAudioChannelFMODEX(FMOD::System *audioengine); +	virtual ~LLAudioChannelFMODEX();  protected:  	/*virtual*/ void play(); @@ -97,28 +99,30 @@ protected:  	/*virtual*/ void update3DPosition();  	/*virtual*/ void updateLoop(); +	void set3DMode(bool use3d);  protected: -	int mChannelID; +	FMOD::System *getSystem()	const {return mSystemp;} +	FMOD::System *mSystemp; +	FMOD::Channel *mChannelp;  	S32 mLastSamplePos;  }; -class LLAudioBufferFMOD : public LLAudioBuffer +class LLAudioBufferFMODEX : public LLAudioBuffer  {  public: -	LLAudioBufferFMOD(); -	virtual ~LLAudioBufferFMOD(); +	LLAudioBufferFMODEX(FMOD::System *audioengine); +	virtual ~LLAudioBufferFMODEX();  	/*virtual*/ bool loadWAV(const std::string& filename);  	/*virtual*/ U32 getLength(); -	friend class LLAudioChannelFMOD; - -	void set3DMode(bool use3d); -protected: -	FSOUND_SAMPLE *getSample()	{ return mSamplep; } +	friend class LLAudioChannelFMODEX;  protected: -	FSOUND_SAMPLE *mSamplep; +	FMOD::System *getSystem()	const {return mSystemp;} +	FMOD::System *mSystemp; +	FMOD::Sound *getSound()		const{ return mSoundp; } +	FMOD::Sound *mSoundp;  }; -#endif // LL_AUDIOENGINE_FMOD_H +#endif // LL_AUDIOENGINE_FMODEX_H diff --git a/indra/llaudio/lllistener_fmod.cpp b/indra/llaudio/lllistener_fmodex.cpp index 0138f4345e..2509a7aebc 100644 --- a/indra/llaudio/lllistener_fmod.cpp +++ b/indra/llaudio/lllistener_fmodex.cpp @@ -1,7 +1,7 @@  /**  - * @file listener_fmod.cpp - * @brief implementation of LISTENER class abstracting the audio - * support as a FMOD 3D implementation (windows only) + * @file listener_fmodex.cpp + * @brief Implementation of LISTENER class abstracting the audio + * support as a FMODEX implementation   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code @@ -27,24 +27,25 @@  #include "linden_common.h"  #include "llaudioengine.h" -#include "lllistener_fmod.h" -#include "fmod.h" +#include "lllistener_fmodex.h" +#include "fmod.hpp"  //-----------------------------------------------------------------------  // constructor  //----------------------------------------------------------------------- -LLListener_FMOD::LLListener_FMOD() +LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)  { +	mSystem = system;  	init();  }  //----------------------------------------------------------------------- -LLListener_FMOD::~LLListener_FMOD() +LLListener_FMODEX::~LLListener_FMODEX()  {  }  //----------------------------------------------------------------------- -void LLListener_FMOD::init(void) +void LLListener_FMODEX::init(void)  {  	// do inherited  	LLListener::init(); @@ -53,31 +54,31 @@ void LLListener_FMOD::init(void)  }  //----------------------------------------------------------------------- -void LLListener_FMOD::translate(LLVector3 offset) +void LLListener_FMODEX::translate(LLVector3 offset)  {  	LLListener::translate(offset); -	FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);  }  //----------------------------------------------------------------------- -void LLListener_FMOD::setPosition(LLVector3 pos) +void LLListener_FMODEX::setPosition(LLVector3 pos)  {  	LLListener::setPosition(pos); -	FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);  }  //----------------------------------------------------------------------- -void LLListener_FMOD::setVelocity(LLVector3 vel) +void LLListener_FMODEX::setVelocity(LLVector3 vel)  {  	LLListener::setVelocity(vel); -	FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +	mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);  }  //----------------------------------------------------------------------- -void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) +void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)  {  	LLListener::orient(up, at); @@ -87,37 +88,46 @@ void LLListener_FMOD::orient(LLVector3 up, LLVector3 at)  	// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed  	at = -at; -	FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); +	mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);  }  //----------------------------------------------------------------------- -void LLListener_FMOD::commitDeferredChanges() +void LLListener_FMODEX::commitDeferredChanges()  { -	FSOUND_Update(); +	mSystem->update();  } -void LLListener_FMOD::setRolloffFactor(F32 factor) +void LLListener_FMODEX::setRolloffFactor(F32 factor)  { +	//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment. +	//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. +	//In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call. +	if(mRolloffFactor != factor) +	{ +		LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f); +		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); +		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL); +	}  	mRolloffFactor = factor; -	FSOUND_3D_SetRolloffFactor(factor); +	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);  } -F32 LLListener_FMOD::getRolloffFactor() +F32 LLListener_FMODEX::getRolloffFactor()  {  	return mRolloffFactor;  } -void LLListener_FMOD::setDopplerFactor(F32 factor) +void LLListener_FMODEX::setDopplerFactor(F32 factor)  {  	mDopplerFactor = factor; -	FSOUND_3D_SetDopplerFactor(factor); +	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);  } -F32 LLListener_FMOD::getDopplerFactor() +F32 LLListener_FMODEX::getDopplerFactor()  {  	return mDopplerFactor;  } diff --git a/indra/llaudio/lllistener_fmod.h b/indra/llaudio/lllistener_fmodex.h index 818da05d51..073b65d53a 100644 --- a/indra/llaudio/lllistener_fmod.h +++ b/indra/llaudio/lllistener_fmodex.h @@ -1,5 +1,5 @@  /**  - * @file listener_fmod.h + * @file listener_fmodex.h   * @brief Description of LISTENER class abstracting the audio support   * as an FMOD 3D implementation (windows and Linux)   * @@ -25,16 +25,23 @@   * $/LicenseInfo$   */ -#ifndef LL_LISTENER_FMOD_H -#define LL_LISTENER_FMOD_H +#ifndef LL_LISTENER_FMODEX_H +#define LL_LISTENER_FMODEX_H  #include "lllistener.h" -class LLListener_FMOD : public LLListener +//Stubs +namespace FMOD +{ +	class System; +} + +//Interfaces +class LLListener_FMODEX : public LLListener  {   public:   -	LLListener_FMOD(); -	virtual ~LLListener_FMOD(); +	LLListener_FMODEX(FMOD::System *system); +	virtual ~LLListener_FMODEX();  	virtual void init();    	virtual void translate(LLVector3 offset); @@ -47,8 +54,8 @@ class LLListener_FMOD : public LLListener  	virtual F32 getDopplerFactor();  	virtual void setRolloffFactor(F32 factor);  	virtual F32 getRolloffFactor(); -   protected: +	 FMOD::System *mSystem;  	 F32 mDopplerFactor;  	 F32 mRolloffFactor;  }; diff --git a/indra/llaudio/llstreamingaudio.h b/indra/llaudio/llstreamingaudio.h index 20104af744..93479f9d59 100644 --- a/indra/llaudio/llstreamingaudio.h +++ b/indra/llaudio/llstreamingaudio.h @@ -45,6 +45,8 @@ class LLStreamingAudioInterface  	virtual void setGain(F32 vol) = 0;  	virtual F32 getGain() = 0;  	virtual std::string getURL() = 0; +	virtual bool supportsAdjustableBufferSizes(){return false;} +	virtual void setBufferSizes(U32 streambuffertime, U32 decodebuffertime){};  };  #endif // LL_STREAMINGAUDIO_H diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp index bcdea771a7..4a74267650 100644 --- a/indra/llaudio/llstreamingaudio_fmod.cpp +++ b/indra/llaudio/llstreamingaudio_fmodex.cpp @@ -1,8 +1,8 @@  /**  - * @file streamingaudio_fmod.cpp - * @brief LLStreamingAudio_FMOD implementation + * @file streamingaudio_fmodex.cpp + * @brief LLStreamingAudio_FMODEX implementation   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -28,25 +28,27 @@  #include "llmath.h" -#include "fmod.h" +#include "fmod.hpp"  #include "fmod_errors.h" -#include "llstreamingaudio_fmod.h" +#include "llstreamingaudio_fmodex.h" -class LLAudioStreamManagerFMOD +class LLAudioStreamManagerFMODEX  {  public: -	LLAudioStreamManagerFMOD(const std::string& url); -	int	startStream(); +	LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url); +	FMOD::Channel* startStream();  	bool stopStream(); // Returns true if the stream was successfully stopped.  	bool ready();  	const std::string& getURL() 	{ return mInternetStreamURL; } -	int getOpenState(); +	FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);  protected: -	FSOUND_STREAM* mInternetStream; +	FMOD::System* mSystem; +	FMOD::Channel* mStreamChannel; +	FMOD::Sound* mInternetStream;  	bool mReady;  	std::string mInternetStreamURL; @@ -57,14 +59,17 @@ protected:  //---------------------------------------------------------------------------  // Internet Streaming  //--------------------------------------------------------------------------- -LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : +LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) : +	mSystem(system),  	mCurrentInternetStreamp(NULL), -	mFMODInternetStreamChannel(-1), +	mFMODInternetStreamChannelp(NULL),  	mGain(1.0f)  {  	// Number of milliseconds of audio to buffer for the audio card.  	// Must be larger than the usual Second Life frame stutter time. -	FSOUND_Stream_SetBufferSize(200); +	const U32 buffer_seconds = 10;		//sec +	const U32 estimated_bitrate = 128;	//kbit/sec +	mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);  	// Here's where we set the size of the network buffer and some buffering   	// parameters.  In this case we want a network buffer of 16k, we want it  @@ -76,13 +81,13 @@ LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :  } -LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD() +LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()  {  	// nothing interesting/safe to do.  } -void LLStreamingAudio_FMOD::start(const std::string& url) +void LLStreamingAudio_FMODEX::start(const std::string& url)  {  	//if (!mInited)  	//{ @@ -96,7 +101,7 @@ void LLStreamingAudio_FMOD::start(const std::string& url)  	if (!url.empty())  	{  		llinfos << "Starting internet stream: " << url << llendl; -		mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url); +		mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);  		mURL = url;  	}  	else @@ -107,13 +112,13 @@ void LLStreamingAudio_FMOD::start(const std::string& url)  } -void LLStreamingAudio_FMOD::update() +void LLStreamingAudio_FMODEX::update()  {  	// Kill dead internet streams, if possible -	std::list<LLAudioStreamManagerFMOD *>::iterator iter; +	std::list<LLAudioStreamManagerFMODEX *>::iterator iter;  	for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)  	{ -		LLAudioStreamManagerFMOD *streamp = *iter; +		LLAudioStreamManagerFMODEX *streamp = *iter;  		if (streamp->stopStream())  		{  			llinfos << "Closed dead stream" << llendl; @@ -132,62 +137,66 @@ void LLStreamingAudio_FMOD::update()  		return;  	} -	int open_state = mCurrentInternetStreamp->getOpenState(); +	unsigned int progress; +	bool starving; +	bool diskbusy; +	FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); -	if (!open_state) +	if (open_state == FMOD_OPENSTATE_READY)  	{  		// Stream is live  		// start the stream if it's ready -		if (mFMODInternetStreamChannel < 0) +		if (!mFMODInternetStreamChannelp && +			(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))  		{ -			mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream(); - -			if (mFMODInternetStreamChannel != -1) -			{ -				// Reset volume to previously set volume -				setGain(getGain()); -				FSOUND_SetPaused(mFMODInternetStreamChannel, false); -			} +			// Reset volume to previously set volume +			setGain(getGain()); +			mFMODInternetStreamChannelp->setPaused(false); +			mLastStarved.stop();  		}  	} -		 -	switch(open_state) +	else if(open_state == FMOD_OPENSTATE_ERROR)  	{ -	default: -	case 0: -		// success -		break; -	case -1: -		// stream handle is invalid -		llwarns << "InternetStream - invalid handle" << llendl;  		stop();  		return; -	case -2: -		// opening -		break; -	case -3: -		// failed to open, file not found, perhaps -		llwarns << "InternetStream - failed to open" << llendl; -		stop(); -		return; -	case -4: -		// connecting -		break; -	case -5: -		// buffering -		break;  	} +	if(mFMODInternetStreamChannelp) +	{ +		FMOD::Sound *sound = NULL; + +		if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) +		{ +			if(starving) +			{ +				if(!mLastStarved.getStarted()) +				{ +					llinfos << "Stream starvation detected! Muting stream audio until it clears." << llendl; +					llinfos << "  (diskbusy="<<diskbusy<<")" << llendl; +					llinfos << "  (progress="<<progress<<")" << llendl; +					mFMODInternetStreamChannelp->setMute(true); +				} +				mLastStarved.start(); +			} +			else if(mLastStarved.getStarted() && mLastStarved.getElapsedTimeF32() > 1.f) +			{ +				mLastStarved.stop(); +				mFMODInternetStreamChannelp->setMute(false); +			} +		} +	}  } -void LLStreamingAudio_FMOD::stop() +void LLStreamingAudio_FMODEX::stop()  { -	if (mFMODInternetStreamChannel != -1) +	mLastStarved.stop(); + +	if (mFMODInternetStreamChannelp)  	{ -		FSOUND_SetPaused(mFMODInternetStreamChannel, true); -		FSOUND_SetPriority(mFMODInternetStreamChannel, 0); -		mFMODInternetStreamChannel = -1; +		mFMODInternetStreamChannelp->setPaused(true); +		mFMODInternetStreamChannelp->setPriority(0); +		mFMODInternetStreamChannelp = NULL;  	}  	if (mCurrentInternetStreamp) @@ -207,7 +216,7 @@ void LLStreamingAudio_FMOD::stop()  	}  } -void LLStreamingAudio_FMOD::pause(int pauseopt) +void LLStreamingAudio_FMODEX::pause(int pauseopt)  {  	if (pauseopt < 0)  	{ @@ -230,7 +239,7 @@ void LLStreamingAudio_FMOD::pause(int pauseopt)  // A stream is "playing" if it has been requested to start.  That  // doesn't necessarily mean audio is coming out of the speakers. -int LLStreamingAudio_FMOD::isPlaying() +int LLStreamingAudio_FMODEX::isPlaying()  {  	if (mCurrentInternetStreamp)  	{ @@ -247,44 +256,47 @@ int LLStreamingAudio_FMOD::isPlaying()  } -F32 LLStreamingAudio_FMOD::getGain() +F32 LLStreamingAudio_FMODEX::getGain()  {  	return mGain;  } -std::string LLStreamingAudio_FMOD::getURL() +std::string LLStreamingAudio_FMODEX::getURL()  {  	return mURL;  } -void LLStreamingAudio_FMOD::setGain(F32 vol) +void LLStreamingAudio_FMODEX::setGain(F32 vol)  {  	mGain = vol; -	if (mFMODInternetStreamChannel != -1) +	if (mFMODInternetStreamChannelp)  	{ -		vol = llclamp(vol * vol, 0.f, 1.f); -		int vol_int = llround(vol * 255.f); -		FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int); +		vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here? + +		mFMODInternetStreamChannelp->setVolume(vol);  	}  } -  ///////////////////////////////////////////////////////  // manager of possibly-multiple internet audio streams -LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : +LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) : +	mSystem(system), +	mStreamChannel(NULL),  	mInternetStream(NULL),  	mReady(false)  {  	mInternetStreamURL = url; -	mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); -	if (!mInternetStream) + +	FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_MPEGSEARCH | FMOD_IGNORETAGS, 0, &mInternetStream); + +	if (result!= FMOD_OK)  	{  		llwarns << "Couldn't open fmod stream, error " -			<< FMOD_ErrorString(FSOUND_GetError()) +			<< FMOD_ErrorString(result)  			<< llendl;  		mReady = false;  		return; @@ -293,48 +305,42 @@ LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) :  	mReady = true;  } -int LLAudioStreamManagerFMOD::startStream() +FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()  {  	// We need a live and opened stream before we try and play it. -	if (!mInternetStream || getOpenState()) +	if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)  	{  		llwarns << "No internet stream to start playing!" << llendl; -		return -1; +		return NULL;  	} -	// Make sure the stream is set to 2D mode. -	FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); +	if(mStreamChannel) +		return mStreamChannel;	//Already have a channel for this stream. -	return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); +	mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel); +	return mStreamChannel;  } -bool LLAudioStreamManagerFMOD::stopStream() +bool LLAudioStreamManagerFMODEX::stopStream()  {  	if (mInternetStream)  	{ -		int read_percent = 0; -		int status = 0; -		int bitrate = 0; -		unsigned int flags = 0x0; -		FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); +  		bool close = true; -		switch (status) +		switch (getOpenState())  		{ -		case FSOUND_STREAM_NET_CONNECTING: +		case FMOD_OPENSTATE_CONNECTING:  			close = false;  			break; -		case FSOUND_STREAM_NET_NOTCONNECTED: -		case FSOUND_STREAM_NET_BUFFERING: -		case FSOUND_STREAM_NET_READY: -		case FSOUND_STREAM_NET_ERROR:  		default:  			close = true;  		}  		if (close)  		{ -			FSOUND_Stream_Close(mInternetStream); +			mInternetStream->release(); +			mStreamChannel = NULL;  			mInternetStream = NULL;  			return true;  		} @@ -349,8 +355,19 @@ bool LLAudioStreamManagerFMOD::stopStream()  	}  } -int LLAudioStreamManagerFMOD::getOpenState() +FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) +{ +	FMOD_OPENSTATE state; +	mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); +	return state; +} + +void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)  { -	int open_state = FSOUND_Stream_GetOpenState(mInternetStream); -	return open_state; +	mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES); +	FMOD_ADVANCEDSETTINGS settings; +	memset(&settings,0,sizeof(settings)); +	settings.cbsize=sizeof(settings); +	settings.defaultDecodeBufferSize = decodebuffertime;//ms +	mSystem->setAdvancedSettings(&settings);  } diff --git a/indra/llaudio/llstreamingaudio_fmod.h b/indra/llaudio/llstreamingaudio_fmodex.h index 9970f0d03b..42b6b3aaa8 100644 --- a/indra/llaudio/llstreamingaudio_fmod.h +++ b/indra/llaudio/llstreamingaudio_fmodex.h @@ -1,9 +1,8 @@  /**  - * @file streamingaudio_fmod.h - * @author Tofu Linden - * @brief Definition of LLStreamingAudio_FMOD implementation + * @file streamingaudio_fmodex.h + * @brief Definition of LLStreamingAudio_FMODEX implementation   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -25,20 +24,28 @@   * $/LicenseInfo$   */ -#ifndef LL_STREAMINGAUDIO_FMOD_H -#define LL_STREAMINGAUDIO_FMOD_H +#ifndef LL_STREAMINGAUDIO_FMODEX_H +#define LL_STREAMINGAUDIO_FMODEX_H  #include "stdtypes.h" // from llcommon  #include "llstreamingaudio.h" +#include "lltimer.h" -class LLAudioStreamManagerFMOD; +//Stubs +class LLAudioStreamManagerFMODEX; +namespace FMOD +{ +	class System; +	class Channel; +} -class LLStreamingAudio_FMOD : public LLStreamingAudioInterface +//Interfaces +class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface  {   public: -	LLStreamingAudio_FMOD(); -	/*virtual*/ ~LLStreamingAudio_FMOD(); +	LLStreamingAudio_FMODEX(FMOD::System *system); +	/*virtual*/ ~LLStreamingAudio_FMODEX();  	/*virtual*/ void start(const std::string& url);  	/*virtual*/ void stop(); @@ -49,14 +56,20 @@ class LLStreamingAudio_FMOD : public LLStreamingAudioInterface  	/*virtual*/ F32 getGain();  	/*virtual*/ std::string getURL(); +	/*virtual*/ bool supportsAdjustableBufferSizes(){return true;} +	/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);  private: -	LLAudioStreamManagerFMOD *mCurrentInternetStreamp; -	int mFMODInternetStreamChannel; -	std::list<LLAudioStreamManagerFMOD *> mDeadStreams; +	FMOD::System *mSystem; + +	LLAudioStreamManagerFMODEX *mCurrentInternetStreamp; +	FMOD::Channel *mFMODInternetStreamChannelp; +	std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;  	std::string mURL;  	F32 mGain; + +	LLTimer mLastStarved;  }; -#endif // LL_STREAMINGAUDIO_FMOD_H +#endif // LL_STREAMINGAUDIO_FMODEX_H diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 0e0c80a456..dfd5da12b3 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -35,7 +35,7 @@  #include "llapr.h"  //#if LL_DARWIN -// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. +// MBW -- XXX -- Getting rid of SecondLifeVorbis for now  #if 0  #include "VorbisFramework.h" diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h index b9cecb60a1..719b0ecbf2 100644 --- a/indra/llaudio/llwindgen.h +++ b/indra/llaudio/llwindgen.h @@ -27,6 +27,7 @@  #define WINDGEN_H  #include "llcommon.h" +#include "llrand.h"  template <class MIXBUFFERFORMAT_T>  class LLWindGen @@ -54,7 +55,9 @@ public:  	}  	const U32 getInputSamplingRate() { return mInputSamplingRate; } -	 +	const F32 getNextSample(); +	const F32 getClampedSample(bool clamp, F32 sample); +  	// newbuffer = the buffer passed from the previous DSP unit.  	// numsamples = length in samples-per-channel at this mix time.  	// NOTE: generates L/R interleaved stereo @@ -89,7 +92,7 @@ public:  			// Start with white noise  			// This expression is fragile, rearrange it and it will break! -			next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); +			next_sample = getNextSample();  			// Apply a pinking filter  			// Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ @@ -126,23 +129,13 @@ public:  			for (U8 i=mSubSamples; i && numsamples; --i, --numsamples)   			{  				mLastSample = mLastSample + delta; -				S32	sample_right = (S32)(mLastSample * mCurrentPanGainR); -				S32	sample_left = (S32)mLastSample - sample_right; +				MIXBUFFERFORMAT_T	sample_right = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample * mCurrentPanGainR); +				MIXBUFFERFORMAT_T	sample_left = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample - (F32)sample_right); -				if (!clip) -				{ -					*cursamplep = (MIXBUFFERFORMAT_T)sample_left; -					++cursamplep; -					*cursamplep = (MIXBUFFERFORMAT_T)sample_right; -					++cursamplep; -				} -				else -				{ -					*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX); -					++cursamplep; -					*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX); -					++cursamplep; -				} +				*cursamplep = sample_left; +				++cursamplep; +				*cursamplep = sample_right; +				++cursamplep;  			}  		} @@ -173,4 +166,9 @@ private:  	F32 mLastSample;  }; +template<class T> inline const F32 LLWindGen<T>::getNextSample() { return (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); } +template<> inline const F32 LLWindGen<F32>::getNextSample() { return ll_frand()-.5f; } +template<class T> inline const F32 LLWindGen<T>::getClampedSample(bool clamp, F32 sample) { return clamp ? (F32)llclamp((S32)sample,(S32)S16_MIN,(S32)S16_MAX) : sample; } +template<> inline const F32 LLWindGen<F32>::getClampedSample(bool clamp, F32 sample) { return sample; } +  #endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4f7ce88165..fae02c0b30 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -10,7 +10,7 @@ include(DirectX)  include(OpenSSL)  include(DragDrop)  include(EXPAT) -include(FMOD) +include(FMODEX)  include(OPENAL)  include(OpenGL)  include(Hunspell) @@ -53,6 +53,10 @@ if (NOT HAVOK_TPV)     add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions)  endif (NOT HAVOK_TPV) +if(FMODEX) +  include_directories(${FMODEX_INCLUDE_DIR}) +endif(FMODEX) +  include_directories(      ${DBUSGLIB_INCLUDE_DIRS}      ${JSONCPP_INCLUDE_DIR} @@ -62,7 +66,6 @@ include_directories(      ${LLCOMMON_INCLUDE_DIRS}      ${LLCOREHTTP_INCLUDE_DIRS}      ${LLPHYSICS_INCLUDE_DIRS} -    ${FMOD_INCLUDE_DIR}      ${LLIMAGE_INCLUDE_DIRS}      ${LLKDU_INCLUDE_DIRS}      ${LLINVENTORY_INCLUDE_DIRS} @@ -1533,29 +1536,12 @@ endif (WINDOWS)  if (OPENAL)    set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") -endif (OPENAL) - -if (FMOD) -  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") +endif (OPENAL)           -  if (DARWIN) -    set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) -    add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) -    set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) -    set_target_properties( -      fmodwrapper -      PROPERTIES -      BUILD_WITH_INSTALL_RPATH 1 -      INSTALL_NAME_DIR "@executable_path/../Resources" -      LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" -      ) -    set(FMODWRAPPER_LIBRARY fmodwrapper) -    target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) -  else (DARWIN) -    # fmodwrapper unnecessary on linux or windows -    set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) -  endif (DARWIN) -endif (FMOD) +if (FMODEX) +  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") +  set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) +endif (FMODEX)  set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") @@ -1636,9 +1622,6 @@ if (WINDOWS)        ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll        ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll        ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll -      ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll -      ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll -      ${SHARED_LIB_STAGING_DIR}/Debug/fmod.dll        ${SHARED_LIB_STAGING_DIR}/Release/msvcr100.dll        ${SHARED_LIB_STAGING_DIR}/Release/msvcp100.dll        ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr100.dll @@ -1703,6 +1686,14 @@ if (WINDOWS)        windows-updater        ) +    if (FMODEX) +      list(APPEND COPY_INPUT_DEPENDENCIES +           ${SHARED_LIB_STAGING_DIR}/Release/fmodex.dll +           ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodex.dll +           ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll +          ) +    endif (FMODEX) +          add_custom_command(        OUTPUT  ${CMAKE_CFG_INTDIR}/copy_touched.bat        COMMAND ${PYTHON_EXECUTABLE} diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f66d8fca5b..3281d347a7 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -291,6 +291,17 @@        <key>Value</key>        <real>1.0</real>      </map> +    <key>AudioLevelUnderwaterRolloff</key> +    <map> +      <key>Comment</key> +      <string>Controls the distance-based dropoff of audio volume underwater(fraction or multiple of default audio rolloff)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>5.0</real> +    </map>      <key>AudioLevelSFX</key>      <map>        <key>Comment</key> @@ -14446,7 +14457,50 @@      <key>Value</key>      <integer>0</integer>    </map> - +  <key>DisablePrecacheDelayAfterTeleporting</key> +  <map> +    <key>Comment</key> +    <string>Disables the artificial delay in the viewer that precaches some incoming assets</string> +    <key>Persist</key> +    <integer>0</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>FMODExProfilerEnable</key> +  <map> +    <key>Comment</key> +    <string>Enable profiler tool if using FMOD Ex</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +    </map> +  <key>FMODExDecodeBufferSize</key> +  <map> +    <key>Comment</key> +    <string>Sets the streaming decode buffer size (in milliseconds)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>1000</integer> +    </map> +  <key>FMODExStreamBufferSize</key> +  <map> +    <key>Comment</key> +    <string>Sets the streaming buffer size (in milliseconds)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>7000</integer> +  </map>    <key>DisablePrecacheDelayAfterTeleporting</key>    <map>      <key>Comment</key> diff --git a/indra/newview/fmod_hidden_symbols.exp b/indra/newview/fmod_hidden_symbols.exp deleted file mode 100644 index 1e790255bc..0000000000 --- a/indra/newview/fmod_hidden_symbols.exp +++ /dev/null @@ -1,240 +0,0 @@ -_CarbonSndPlayDoubleBuffer -_ConvertFromIeeeExtended -__book_maptype1_quantvals -__book_unquantize -__float32_pack -__float32_unpack -__ilog -__make_words -_lpc_clear -_lpc_init -__vorbis_block_alloc -__vorbis_block_ripcord -__vorbis_apply_window -__vorbis_window_get -_vorbis_analysis_blockout -_vorbis_analysis_buffer -_vorbis_analysis_wrote -_vorbis_block_clear -_vorbis_block_init -_vorbis_dsp_clear -_vorbis_synthesis_blockin -_vorbis_synthesis_init -_vorbis_synthesis_pcmout -_vorbis_synthesis_read -_vorbis_packet_blocksize -_vorbis_synthesis -_vorbis_book_clear -_vorbis_book_decode -_vorbis_book_decodev_add -_vorbis_book_decodev_set -_vorbis_book_decodevs_add -_vorbis_book_decodevv_add -_vorbis_book_init_decode -_vorbis_comment_add -_vorbis_comment_add_tag -_vorbis_comment_clear -_vorbis_comment_init -_vorbis_comment_query -_vorbis_comment_query_count -_vorbis_coslook -_vorbis_fromdBlook -_vorbis_info_blocksize -_vorbis_info_clear -_vorbis_info_init -_vorbis_invsq2explook -_vorbis_invsqlook -_vorbis_lpc_from_curve -_vorbis_lpc_from_data -_vorbis_lpc_predict -_vorbis_lsp_to_curve -_vorbis_staticbook_clear -_vorbis_staticbook_destroy -_vorbis_staticbook_unpack -_vorbis_synthesis_headerin -_vorbis_synthesis_lapout -_vorbis_synthesis_restart -_vorbis_synthesis_trackonly -_vorbis_window -_ogg_packet_clear -_ogg_page_bos -_ogg_page_checksum_set -_ogg_page_continued -_ogg_page_eos -_ogg_page_granulepos -_ogg_page_packets -_ogg_page_pageno -_ogg_page_serialno -_ogg_page_version -_ogg_stream_reset_serialno -_ogg_stream_clear -_ogg_stream_destroy -_ogg_stream_eos -_ogg_stream_flush -_ogg_stream_init -_ogg_stream_packetout -_ogg_stream_packetpeek -_ogg_stream_pagein -_ogg_stream_pageout -_ogg_stream_reset -_ogg_sync_buffer -_ogg_sync_clear -_ogg_sync_destroy -_ogg_sync_init -_ogg_sync_pageout -_ogg_sync_pageseek -_ogg_sync_reset -_ogg_sync_wrote -_ov_bitrate -_ov_bitrate_instant -_ov_clear -_ov_comment -_ov_info -_ov_open -_ov_open_callbacks -_ov_pcm_seek -_ov_pcm_seek_page -_ov_pcm_tell -_ov_pcm_total -_ov_raw_seek -_ov_raw_tell -_ov_raw_total -_ov_read -_ov_read_float -_ov_seekable -_ov_serialnumber -_ov_streams -_ov_test -_ov_test_callbacks -_ov_test_open -_ov_time_seek -_ov_time_seek_page -_ov_time_tell -_ov_time_total -_ogg_toupper -_oggpackB_adv -_oggpackB_adv1 -_oggpackB_bits -_oggpackB_bytes -_oggpackB_get_buffer -_oggpackB_look -_oggpackB_look1 -_oggpackB_read -_oggpackB_read1 -_oggpackB_readinit -_oggpackB_reset -_oggpack_adv -_oggpack_adv1 -_oggpack_bits -_oggpack_bytes -_oggpack_get_buffer -_oggpack_look -_oggpack_look1 -_oggpack_read -_oggpack_read1 -_oggpack_readinit -_oggpack_reset -_ov_crosslap -_ov_pcm_seek_lap -_ov_pcm_seek_page_lap -_ov_raw_seek_lap -_ov_time_seek_lap -_ov_time_seek_page_lap -_II_step_one -_II_step_two -_MyRecComp -_SampleRates -_Sinfo -_ValidStepIndex -__Z11fmodwrapperv -__Z11fmodwrapperv.eh -__floor_P -__mapping_P -__residue_P -__ve_envelope_clear -__ve_envelope_init -__ve_envelope_mark -__ve_envelope_search -__ve_envelope_shift -__vi_gpsy_free -__vi_psy_free -__vorbis_window_init -__vp_ampmax_decay -__vp_couple -__vp_global_free -__vp_global_look -__vp_noise_normalize -__vp_noise_normalize_sort -__vp_noisemask -__vp_offset_and_mix -__vp_psy_clear -__vp_psy_init -__vp_quantize_couple_memo -__vp_quantize_couple_sort -__vp_remove_floor -__vp_tonemask -_alloc_0 -_alloc_1 -_alloc_2 -_alloc_3 -_alloc_4 -_bandInfo -_cdcallback -_cdchannel -_cdmode -_cdnumtracks -_cdstream -_cdtrack -_drft_backward -_drft_clear -_drft_forward -_drft_init -_eatwhite -_floor0_exportbundle -_floor1_exportbundle -_gFreeList -_gNMRecBusy -_gNMRecPtr -_gSilenceOnes -_gSilenceTwos -_longLimit -_mapping0_exportbundle -_mdct_backward -_mdct_clear -_mdct_forward -_mdct_init -_muls -_mystrdup -_res0_free_info -_res0_free_look -_res0_inverse -_res0_look -_res0_unpack -_res1_class -_res1_inverse -_res2_inverse -_residue0_exportbundle -_residue1_exportbundle -_residue2_exportbundle -_scale -_shortLimit -_tabsel_123 -_F_Free -_F_Malloc -_F_ReAlloc -_F_memcmp -_F_memmove -_F_strcat -_F_strchr -_F_strcmp -_F_strcpy -_F_stricmp -_F_strlen -_F_strncat -_F_strncmp -_F_strncpy -_F_strnicmp -_F_strstr -_F_strupr -_F_tolower -_F_toupper diff --git a/indra/newview/fmodwrapper.cpp b/indra/newview/fmodwrapper.cpp deleted file mode 100644 index 16f1d19a78..0000000000 --- a/indra/newview/fmodwrapper.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/**  - * @file fmodwrapper.cpp - * @brief dummy source file for building a shared library to wrap libfmod.a - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -extern "C" -{ -	void FSOUND_Init(void); -} - -void* fmodwrapper(void) -{ -	// When building the fmodwrapper library, the linker doesn't seem to want to bring in libfmod.a unless I explicitly -	// reference at least one symbol in the library.  This seemed like the simplest way. -	return (void*)&FSOUND_Init; -} diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 1381e49c62..48b883e999 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,17 +4,17 @@  ## These options are for self-assisted troubleshooting during this beta  ## testing phase; you should not usually need to touch them. +## - Avoids using any FMOD Ex audio driver. +#export LL_BAD_FMODEX_DRIVER=x  ## - Avoids using any OpenAL audio driver.  #export LL_BAD_OPENAL_DRIVER=x -## - Avoids using any FMOD audio driver. -#export LL_BAD_FMOD_DRIVER=x -## - Avoids using the FMOD ESD audio driver. -#export LL_BAD_FMOD_ESD=x -## - Avoids using the FMOD OSS audio driver. -#export LL_BAD_FMOD_OSS=x -## - Avoids using the FMOD ALSA audio driver. +## - Avoids using the FMOD Ex PulseAudio audio driver. +#export LL_BAD_FMOD_PULSEAUDIO=x +## - Avoids using the FMOD or FMOD Ex ALSA audio driver.  #export LL_BAD_FMOD_ALSA=x +## - Avoids using the FMOD or FMOD Ex OSS audio driver. +#export LL_BAD_FMOD_OSS=x  ## - Avoids the optional OpenGL extensions which have proven most problematic  ##   on some hardware.  Disabling this option may cause BETTER PERFORMANCE but diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3adf956ae3..97962b8705 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1707,19 +1707,7 @@ bool LLAppViewer::cleanup()  		gAudiop->setStreamingAudioImpl(NULL);  		// shut down the audio subsystem - -		bool want_longname = false; -		if (gAudiop->getDriverName(want_longname) == "FMOD") -		{ -			// This hack exists because fmod likes to occasionally -			// crash or hang forever when shutting down, for no -			// apparent reason. -			llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush; -		} -		else -		{ -			gAudiop->shutdown(); -		} +        gAudiop->shutdown();  		delete gAudiop;  		gAudiop = NULL; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8b71f1067f..9d5fd46a1d 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -37,8 +37,8 @@  #include "llviewermedia_streamingaudio.h"  #include "llaudioengine.h" -#ifdef LL_FMOD -# include "llaudioengine_fmod.h" +#ifdef LL_FMODEX +# include "llaudioengine_fmodex.h"  #endif  #ifdef LL_OPENAL @@ -623,32 +623,32 @@ bool idle_startup()  		{  			gAudiop = NULL; -#ifdef LL_OPENAL +#ifdef LL_FMODEX		  			if (!gAudiop  #if !LL_WINDOWS -			    && NULL == getenv("LL_BAD_OPENAL_DRIVER") +			    && NULL == getenv("LL_BAD_FMODEX_DRIVER")  #endif // !LL_WINDOWS  			    )  			{ -				gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); +				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable"));  			}  #endif -#ifdef LL_FMOD			 +#ifdef LL_OPENAL  			if (!gAudiop  #if !LL_WINDOWS -			    && NULL == getenv("LL_BAD_FMOD_DRIVER") +			    && NULL == getenv("LL_BAD_OPENAL_DRIVER")  #endif // !LL_WINDOWS  			    )  			{ -				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); +				gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();  			}  #endif - +              			if (gAudiop)  			{  #if LL_WINDOWS -				// FMOD on Windows needs the window handle to stop playing audio +				// FMOD Ex on Windows needs the window handle to stop playing audio  				// when window is minimized. JC  				void* window_handle = (HWND)gViewerWindow->getPlatformWindow();  #else diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 564bf7997a..094694dc06 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -44,6 +44,8 @@  #include "llparcel.h"  #include "llviewermessage.h" +#include "llstreamingaudio.h" +  /////////////////////////////////////////////////////////  LLViewerAudio::LLViewerAudio() : @@ -102,6 +104,11 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)  		else  		{  			mFadeState = FADE_IN; + +			LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl(); +			if(stream && stream->supportsAdjustableBufferSizes()) +				stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize")); +  			gAudiop->startInternetStream(mNextStreamURI);  			startFading();  			registerIdleListener(); @@ -157,6 +164,11 @@ bool LLViewerAudio::onIdleUpdate()  			if (!mNextStreamURI.empty())  			{  				mFadeState = FADE_IN; + +				LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl(); +				if(stream && stream->supportsAdjustableBufferSizes()) +					stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize")); +  				gAudiop->startInternetStream(mNextStreamURI);  				startFading();  			} @@ -386,7 +398,12 @@ void audio_update_volume(bool force_update)  		gAudiop->setMasterGain ( master_volume );  		gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler")); -		gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); + +		if(!LLViewerCamera::getInstance()->cameraUnderWater()) +			gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); +		else +			gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelUnderwaterRolloff")); +  		gAudiop->setMuted(mute_audio || progress_view_visible);  		//Play any deferred sounds when unmuted @@ -473,44 +490,22 @@ void audio_update_listener()  void audio_update_wind(bool force_update)  {  #ifdef kAUDIO_ENABLE_WIND -	// -	//  Extract height above water to modulate filter by whether above/below water  -	//  +  	LLViewerRegion* region = gAgent.getRegion();  	if (region)  	{ -		static F32 last_camera_water_height = -1000.f; -		LLVector3 camera_pos = gAgentCamera.getCameraPositionAgent(); -		F32 camera_water_height = camera_pos.mV[VZ] - region->getWaterHeight(); -		 -		// -		//  Don't update rolloff factor unless water surface has been crossed -		// -		if (force_update || (last_camera_water_height * camera_water_height) < 0.f) -		{ -            static LLUICachedControl<F32> rolloff("AudioLevelRolloff", 1.0f); -			if (camera_water_height < 0.f) -			{ -				gAudiop->setRolloffFactor(rolloff * LL_ROLLOFF_MULTIPLIER_UNDER_WATER); -			} -			else  -			{ -				gAudiop->setRolloffFactor(rolloff); -			} -		} -         -        // Scale down the contribution of weather-simulation wind to the -        // ambient wind noise.  Wind velocity averages 3.5 m/s, with gusts to 7 m/s -        // whereas steady-state avatar walk velocity is only 3.2 m/s. -        // Without this the world feels desolate on first login when you are -        // standing still. -        static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); -        LLVector3 scaled_wind_vec = gWindVec * wind_level; -         -        // Mix in the avatar's motion, subtract because when you walk north, -        // the apparent wind moves south. -        LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); -         +		// Scale down the contribution of weather-simulation wind to the +		// ambient wind noise.  Wind velocity averages 3.5 m/s, with gusts to 7 m/s +		// whereas steady-state avatar walk velocity is only 3.2 m/s. +		// Without this the world feels desolate on first login when you are +		// standing still. +		static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); +		LLVector3 scaled_wind_vec = gWindVec * wind_level; + +		// Mix in the avatar's motion, subtract because when you walk north, +		// the apparent wind moves south. +		LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); +  		// rotate the wind vector to be listener (agent) relative  		gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec ); @@ -543,8 +538,7 @@ void audio_update_wind(bool force_update)  			gAudiop->mMaxWindGain = llmax(gAudiop->mMaxWindGain - volume_delta, 0.f);  		} -		last_camera_water_height = camera_water_height; -		gAudiop->updateWind(gRelativeWindVec, camera_water_height); +		gAudiop->updateWind(gRelativeWindVec, gAgentCamera.getCameraPositionAgent()[VZ] - gAgent.getRegion()->getWaterHeight());  	}  #endif  } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 051f5f4485..a62f73deef 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -655,6 +655,7 @@ void settings_setup_listeners()  	gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));  	gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));  	gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); +	gSavedSettings.getControl("AudioLevelUnderwaterRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));  	gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));  	gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));  	gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 69248e26bc..e2b914aae8 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -367,10 +367,14 @@ class WindowsManifest(ViewerManifest):                  print err.message                  print "Skipping COLLADA and GLOD libraries (assumming linked statically)" - -            # Get fmod dll, continue if missing -            if not self.path("fmod.dll"): -                print "Skipping fmod.dll" +            # Get fmodex dll, continue if missing +            try: +                if self.args['configuration'].lower() == 'debug': +                    self.path("fmodexL.dll") +                else: +                    self.path("fmodex.dll") +            except: +                print "Skipping fmodex audio library(assuming other audio engine)"              # For textures              if self.args['configuration'].lower() == 'debug': @@ -743,6 +747,7 @@ class DarwinManifest(ViewerManifest):                                  "libcollada14dom.dylib",                                  "libexpat.1.5.2.dylib",                                  "libexception_handler.dylib", +                                "libfmodex.dylib",                                  "libGLOD.dylib",                                  ):                      dylibs += path_optional(os.path.join(libdir, libfile), libfile) @@ -757,11 +762,7 @@ class DarwinManifest(ViewerManifest):                                  'SLVoice',                                  ):                       self.path2basename(libdir, libfile) -                 -                # FMOD for sound -                libfile = "libfmodwrapper.dylib" -                path_optional(os.path.join(self.args['configuration'], libfile), libfile) -                 +                  # our apps                  for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),                                           ("mac_updater", "mac-updater.app"), @@ -1122,11 +1123,13 @@ class Linux_i686Manifest(LinuxManifest):                  pass              try: -                    self.path("libfmod-3.75.so") +                    self.path("libfmodex-*.so") +                    self.path("libfmodex.so")                      pass              except: -                    print "Skipping libfmod-3.75.so - not found" +                    print "Skipping libfmodex.so - not found"                      pass +              self.end_prefix("lib")              # Vivox runtimes | 
