diff --git a/autobuild.xml b/autobuild.xml
index 5346c8ef4086f491514305c3d5ba9f01ce91de5a..1558b574331da83c3758788df103346eaf2820bf 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -793,6 +793,94 @@
         <key>version</key>
         <string>4.44.64.201709041433</string>
       </map>
+      <key>fmodstudio</key>
+      <map>
+        <key>copyright</key>
+        <string>FMOD Studio, copyright (c) Firelight Technologies Pty, Ltd., 2012-2017.</string>
+        <key>description</key>
+        <string>FMOD Studio audio system library</string>
+        <key>license</key>
+        <string>fmodstudio</string>
+        <key>license_file</key>
+        <string>LICENSES/fmodstudio.txt</string>
+        <key>name</key>
+        <string>fmodstudio</string>
+        <key>platforms</key>
+        <map>
+          <key>darwin64</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>a3ccf7916d1e0b6f01370978b661c139</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
+              <key>url</key>
+              <string>https://depot.alchemyviewer.org/pub/darwin/lib/fmodstudio-1.10.02-darwin-201712262058.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>darwin64</string>
+          </map>
+          <key>linux</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>1331456a3df95294eaf44fab990f62cd</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
+              <key>url</key>
+              <string>https://depot.alchemyviewer.org/pub/linux/lib/fmodstudio-1.06.07-linux-201507231333.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>linux</string>
+          </map>
+          <key>linux64</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>54dbd41322a08a1fc333ca6d96af5502</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
+              <key>url</key>
+              <string>https://depot.alchemyviewer.org/pub/linux64/lib/fmodstudio-1.10.00-linux64-201709282320.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>linux64</string>
+          </map>
+          <key>windows</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>b23a30967666da49346983658ed50e92</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
+              <key>url</key>
+              <string>https://depot.alchemyviewer.org/pub/windows/lib/fmodstudio-1.10.00-windows-201709290225.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>windows</string>
+          </map>
+          <key>windows64</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>c2c45c2ebd9fd930098aa2a3b85bbe5f</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
+              <key>url</key>
+              <string>https://bitbucket.org/NiranV/fmodex/downloads/fmodstudio-1.10.02-windows64-201712251435.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>windows64</string>
+          </map>
+        </map>
+        <key>version</key>
+        <string>1.10.02</string>
+      </map>
       <key>fontconfig</key>
       <map>
         <key>copyright</key>
@@ -4036,7 +4124,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
                   <string>-DINSTALL_PROPRIETARY=FALSE</string>
                   <string>-DUSE_KDU=FALSE</string>
                   <string>-DLL_TESTS=FALSE</string>
-                  <string>-DFMODEX=TRUE</string>
+                  <string>-DFMODSTUDIO:BOOL=ON</string>
                   <string>-DPACKAGE:BOOL=FALSE</string>
                 </array>
               </map>
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 4a3ebe4835bff370129a9409b3d93a78dcb77496..e0e7e9234e441d115555e5e30a802fa10629efcd 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -27,7 +27,7 @@ set(cmake_SOURCE_FILES
     FindAPR.cmake
     FindAutobuild.cmake
     FindBerkeleyDB.cmake
-    FindFMODEX.cmake
+    FindFMODSTUDIO.cmake
     FindGLH.cmake
     FindGoogleBreakpad.cmake
     FindHUNSPELL.cmake
@@ -38,7 +38,7 @@ set(cmake_SOURCE_FILES
     FindURIPARSER.cmake
     FindXmlRpcEpi.cmake
     FindZLIB.cmake
-    FMODEX.cmake
+    FMODSTUDIO.cmake
     FreeType.cmake
     GLEXT.cmake
     GLH.cmake
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 09a97fc03e979b17bc68553aad0515f5c3c9d82a..e7356081ebb05bd0399c29dbde298e981daa6a7d 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -6,6 +6,8 @@
 
 include(CMakeCopyIfDifferent)
 include(Linking)
+include(Variables)
+include(LLCommon)
 
 ###################################################################
 # set up platform specific lists of files that need to be copied
@@ -49,14 +51,15 @@ if(WINDOWS)
         libhunspell.dll
         )
 
-    if (FMODEX)
-
-        if(ADDRESS_SIZE EQUAL 32)
-            set(release_files ${release_files} fmodex.dll)
-        else(ADDRESS_SIZE EQUAL 32)
-            set(release_files ${release_files} fmodex64.dll)
-        endif(ADDRESS_SIZE EQUAL 32)
-    endif (FMODEX)
+    if (FMODSTUDIO)
+      if(ADDRESS_SIZE STREQUAL 64)
+        list(APPEND debug_files fmodL64.dll)
+        list(APPEND release_files fmod64.dll)
+      else(ADDRESS_SIZE STREQUAL 64)
+        list(APPEND debug_files fmodL.dll)
+        list(APPEND release_files fmod.dll)
+      endif(ADDRESS_SIZE STREQUAL 64)
+    endif (FMODSTUDIO)
 
     #*******************************
     # Copy MS C runtime dlls, required for packaging.
@@ -180,10 +183,14 @@ elseif(DARWIN)
         libnghttp2.14.14.0.dylib
        )
 
-    if (FMODEX)
-      set(debug_files ${debug_files} libfmodexL.dylib)
-      set(release_files ${release_files} libfmodex.dylib)
-    endif (FMODEX)
+    if (OPENAL)
+      list(APPEND release_files libopenal.dylib libalut.dylib)
+    endif (OPENAL)
+
+    if (FMODSTUDIO)
+      list(APPEND debug_files libfmodL.dylib)
+      list(APPEND release_files libfmod.dylib)
+    endif (FMODSTUDIO)
 
 elseif(LINUX)
     # linux is weird, multiple side by side configurations aren't supported
@@ -230,10 +237,14 @@ elseif(LINUX)
         libfontconfig.so.1
        )
 
-    if (FMODEX)
-      set(debug_files ${debug_files} "libfmodexL.so")
-      set(release_files ${release_files} "libfmodex.so")
-    endif (FMODEX)
+    if (USE_TCMALLOC)
+      list(APPEND release_files "libtcmalloc_minimal.so")
+    endif (USE_TCMALLOC)
+
+    if (FMODSTUDIO)
+      list(APPEND debug_files "libfmodL.so")
+      list(APPEND release_files "libfmod.so")
+    endif (FMODSTUDIO)
 
 else(WINDOWS)
     message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake
deleted file mode 100644
index 720933d1b794bf369e17b70bd81591f1b79ff274..0000000000000000000000000000000000000000
--- a/indra/cmake/FMODEX.cmake
+++ /dev/null
@@ -1,46 +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 FMODEX.
-# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether
-# they are using USESYSTEMLIBS or not.
-if (INSTALL_PROPRIETARY)
-  set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.")
-endif (INSTALL_PROPRIETARY)
-
-if (FMODEX)
-  if (USESYSTEMLIBS)
-    # In that case, we use the version of the library installed on the system
-    set(FMODEX_FIND_REQUIRED ON)
-    include(FindFMODEX)
-  else (USESYSTEMLIBS)
-    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 (USESYSTEMLIBS)
-endif (FMODEX)
-
diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b4e53245b349e60c5204e2b7dec64f865453aec1
--- /dev/null
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -0,0 +1,51 @@
+# -*- 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 FMODSTUDIO.
+# Open source devs should use the -DFMODSTUDIO:BOOL=ON then if they want to build with FMOD, whether
+# they are using STANDALONE or not.
+if (INSTALL_PROPRIETARY)
+  set(FMODSTUDIO ON)
+endif (INSTALL_PROPRIETARY)
+
+if (FMODSTUDIO)
+  if (STANDALONE)
+    # In that case, we use the version of the library installed on the system
+    set(FMODSTUDIO_FIND_REQUIRED ON)
+    include(FindFMODSTUDIO)
+  else (STANDALONE)
+    if (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR)
+      # If the path have been specified in the arguments, use that
+      set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY})
+      MESSAGE(STATUS "Using FMODSTUDIO path: ${FMODSTUDIO_LIBRARIES}, ${FMODSTUDIO_INCLUDE_DIR}")
+    else (FMODSTUDIO_LIBRARY AND FMODSTUDIO_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(fmodstudio)    
+      if (WINDOWS)
+        if (ADDRESS_SIZE EQUAL 32)
+          set(FMODSTUDIO_LIBRARY 
+              debug fmodL_vc
+              optimized fmod_vc)
+         elseif (ADDRESS_SIZE EQUAL 64)
+           set(FMODSTUDIO_LIBRARY 
+              debug fmodL64_vc
+              optimized fmod64_vc)
+         endif(ADDRESS_SIZE EQUAL 32)
+      elseif (DARWIN)
+        set(FMODSTUDIO_LIBRARY 
+            debug fmodL
+            optimized fmod)
+      elseif (LINUX)
+        set(FMODSTUDIO_LIBRARY 
+            debug fmodL
+            optimized fmod)
+      endif (WINDOWS)
+      set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY})
+      set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio)
+    endif (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR)
+  endif (STANDALONE)
+endif (FMODSTUDIO)
diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake
deleted file mode 100644
index b621727c0ea490c8d55c7d89f243813ab698bda6..0000000000000000000000000000000000000000
--- a/indra/cmake/FindFMODEX.cmake
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- 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
-  )
diff --git a/indra/cmake/FindFMODSTUDIO.cmake b/indra/cmake/FindFMODSTUDIO.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..2eb5660a7a36c1177eb68d9ae6e9794cac83a039
--- /dev/null
+++ b/indra/cmake/FindFMODSTUDIO.cmake
@@ -0,0 +1,65 @@
+# -*- cmake -*-
+
+# - Find FMODSTUDIO
+# Find the FMODSTUDIO includes and library
+# This module defines
+#  FMODSTUDIO_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
+#  FMODSTUDIO_LIBRARIES, the libraries needed to use FMODSTUDIO.
+#  FMODSTUDIO, If false, do not try to use FMODSTUDIO.
+# also defined, but not for general use are
+#  FMODSTUDIO_LIBRARY, where to find the FMODSTUDIO library.
+
+FIND_PATH(FMODSTUDIO_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
+
+SET(FMODSTUDIO_NAMES ${FMODSTUDIO_NAMES} fmod fmod_vc)
+FIND_LIBRARY(FMODSTUDIO_LIBRARY
+  NAMES ${FMODSTUDIO_NAMES}
+  PATH_SUFFIXES fmod
+  )
+
+IF (FMODSTUDIO_SDK_DIR OR WINDOWS)
+    if(WINDOWS)
+        set(FMODSTUDIO_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODSTUDIO")
+        STRING(REGEX REPLACE "\\\\" "/" FMODSTUDIO_SDK_DIR ${FMODSTUDIO_SDK_DIR}) 
+    endif(WINDOWS)
+    find_library(FMODSTUDIO_LIBRARY
+             fmod_vc fmodL_vc 
+             PATHS
+             ${FMODSTUDIO_SDK_DIR}/api/lib
+             ${FMODSTUDIO_SDK_DIR}/api
+             ${FMODSTUDIO_SDK_DIR}
+             )
+    find_path(FMODSTUDIO_INCLUDE_DIR fmod.h
+        ${FMODSTUDIO_SDK_DIR}/api/inc
+        ${FMODSTUDIO_SDK_DIR}/api
+        ${FMODSTUDIO_SDK_DIR}
+      )
+    find_path(FMODSTUDIO_INCLUDE_DIR fmod.h
+        ${FMODSTUDIO_SDK_DIR}/api/inc
+        ${FMODSTUDIO_SDK_DIR}/api
+        ${FMODSTUDIO_SDK_DIR}
+      )
+    IF (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR)
+      SET(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY})
+      SET(FMODSTUDIO_FOUND "YES")
+    endif (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR)
+ENDIF (FMODSTUDIO_SDK_DIR OR WINDOWS)
+
+IF (FMODSTUDIO_FOUND)
+  IF (NOT FMODSTUDIO_FIND_QUIETLY)
+    MESSAGE(STATUS "Found FMODSTUDIO: ${FMODSTUDIO_LIBRARIES}")
+  ENDIF (NOT FMODSTUDIO_FIND_QUIETLY)
+ELSE (FMODSTUDIO_FOUND)
+  IF (FMODSTUDIO_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find FMODSTUDIO library")
+  ENDIF (FMODSTUDIO_FIND_REQUIRED)
+ENDIF (FMODSTUDIO_FOUND)
+
+# Deprecated declarations.
+SET (NATIVE_FMODSTUDIO_INCLUDE_PATH ${FMODSTUDIO_INCLUDE_DIR} )
+GET_FILENAME_COMPONENT (NATIVE_FMODSTUDIO_LIB_PATH ${FMODSTUDIO_LIBRARY} PATH)
+
+MARK_AS_ADVANCED(
+  FMODSTUDIO_LIBRARY
+  FMODSTUDIO_INCLUDE_DIR
+  )
\ No newline at end of file
diff --git a/indra/cmake/LLAudio.cmake b/indra/cmake/LLAudio.cmake
index 7c248dfc7205231fc563e3ea0fffea88fb849cf1..94b45fbd58e0becae685c90b241df44cc18355dc 100644
--- a/indra/cmake/LLAudio.cmake
+++ b/indra/cmake/LLAudio.cmake
@@ -1,6 +1,7 @@
 # -*- cmake -*-
 
 include(Audio)
+include(OPENAL)
 
 set(LLAUDIO_INCLUDE_DIRS
     ${LIBS_OPEN_DIR}/llaudio
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index e943dd5d5ccd059100c1ad41507a3f5d377b73d1..eb79c463a12b55192878ec7bca609753d90bd12a 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -4,7 +4,7 @@ project(llaudio)
 
 include(00-Common)
 include(LLAudio)
-include(FMODEX)
+include(FMODSTUDIO)
 include(OPENAL)
 include(LLCommon)
 include(LLMath)
@@ -38,26 +38,27 @@ set(llaudio_HEADER_FILES
     llaudioengine.h
     lllistener.h
     llaudiodecodemgr.h
+	llstreamingaudio.h
     llvorbisencode.h
     llwindgen.h
     )
 
-if (FMODEX)
+if (FMODSTUDIO)
     include_directories(
-        ${FMODEX_INCLUDE_DIR}
+        ${FMODSTUDIO_INCLUDE_DIR}
         )
     list(APPEND llaudio_SOURCE_FILES
-         llaudioengine_fmodex.cpp
-         lllistener_fmodex.cpp
-         llstreamingaudio_fmodex.cpp
+         llaudioengine_fmodstudio.cpp
+         lllistener_fmodstudio.cpp
+         llstreamingaudio_fmodstudio.cpp
          )
 
     list(APPEND llaudio_HEADER_FILES
-         llaudioengine_fmodex.h
-         lllistener_fmodex.h
-         llstreamingaudio_fmodex.h
+         llaudioengine_fmodstudio.h
+         lllistener_fmodstudio.h
+         llstreamingaudio_fmodstudio.h
          )
-endif (FMODEX)
+endif (FMODSTUDIO)
 
 if (OPENAL)
   list(APPEND llaudio_SOURCE_FILES
@@ -83,6 +84,7 @@ target_link_libraries(
     ${LLMATH_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
     ${LLVFS_LIBRARIES}
+    ${LLXML_LIBRARIES}
     ${VORBISENC_LIBRARIES}
     ${VORBISFILE_LIBRARIES}
     ${VORBIS_LIBRARIES}
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index f49028aad51955fbc5a606cda3ebcf9f2985e43e..2fce0bf84cc804d143f75930e3754655228153df 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -69,6 +69,7 @@ LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl()
 
 void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl)
 {
+	delete mStreamingAudioImpl;
 	mStreamingAudioImpl = impl;
 }
 
@@ -133,14 +134,19 @@ void LLAudioEngine::shutdown()
 {
 	// Clean up decode manager
 	delete gAudioDecodeMgrp;
-	gAudioDecodeMgrp = NULL;
+	gAudioDecodeMgrp = nullptr;
 
 	// Clean up wind source
 	cleanupWind();
 
+	// Clean up streaming audio
+	stopInternetStream();
+	delete mStreamingAudioImpl;
+	mStreamingAudioImpl = nullptr;
+
 	// Clean up audio sources
 	source_map::iterator iter_src;
-	for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
+	for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); ++iter_src)
 	{
 		delete iter_src->second;
 	}
@@ -148,7 +154,7 @@ void LLAudioEngine::shutdown()
 
 	// Clean up audio data
 	data_map::iterator iter_data;
-	for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++)
+	for (iter_data = mAllData.begin(); iter_data != mAllData.end(); ++iter_data)
 	{
 		delete iter_data->second;
 	}
@@ -159,14 +165,14 @@ void LLAudioEngine::shutdown()
 	for (i = 0; i < MAX_CHANNELS; i++)
 	{
 		delete mChannels[i];
-		mChannels[i] = NULL;
+		mChannels[i] = nullptr;
 	}
 
 	// Clean up buffers
 	for (i = 0; i < MAX_BUFFERS; i++)
 	{
 		delete mBuffers[i];
-		mBuffers[i] = NULL;
+		mBuffers[i] = nullptr;
 	}
 }
 
@@ -749,7 +755,7 @@ void LLAudioEngine::setMaxWindGain(F32 gain)
 }
 
 
-F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
+F64 LLAudioEngine::mapWindVecToGain(const LLVector3& wind_vec)
 {
 	F64 gain = 0.0;
 	
@@ -768,7 +774,7 @@ F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
 } 
 
 
-F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
+F64 LLAudioEngine::mapWindVecToPitch(const LLVector3& wind_vec)
 {
 	LLVector3 listen_right;
 	F64 theta;
@@ -792,7 +798,7 @@ F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
 }
 
 
-F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec)
+F64 LLAudioEngine::mapWindVecToPan(const LLVector3& wind_vec)
 {
 	LLVector3 listen_right;
 	F64 theta;
@@ -841,14 +847,17 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i
 	asp->play(audio_uuid);
 }
 
-void LLAudioEngine::triggerSound(SoundData& soundData)
+void LLAudioEngine::triggerSound(const SoundData& soundData)
 {
 	triggerSound(soundData.audio_uuid, soundData.owner_id, soundData.gain, soundData.type, soundData.pos_global);
 }
 
-void LLAudioEngine::setListenerPos(LLVector3 aVec)
+void LLAudioEngine::setListenerPos(const LLVector3& aVec)
 {
-	mListenerp->setPosition(aVec);  
+	if (mListenerp)
+	{
+		mListenerp->setPosition(aVec);
+	}
 }
 
 
@@ -856,36 +865,47 @@ LLVector3 LLAudioEngine::getListenerPos()
 {
 	if (mListenerp)
 	{
-		return(mListenerp->getPosition());  
+		return mListenerp->getPosition();
 	}
 	else
 	{
-		return(LLVector3::zero);
+		return LLVector3::zero;
+	}
+}
+
+void LLAudioEngine::setListenerVelocity(const LLVector3& aVec)
+{
+	if (mListenerp)
+	{
+		mListenerp->setVelocity(aVec);
 	}
 }
 
 
-void LLAudioEngine::setListenerVelocity(LLVector3 aVec)
+void LLAudioEngine::translateListener(const LLVector3& aVec)
 {
-	mListenerp->setVelocity(aVec);  
-}
-
-
-void LLAudioEngine::translateListener(LLVector3 aVec)
-{
-	mListenerp->translate(aVec);	
+	if (mListenerp)
+	{
+		mListenerp->translate(aVec);
+	}
 }
 
 
-void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at)
+void LLAudioEngine::orientListener(const LLVector3& up, const LLVector3& at)
 {
-	mListenerp->orient(up, at);  
+	if (mListenerp)
+	{
+		mListenerp->orient(up, at);
+	}
 }
 
 
-void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
+void LLAudioEngine::setListener(const LLVector3& pos, const LLVector3& vel, const LLVector3& up, const LLVector3& at)
 {
-	mListenerp->set(pos,vel,up,at);  
+	if (mListenerp)
+	{
+		mListenerp->set(pos, vel, up, at);
+	}
 }
 
 
@@ -935,7 +955,10 @@ F32 LLAudioEngine::getRolloffFactor()
 
 void LLAudioEngine::commitDeferredChanges()
 {
-	mListenerp->commitDeferredChanges();  
+	if (mListenerp)
+	{
+		mListenerp->commitDeferredChanges();
+	}
 }
 
 
@@ -946,7 +969,7 @@ LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id)
 
 	if (iter == mAllSources.end())
 	{
-		return NULL;
+		return nullptr;
 	}
 	else
 	{
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index f1e1b4e308c79a440115011ed64a53c2dfe0343e..ea130d90fd995b17ee50109609f472aa6c183887 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -48,7 +48,7 @@ const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;
 const F32 DEFAULT_MIN_DISTANCE = 2.0f;
 
 #define MAX_CHANNELS 30
-#define MAX_BUFFERS 40	// Some extra for preloading, maybe?
+#define MAX_BUFFERS 60	// Some extra for preloading, maybe?
 
 // This define is intended to allow us to switch from os based wav
 // file loading to vfs based wav file loading. The problem is that I
@@ -105,7 +105,7 @@ class LLAudioEngine
 
 	// Used by the mechanics of the engine
 	//virtual void processQueue(const LLUUID &sound_guid);
-	virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at);
+	virtual void setListener(const LLVector3& pos, const LLVector3& vel, const LLVector3& up, const LLVector3& at);
 	virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0;
 	virtual void idle(F32 max_decode_time = 0.f);
 	virtual void updateChannels();
@@ -144,7 +144,7 @@ class LLAudioEngine
 	void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
 					  const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
 					  const LLVector3d &pos_global = LLVector3d::zero);
-	void triggerSound(SoundData& soundData);
+	void triggerSound(const SoundData& soundData);
 
 	bool preloadSound(const LLUUID &id);
 
@@ -202,15 +202,15 @@ class LLAudioEngine
 
 
 	// listener methods
-	virtual void setListenerPos(LLVector3 vec);
-	virtual void setListenerVelocity(LLVector3 vec);
-	virtual void orientListener(LLVector3 up, LLVector3 at);
-	virtual void translateListener(LLVector3 vec);
+	virtual void setListenerPos(const LLVector3& vec);
+	virtual void setListenerVelocity(const LLVector3& vec);
+	virtual void orientListener(const LLVector3& up, const LLVector3& at);
+	virtual void translateListener(const LLVector3& vec);
 
 
-	F64 mapWindVecToGain(LLVector3 wind_vec);
-	F64 mapWindVecToPitch(LLVector3 wind_vec);
-	F64 mapWindVecToPan(LLVector3 wind_vec);
+	F64 mapWindVecToGain(const LLVector3& wind_vec);
+	F64 mapWindVecToPitch(const LLVector3& wind_vec);
+	F64 mapWindVecToPan(const LLVector3& wind_vec);
 
 protected:
 	LLListener *mListenerp;
@@ -466,17 +466,17 @@ struct SoundData
 	S32 type;
 	LLVector3d pos_global;
 
-	SoundData(const LLUUID &audio_uuid, 
-		const LLUUID& owner_id, 
-		const F32 gain, 					  
-		const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
-		const LLVector3d &pos_global = LLVector3d::zero)
+	SoundData(const LLUUID &audio_uuid_in,
+		const LLUUID& owner_id_in,
+		const F32 gain_in,
+		const S32 type_in = LLAudioEngine::AUDIO_TYPE_NONE,
+		const LLVector3d &pos_global_in = LLVector3d::zero) :
+		audio_uuid(audio_uuid_in),
+		owner_id(owner_id_in),
+		gain(gain_in),
+		type(type_in),
+		pos_global(pos_global_in)
 	{
-		this->audio_uuid = audio_uuid;
-		this->owner_id = owner_id;
-		this->gain = gain;
-		this->type = type;
-		this->pos_global = pos_global;
 	}
 };
 
diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp
deleted file mode 100644
index 7e65a05e48ab561f7c65b9cdd406571c5f2bba42..0000000000000000000000000000000000000000
--- a/indra/llaudio/llaudioengine_fmodex.cpp
+++ /dev/null
@@ -1,767 +0,0 @@
-/** 
- * @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) 2014, 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;
-	mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
-}
-
-
-LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX()
-{
-	delete mWindDSPDesc;
-}
-
-
-inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
-{
-	if(result == FMOD_OK)
-		return false;
-	LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
-	return true;
-}
-
-void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
-{
-	if(type & FMOD_MEMORY_STREAM_DECODE)
-	{
-		LL_INFOS() << "Decode buffer size: " << size << LL_ENDL;
-	}
-	else if(type & FMOD_MEMORY_STREAM_FILE)
-	{
-		LL_INFOS() << "Strean buffer size: " << size << LL_ENDL;
-	}
-	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;
-
-	// turn off non-error log spam to fmod.log (TODO: why do we even have an fmod.log if we don't link against log lib?)
-	FMOD::Debug_SetLevel(FMOD_DEBUG_LEVEL_ERROR);
-
-	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;
-	mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL;
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_numbuffers=" << r_numbuffers << LL_ENDL;
-
-	mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits);
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL;
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_channels=" << r_channels << LL_ENDL;
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bits =" << r_bits << LL_ENDL;
-
-	char r_name[512];
-	mSystem->getDriverInfo(0, r_name, 511, 0);
-	r_name[511] = '\0';
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_name=\"" << r_name << "\"" <<  LL_ENDL;
-
-	int latency = 100; // optimistic default - i suspect if sample rate is 0, everything breaks. 
-	if ( r_samplerate != 0 )
-		latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate);
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): latency=" << latency << "ms" << LL_ENDL;
-
-	mInited = true;
-
-	LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): initialization complete." << LL_ENDL;
-
-	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)
-	{
-		LL_WARNS() << "Listener creation failed" << LL_ENDL;
-	}
-}
-
-
-void LLAudioEngine_FMODEX::shutdown()
-{
-	stopInternetStream();
-
-	LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL;
-	LLAudioEngine::shutdown();
-	
-	LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL;
-	if ( mSystem ) // speculative fix for MAINT-2657
-	{
-		mSystem->close();
-		mSystem->release();
-	}
-	LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL;
-
-	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)
-	{
-		memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc));	//Set everything to zero
-		strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name));
-		mWindDSPDesc->channels = 2;
-		mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads
-		if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &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);
-	}
-
-	// *TODO:  Should this guard against multiple plays?
-	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.
-			LL_ERRS() << "No FMOD sound!" << LL_ENDL;
-			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");
-		}
-
-		//LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL;
-	}
-
-	// 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;
-
-		mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
-		//Check_FMOD_Error(result, "FMOD::Channel::setVolume");
-
-		mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
-		/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
-		{
-			S32 index;
-			mChannelp->getIndex(&index);
- 			LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
- 					<< " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL;		
-		}*/
-	}
-
-	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)
-	{
-		//LL_INFOS() << "Aborting cleanup with no channel handle." << LL_ENDL;
-		return;
-	}
-
-	//LL_INFOS() << "Cleaning up channel: " << mChannelID << LL_ENDL;
-	Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
-
-	mCurrentBufferp = NULL;
-	mChannelp = NULL;
-}
-
-
-void LLAudioChannelFMODEX::play()
-{
-	if (!mChannelp)
-	{
-		LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL;
-		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.
-		LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL;
-
-		//
-		// 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(&current_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);
-	}
-}
-
-// *NOTE:  This is almost certainly being called on the mixer thread,
-// not the main thread.  May have implications for callees or audio
-// engine shutdown.
-
-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_fmodex.h b/indra/llaudio/llaudioengine_fmodex.h
deleted file mode 100644
index ca389d489fd981359e666ae50b250668a7489c90..0000000000000000000000000000000000000000
--- a/indra/llaudio/llaudioengine_fmodex.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/** 
- * @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
- * Copyright (C) 2014, 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$
- */
-
-#ifndef LL_AUDIOENGINE_FMODEX_H
-#define LL_AUDIOENGINE_FMODEX_H
-
-#include "llaudioengine.h"
-#include "llwindgen.h"
-
-//Stubs
-class LLAudioStreamManagerFMODEX;
-namespace FMOD
-{
-	class System;
-	class Channel;
-	class ChannelGroup;
-	class Sound;
-	class DSP;
-}
-typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
-
-//Interfaces
-class LLAudioEngine_FMODEX : public LLAudioEngine 
-{
-public:
-	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 void allocateListener();
-
-	virtual void shutdown();
-
-	/*virtual*/ bool initWind();
-	/*virtual*/ void cleanupWind();
-
-	/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
-
-	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);
-
-	bool mInited;
-
-	LLWindGen<MIXBUFFERFORMAT> *mWindGen;
-
-	FMOD_DSP_DESCRIPTION *mWindDSPDesc;
-	FMOD::DSP *mWindDSP;
-	FMOD::System *mSystem;
-	bool mEnableProfiler;
-
-public:
-	static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
-};
-
-
-class LLAudioChannelFMODEX : public LLAudioChannel
-{
-public:
-	LLAudioChannelFMODEX(FMOD::System *audioengine);
-	virtual ~LLAudioChannelFMODEX();
-
-protected:
-	/*virtual*/ void play();
-	/*virtual*/ void playSynced(LLAudioChannel *channelp);
-	/*virtual*/ void cleanup();
-	/*virtual*/ bool isPlaying();
-
-	/*virtual*/ bool updateBuffer();
-	/*virtual*/ void update3DPosition();
-	/*virtual*/ void updateLoop();
-
-	void set3DMode(bool use3d);
-protected:
-	FMOD::System *getSystem()	const {return mSystemp;}
-	FMOD::System *mSystemp;
-	FMOD::Channel *mChannelp;
-	S32 mLastSamplePos;
-};
-
-
-class LLAudioBufferFMODEX : public LLAudioBuffer
-{
-public:
-	LLAudioBufferFMODEX(FMOD::System *audioengine);
-	virtual ~LLAudioBufferFMODEX();
-
-	/*virtual*/ bool loadWAV(const std::string& filename);
-	/*virtual*/ U32 getLength();
-	friend class LLAudioChannelFMODEX;
-protected:
-	FMOD::System *getSystem()	const {return mSystemp;}
-	FMOD::System *mSystemp;
-	FMOD::Sound *getSound()		const{ return mSoundp; }
-	FMOD::Sound *mSoundp;
-};
-
-
-#endif // LL_AUDIOENGINE_FMODEX_H
diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f80cda019a2e45fab186561e0d9ccb4e95cfb73
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -0,0 +1,743 @@
+/**
+* @file audioengine_fmodstudio.cpp
+* @brief Implementation of LLAudioEngine class abstracting the audio
+* support as a FMOD Studio implementation
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, 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_fmodstudio.h"
+
+#include "llaudioengine_fmodstudio.h"
+#include "lllistener_fmodstudio.h"
+
+#include "llerror.h"
+#include "llmath.h"
+#include "llrand.h"
+
+#include "fmod.hpp"
+#include "fmod_errors.h"
+#include "lldir.h"
+
+#include "sound_ids.h"
+
+const U32 EXTRA_SOUND_CHANNELS = 32;
+
+FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels);
+
+FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = { nullptr };
+
+LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(const std::string& app_name, bool enable_profiler, U32 resample_method)
+	: mInited(false)
+	, mWindGen(nullptr)
+	, mWindDSPDesc(nullptr)
+	, mWindDSP(nullptr)
+	, mSystem(nullptr)
+	, mEnableProfiler(enable_profiler)
+	, mResampleMethod(resample_method)
+	, mAppName(app_name)
+{
+}
+
+LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO()
+{
+}
+
+inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
+{
+	if (result == FMOD_OK)
+		return false;
+	LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
+	return true;
+}
+
+bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata)
+{
+	U32 version;
+	FMOD_RESULT result;
+
+	LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL;
+
+	result = FMOD::System_Create(&mSystem);
+	if (Check_FMOD_Error(result, "FMOD::System_Create"))
+		return false;
+
+	//will call LLAudioEngine_FMODSTUDIO::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 Studio version (" << version
+			<< ")!  You should be using FMOD Studio" << FMOD_VERSION << LL_ENDL;
+	}
+
+	// In this case, all sounds, PLUS wind and stream will be software.
+	result = mSystem->setSoftwareChannels(num_channels + EXTRA_SOUND_CHANNELS);
+	Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels");
+
+	FMOD_ADVANCEDSETTINGS adv_settings = {};
+	adv_settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS);
+	switch (mResampleMethod)
+	{
+	default:
+	case RESAMPLE_LINEAR:
+		adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR;
+		break;
+	case RESAMPLE_CUBIC:
+		adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_CUBIC;
+		break;
+	case RESAMPLE_SPLINE:
+		adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_SPLINE;
+		break;
+	}
+
+	result = mSystem->setAdvancedSettings(&adv_settings);
+	Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings");
+
+	U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE;
+	if (mEnableProfiler)
+	{
+		fmod_flags |= FMOD_INIT_PROFILE_ENABLE;
+	}
+
+#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 ((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK &&
+				(result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, const_cast<char*>(mAppName.c_str()))) == 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 ((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK &&
+				(result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, 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)
+	{
+		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;
+	if (!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput"))
+	{
+		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;
+		default:
+			LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
+		};
+	}
+#else // LL_LINUX
+
+	// initialize the FMOD engine
+	result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, nullptr);
+	if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
+	{
+		/*
+		Ok, the speaker mode selected isn't supported by this soundcard. Switch it
+		back to stereo...
+		*/
+		result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0);
+		Check_FMOD_Error(result, "Error falling back to stereo mode");
+		/*
+		... and re-init.
+		*/
+		result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, nullptr);
+	}
+	if (Check_FMOD_Error(result, "Error initializing FMOD Studio"))
+		return false;
+#endif
+
+	if (mEnableProfiler)
+	{
+		Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup");
+		Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup");
+		Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup");
+		Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup");
+	}
+
+	// set up our favourite FMOD-native streaming audio implementation if none has already been added
+	if (!getStreamingAudioImpl()) // no existing implementation added
+		setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem));
+
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL;
+
+	FMOD_ADVANCEDSETTINGS adv_settings_dump = {};
+	mSystem->getAdvancedSettings(&adv_settings_dump);
+
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): resampler=" << adv_settings.resamplerMethod << " bytes" << LL_ENDL;
+
+	int r_numbuffers, r_samplerate, r_channels;
+	unsigned int r_bufferlength;
+	mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL;
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL;
+
+	char r_name[512];
+	mSystem->getDriverInfo(0, r_name, 511, nullptr, &r_samplerate, nullptr, &r_channels);
+	r_name[511] = '\0';
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL;
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL;
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_channels=" << r_channels << LL_ENDL;
+
+	int latency = 100; // optimistic default - i suspect if sample rate is 0, everything breaks. 
+	if (r_samplerate != 0)
+		latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate);
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL;
+
+	mInited = true;
+
+	LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL;
+
+	return true;
+}
+
+
+std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose)
+{
+	llassert_always(mSystem);
+	if (verbose)
+	{
+		U32 version;
+		if (!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion"))
+		{
+			return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF);
+		}
+	}
+	return "FMOD Studio";
+}
+
+
+void LLAudioEngine_FMODSTUDIO::allocateListener(void)
+{
+	try
+	{
+		mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem);
+	}
+	catch (const std::bad_alloc& e)
+	{
+		LL_WARNS() << "Listener allocation failed due to: " << e.what() << LL_ENDL;
+	}
+
+}
+
+
+void LLAudioEngine_FMODSTUDIO::shutdown()
+{
+	LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL;
+	LLAudioEngine::shutdown();
+
+	LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL;
+	if (mSystem) // speculative fix for MAINT-2657
+	{
+		Check_FMOD_Error(mSystem->close(), "FMOD::System::close");
+		Check_FMOD_Error(mSystem->release(), "FMOD::System::release");
+	}
+	LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL;
+
+	delete mListenerp;
+	mListenerp = nullptr;
+}
+
+
+LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer()
+{
+	return new LLAudioBufferFMODSTUDIO(mSystem);
+}
+
+
+LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel()
+{
+	return new LLAudioChannelFMODSTUDIO(mSystem);
+}
+
+bool LLAudioEngine_FMODSTUDIO::initWind()
+{
+	mNextWindUpdate = 0.0;
+
+	cleanupWind();
+
+	mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
+	memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc));	//Set everything to zero
+	mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
+	strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name));	//Set name to "Wind Unit"
+	mWindDSPDesc->numoutputbuffers = 1;
+	mWindDSPDesc->read = &windDSPCallback; //Assign callback.
+	if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP)
+		return false;
+
+	int frequency = 44100;
+	FMOD_SPEAKERMODE mode;
+	if (!Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat"))
+	{
+		mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
+
+		if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") &&
+			!Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat") &&
+			!Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP"))
+			return true;	//Success
+	}
+
+	cleanupWind();
+	return false;
+}
+
+
+void LLAudioEngine_FMODSTUDIO::cleanupWind()
+{
+	if (mWindDSP)
+	{
+		FMOD::ChannelGroup* mastergroup = nullptr;
+		if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&mastergroup), "FMOD::System::getMasterChannelGroup") && mastergroup)
+			Check_FMOD_Error(mastergroup->removeDSP(mWindDSP), "FMOD::ChannelGroup::removeDSP");
+		Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release");
+		mWindDSP = nullptr;
+	}
+
+	delete mWindDSPDesc;
+	mWindDSPDesc = nullptr;
+
+	delete mWindGen;
+	mWindGen = nullptr;
+}
+
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMODSTUDIO::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_FMODSTUDIO::setInternalGain(F32 gain)
+{
+	if (!mInited)
+	{
+		return;
+	}
+
+	gain = llclamp(gain, 0.0f, 1.0f);
+
+	FMOD::ChannelGroup *master_group;
+	if (Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup"))
+		return;
+
+	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());
+	}
+}
+
+//
+// LLAudioChannelFMODSTUDIO implementation
+//
+
+LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(nullptr), mLastSamplePos(0)
+{
+}
+
+
+LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO()
+{
+	cleanup();
+}
+
+bool LLAudioChannelFMODSTUDIO::updateBuffer()
+{
+	if (mCurrentSourcep)
+	{
+		if (LLAudioChannel::updateBuffer())
+		{
+			// Base class update returned true, which means that we need to actually
+			// set up the channel for a different buffer.
+
+			LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)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.
+				LL_ERRS() << "No FMOD sound!" << LL_ENDL;
+				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(soundp, nullptr, true, &mChannelp);
+				Check_FMOD_Error(result, "FMOD::System::playSound");
+			}
+
+			//LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL;
+		}
+
+		//FMOD_RESULT result;
+
+		mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
+		//Check_FMOD_Error(result, "FMOD::Channel::setVolume");
+
+		mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
+		/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
+		{
+		S32 index;
+		mChannelp->getIndex(&index);
+		LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
+		<< " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL;
+		}*/
+	}
+	else
+	{
+		LL_DEBUGS() << "No source buffer!" << LL_ENDL;
+		return false;
+	}
+
+	return true;
+}
+
+
+void LLAudioChannelFMODSTUDIO::update3DPosition()
+{
+	if (!mChannelp)
+	{
+		// We're not actually a live channel (i.e., we're not playing back anything)
+		return;
+	}
+
+	LLAudioBufferFMODSTUDIO  *bufferp = (LLAudioBufferFMODSTUDIO  *)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 LLAudioChannelFMODSTUDIO::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;
+	Check_FMOD_Error(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES), "FMOD::Channel::getPosition");
+
+	if (cur_pos < (U32)mLastSamplePos)
+	{
+		mLoopedThisFrame = true;
+	}
+	mLastSamplePos = cur_pos;
+}
+
+
+void LLAudioChannelFMODSTUDIO::cleanup()
+{
+	if (!mChannelp)
+	{
+		//LL_INFOS() << "Aborting cleanup with no channel handle." << LL_ENDL;
+		return;
+	}
+
+	//LL_INFOS() << "Cleaning up channel: " << mChannelID << LL_ENDL;
+	Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop");
+
+	mCurrentBufferp = nullptr;
+	mChannelp = nullptr;
+}
+
+
+void LLAudioChannelFMODSTUDIO::play()
+{
+	if (!mChannelp)
+	{
+		LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL;
+		return;
+	}
+
+	Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused");
+
+	getSource()->setPlayedOnce(true);
+
+	if (LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()])
+		Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]), "FMOD::Channel::setChannelGroup");
+}
+
+
+void LLAudioChannelFMODSTUDIO::playSynced(LLAudioChannel *channelp)
+{
+	LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)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 LLAudioChannelFMODSTUDIO::isPlaying()
+{
+	if (!mChannelp)
+	{
+		return false;
+	}
+
+	bool paused, playing;
+	Check_FMOD_Error(mChannelp->getPaused(&paused), "FMOD::Channel::getPaused");
+	Check_FMOD_Error(mChannelp->isPlaying(&playing), "FMOD::Channel::isPlaying");
+	return !paused && playing;
+}
+
+
+//
+// LLAudioChannelFMODSTUDIO implementation
+//
+
+
+LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystemp(system), mSoundp(nullptr)
+{
+}
+
+
+LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO()
+{
+	if (mSoundp)
+	{
+		Check_FMOD_Error(mSoundp->release(), "FMOD::Sound::Release");
+		mSoundp = nullptr;
+	}
+}
+
+
+bool LLAudioBufferFMODSTUDIO::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 (!gDirUtilp->fileExists(filename))
+	{
+		// File not found, abort.
+		return false;
+	}
+
+	if (mSoundp)
+	{
+		// If there's already something loaded in this buffer, clean it up.
+		Check_FMOD_Error(mSoundp->release(), "FMOD::Sound::release");
+		mSoundp = nullptr;
+	}
+
+	FMOD_MODE base_mode = FMOD_LOOP_NORMAL;
+	FMOD_CREATESOUNDEXINFO 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
+	FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp);
+	if (result != FMOD_OK)
+	{
+		// We failed to load the file for some reason.
+		LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL;
+
+		//
+		// 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 LLAudioBufferFMODSTUDIO::getLength()
+{
+	if (!mSoundp)
+	{
+		return 0;
+	}
+
+	U32 length;
+	Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES), "FMOD::Sound::getLength");
+	return length;
+}
+
+
+void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d)
+{
+	FMOD_MODE current_mode;
+	if (Check_FMOD_Error(mChannelp->getMode(&current_mode), "FMOD::Channel::getMode"))
+		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)
+	{
+		Check_FMOD_Error(mChannelp->setMode(new_mode), "FMOD::Channel::setMode");
+	}
+}
+
+// *NOTE:  This is almost certainly being called on the mixer thread,
+// not the main thread.  May have implications for callees or audio
+// engine shutdown.
+
+FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
+{
+	// inbuffer = incomming data.
+	// newbuffer = outgoing data. AKA this DSP's output.
+	// length = length in samples at this mix time. True buffer size, in bytes, would be (length * sizeof(float) * inchannels).
+	// userdata = user-provided data attached this DSP via FMOD::DSP::setUserData.
+
+	LLWindGen<LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT> *windgen;
+	FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
+
+	thisdsp->getUserData((void **)&windgen);
+
+	if (windgen)
+		windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length);
+
+	return FMOD_OK;
+}
\ No newline at end of file
diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b21ed5bab5e2edb0eb5610e22a716896671d8b9
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmodstudio.h
@@ -0,0 +1,138 @@
+/**
+* @file audioengine_fmodstudio.h
+* @brief Definition of LLAudioEngine class abstracting the audio
+* support as a FMOD Studio implementation
+*
+* $LicenseInfo:firstyear=2002&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, 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$
+*/
+
+#ifndef LL_AUDIOENGINE_FMODSTUDIO_H
+#define LL_AUDIOENGINE_FMODSTUDIO_H
+
+#include "llaudioengine.h"
+#include "llwindgen.h"
+
+//Stubs
+class LLAudioStreamManagerFMODSTUDIO;
+namespace FMOD
+{
+	class System;
+	class Channel;
+	class ChannelGroup;
+	class Sound;
+	class DSP;
+}
+typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
+
+//Interfaces
+class LLAudioEngine_FMODSTUDIO : public LLAudioEngine
+{
+public:
+	enum
+	{
+		RESAMPLE_LINEAR = 0,
+		RESAMPLE_CUBIC,
+		RESAMPLE_SPLINE
+	};
+	LLAudioEngine_FMODSTUDIO(const std::string& app_name, bool enable_profiler, U32 resample_method);
+	virtual ~LLAudioEngine_FMODSTUDIO();
+
+	// initialization/startup/shutdown
+	bool init(const S32 num_channels, void *user_data) final override;
+	std::string getDriverName(bool verbose) final override;
+	void allocateListener() final override;
+
+	void shutdown() final override;
+
+	/*virtual*/ bool initWind() final override;
+	/*virtual*/ void cleanupWind() final override;
+
+	/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water) final override;
+
+	typedef F32 MIXBUFFERFORMAT;
+
+	FMOD::System *getSystem()				const { return mSystem; }
+protected:
+	/*virtual*/ LLAudioBuffer *createBuffer() final override; // Get a free buffer, or flush an existing one if you have to.
+	/*virtual*/ LLAudioChannel *createChannel() final override; // Create a new audio channel.
+
+	/*virtual*/ void setInternalGain(F32 gain) final override;
+
+	bool mInited;
+
+	LLWindGen<MIXBUFFERFORMAT> *mWindGen;
+
+	FMOD_DSP_DESCRIPTION *mWindDSPDesc;
+	FMOD::DSP *mWindDSP;
+	FMOD::System *mSystem;
+	bool mEnableProfiler;
+	U32 mResampleMethod;
+	std::string mAppName;
+
+public:
+	static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
+};
+
+
+class LLAudioChannelFMODSTUDIO : public LLAudioChannel
+{
+public:
+	LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
+	virtual ~LLAudioChannelFMODSTUDIO();
+
+protected:
+	/*virtual*/ void play() final override;
+	/*virtual*/ void playSynced(LLAudioChannel *channelp) final override;
+	/*virtual*/ void cleanup() final override;
+	/*virtual*/ bool isPlaying() final override;
+
+	/*virtual*/ bool updateBuffer() final override;
+	/*virtual*/ void update3DPosition() final override;
+	/*virtual*/ void updateLoop() final override;
+
+	void set3DMode(bool use3d);
+protected:
+	FMOD::System *getSystem()	const { return mSystemp; }
+	FMOD::System *mSystemp;
+	FMOD::Channel *mChannelp;
+	S32 mLastSamplePos;
+};
+
+
+class LLAudioBufferFMODSTUDIO : public LLAudioBuffer
+{
+public:
+	LLAudioBufferFMODSTUDIO(FMOD::System *audioengine);
+	virtual ~LLAudioBufferFMODSTUDIO();
+
+	/*virtual*/ bool loadWAV(const std::string& filename) final override;
+	/*virtual*/ U32 getLength() final override;
+	friend class LLAudioChannelFMODSTUDIO;
+protected:
+	FMOD::System *getSystem()	const { return mSystemp; }
+	FMOD::System *mSystemp;
+	FMOD::Sound *getSound()		const{ return mSoundp; }
+	FMOD::Sound *mSoundp;
+};
+
+
+#endif // LL_AUDIOENGINE_FMODSTUDIO_H
\ No newline at end of file
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index e6ac586618e3cb2855e76a3b308c2a6ab181a8c4..92cc94bbd0d0818da24e5a256e9131f73c96295d 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -79,7 +79,7 @@ bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
 	ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
 
 	alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
-	alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
+	alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
 	LL_INFOS() << "ALC version: " << major << "." << minor << LL_ENDL;
 
 	LL_INFOS() << "ALC default device: "
@@ -181,6 +181,8 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
 void LLAudioChannelOpenAL::cleanup()
 {
 	alSourceStop(mALSource);
+	alSourcei(mALSource, AL_BUFFER, AL_NONE);
+
 	mCurrentBufferp = NULL;
 }
 
@@ -320,7 +322,13 @@ void LLAudioBufferOpenAL::cleanup()
 {
 	if(mALBuffer != AL_NONE)
 	{
+		alGetError(); // clear error
 		alDeleteBuffers(1, &mALBuffer);
+		ALenum error = alutGetError();
+		if (ALC_NO_ERROR != error)
+		{
+			LL_WARNS("OpenAL") << "Error: " << alutGetErrorString(error) << " when cleaning up a buffer" << LL_ENDL;
+		}
 		mALBuffer = AL_NONE;
 	}
 }
@@ -437,6 +445,7 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
 	F64 pitch;
 	F64 center_freq;
 	ALenum error;
+	ALuint *buffers = NULL;
 	
 	if (!mEnableWind)
 		return;
@@ -481,57 +490,66 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
 
 	//LL_INFOS() << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers	<<" (" << unprocessed << ":" << processed << ")" << LL_ENDL;
 
-	while(processed--) // unqueue old buffers
+	//delete the old wind buffers
+	buffers = new ALuint[processed];
+	alGetError(); /* clear error */
+	alSourceUnqueueBuffers(mWindSource, processed, &buffers[0]);
+	error = alGetError();
+	if (error != AL_NO_ERROR)
+	{
+		LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << LL_ENDL;
+		}
+	else
 	{
-		ALuint buffer;
-		ALenum error;
-		alGetError(); /* clear error */
-		alSourceUnqueueBuffers(mWindSource, 1, &buffer);
-		error = alGetError();
-		if(error != AL_NO_ERROR)
-		{
-			LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << LL_ENDL;
-		}
-		else
-		{
-			alDeleteBuffers(1, &buffer);
-		}
+		alDeleteBuffers(processed, &buffers[0]);
+	}
+	// We dont need to keep track of the buffers' id now.
+	delete[] buffers;
+	buffers = NULL;
+	
+	//create the buffers for the empty wind buffers
+	unprocessed += mNumEmptyWindALBuffers;
+	buffers = new ALuint[mNumEmptyWindALBuffers];
+	alGetError(); /* clear error */
+	alGenBuffers(mNumEmptyWindALBuffers, &buffers[0]);
+	if ((error = alGetError()) != AL_NO_ERROR)
+	{
+		LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << error << LL_ENDL;
+		//break;
 	}
 
-	unprocessed += mNumEmptyWindALBuffers;
-	while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers
+	//fill the buffers with generated wind.
+	int errors = 0;
+	for (int i = 0; i < mNumEmptyWindALBuffers; i++)
 	{
-		ALuint buffer;
-		alGetError(); /* clear error */
-		alGenBuffers(1,&buffer);
-		if((error=alGetError()) != AL_NO_ERROR)
-		{
-			LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << error << LL_ENDL;
-			break;
-		}
-
-		alBufferData(buffer,
-			     AL_FORMAT_STEREO16,
-			     mWindGen->windGenerate(mWindBuf,
-						    mWindBufSamples),
-			     mWindBufBytes,
-			     mWindBufFreq);
+		alBufferData(buffers[i],
+			AL_FORMAT_STEREO16,
+			mWindGen->windGenerate(mWindBuf,
+			mWindBufSamples),
+			mWindBufBytes,
+			mWindBufFreq);
 		error = alGetError();
 		if(error != AL_NO_ERROR)
 		{
 			LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << LL_ENDL;
+			errors++;
 		}
-		
-		alSourceQueueBuffers(mWindSource, 1, &buffer);
-		error = alGetError();
-		if(error != AL_NO_ERROR)
-		{
-			LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << LL_ENDL;
-		}
-
-		--mNumEmptyWindALBuffers;
 	}
 
+	//queue the buffers
+	alSourceQueueBuffers(mWindSource, mNumEmptyWindALBuffers, &buffers[0]);
+	error = alGetError();
+	if (error != AL_NO_ERROR)
+	{
+		LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << LL_ENDL;
+	}
+	
+	mNumEmptyWindALBuffers = errors;
+	// We dont need to keep track of the buffers' id now.
+	delete[] buffers;
+	buffers = NULL;
+
+	//restart playing if not playing
 	ALint playing;
 	alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
 	if(playing != AL_PLAYING)
diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp
index df2366c8c21dda56892e436cadd8f2e4ee7580f8..37694f89b9fe1a6873ca93dec2aaa337b41897a6 100644
--- a/indra/llaudio/lllistener.cpp
+++ b/indra/llaudio/lllistener.cpp
@@ -28,15 +28,18 @@
 
 #include "lllistener.h"
 
-#define DEFAULT_AT  0.0f,0.0f,-1.0f
-#define DEFAULT_UP  0.0f,1.0f,0.0f
+const LLVector3 DEFAULT_AT(0.0f, 0.0f, -1.0f);
+const LLVector3 DEFAULT_UP(0.0f, 1.0f, 0.0f);
 
 //-----------------------------------------------------------------------
 // constructor
 //-----------------------------------------------------------------------
 LLListener::LLListener()
+	: mPosition(LLVector3::zero),
+	mVelocity(LLVector3::zero),
+	mListenAt(DEFAULT_AT),
+	mListenUp(DEFAULT_UP)
 {
-	init();
 }
 
 //-----------------------------------------------------------------------
@@ -45,22 +48,13 @@ LLListener::~LLListener()
 }
 
 //-----------------------------------------------------------------------
-void LLListener::init(void)
-{
-	mPosition.zeroVec();
-	mListenAt.setVec(DEFAULT_AT);
-	mListenUp.setVec(DEFAULT_UP);
-	mVelocity.zeroVec();
-}
-
-//-----------------------------------------------------------------------
-void LLListener::translate(LLVector3 offset)
+void LLListener::translate(const LLVector3& offset)
 {
 	mPosition += offset;
 }
 
 //-----------------------------------------------------------------------
-void LLListener::setPosition(LLVector3 pos)
+void LLListener::setPosition(const LLVector3& pos)
 {
 	mPosition = pos;
 }
@@ -84,24 +78,21 @@ LLVector3 LLListener::getUp(void)
 }
 
 //-----------------------------------------------------------------------
-void LLListener::setVelocity(LLVector3 vel)
+void LLListener::setVelocity(const LLVector3& vel)
 {
 	mVelocity = vel;
 }
 
 //-----------------------------------------------------------------------
-void LLListener::orient(LLVector3 up, LLVector3 at)
+void LLListener::orient(const LLVector3& up, const LLVector3& at)
 {
 	mListenUp = up;
 	mListenAt = at;
 }
 
 //-----------------------------------------------------------------------
-void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
+void LLListener::set(const LLVector3& pos, const LLVector3& vel, const LLVector3& up, const LLVector3& at)
 {
-	mPosition = pos;
-	mVelocity = vel;
-
 	setPosition(pos);
 	setVelocity(vel);
 	orient(up,at);
diff --git a/indra/llaudio/lllistener.h b/indra/llaudio/lllistener.h
index 41836bf03999cffa1d453a49f5f6619b3f6039ce..b118d7f45910c56f605c17298b0c643d13a69e98 100644
--- a/indra/llaudio/lllistener.h
+++ b/indra/llaudio/lllistener.h
@@ -45,15 +45,14 @@ class LLListener
  public:  
 	LLListener();
 	virtual ~LLListener();
-	virtual void init();  
 
-	virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at);
-
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
-
-	virtual void orient(LLVector3 up, LLVector3 at);
-	virtual void translate(LLVector3 offset);
+	virtual void set(const LLVector3& pos, const LLVector3& vel, const LLVector3& up, const LLVector3& at);
+
+	virtual void setPosition(const LLVector3& pos);
+	virtual void setVelocity(const LLVector3& vel);
+
+	virtual void orient(const LLVector3& up, const LLVector3& at);
+	virtual void translate(const LLVector3& offset);
 
 	virtual void setDopplerFactor(F32 factor);
 	virtual void setRolloffFactor(F32 factor);
diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodex.cpp
deleted file mode 100644
index 31ab47a635f34d93fd1ee3e85676c785affa0e28..0000000000000000000000000000000000000000
--- a/indra/llaudio/lllistener_fmodex.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/** 
- * @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
- * 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 "llaudioengine.h"
-#include "lllistener_fmodex.h"
-#include "fmod.hpp"
-
-//-----------------------------------------------------------------------
-// constructor
-//-----------------------------------------------------------------------
-LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
-{
-	mSystem = system;
-	init();
-}
-
-//-----------------------------------------------------------------------
-LLListener_FMODEX::~LLListener_FMODEX()
-{
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::init(void)
-{
-	// do inherited
-	LLListener::init();
-	mDopplerFactor = 1.0f;
-	mRolloffFactor = 1.0f;
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::translate(LLVector3 offset)
-{
-	LLListener::translate(offset);
-
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::setPosition(LLVector3 pos)
-{
-	LLListener::setPosition(pos);
-
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::setVelocity(LLVector3 vel)
-{
-	LLListener::setVelocity(vel);
-
-	mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)
-{
-	LLListener::orient(up, at);
-
-	// Welcome to the transition between right and left
-	// (coordinate systems, that is)
-	// Leaving the at vector alone results in a L/R reversal
-	// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
-	at = -at;
-
-	mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::commitDeferredChanges()
-{
-	if(!mSystem)
-	{
-		return;
-	}
-
-	mSystem->update();
-}
-
-
-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;
-	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
-}
-
-
-F32 LLListener_FMODEX::getRolloffFactor()
-{
-	return mRolloffFactor;
-}
-
-
-void LLListener_FMODEX::setDopplerFactor(F32 factor)
-{
-	mDopplerFactor = factor;
-	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
-}
-
-
-F32 LLListener_FMODEX::getDopplerFactor()
-{
-	return mDopplerFactor;
-}
-
-
diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodex.h
deleted file mode 100644
index 073b65d53adc5c68f5f486f3e2d3bc68cbdea5b0..0000000000000000000000000000000000000000
--- a/indra/llaudio/lllistener_fmodex.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/** 
- * @file listener_fmodex.h
- * @brief Description of LISTENER class abstracting the audio support
- * as an FMOD 3D implementation (windows and Linux)
- *
- * $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$
- */
-
-#ifndef LL_LISTENER_FMODEX_H
-#define LL_LISTENER_FMODEX_H
-
-#include "lllistener.h"
-
-//Stubs
-namespace FMOD
-{
-	class System;
-}
-
-//Interfaces
-class LLListener_FMODEX : public LLListener
-{
- public:  
-	LLListener_FMODEX(FMOD::System *system);
-	virtual ~LLListener_FMODEX();
-	virtual void init();  
-
-	virtual void translate(LLVector3 offset);
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
-	virtual void orient(LLVector3 up, LLVector3 at);
-	virtual void commitDeferredChanges();
-
-	virtual void setDopplerFactor(F32 factor);
-	virtual F32 getDopplerFactor();
-	virtual void setRolloffFactor(F32 factor);
-	virtual F32 getRolloffFactor();
- protected:
-	 FMOD::System *mSystem;
-	 F32 mDopplerFactor;
-	 F32 mRolloffFactor;
-};
-
-#endif
-
-
diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d7b67c618015299b716558f90810327a2bc1faa
--- /dev/null
+++ b/indra/llaudio/lllistener_fmodstudio.cpp
@@ -0,0 +1,126 @@
+/**
+* @file listener_fmodstudio.cpp
+* @brief Implementation of LISTENER class abstracting the audio
+* support as a FMOD Studio 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 "llaudioengine.h"
+#include "lllistener_fmodstudio.h"
+#include "fmod.hpp"
+
+//-----------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------
+LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
+	: LLListener(),
+	mDopplerFactor(1.0f),
+	mRolloffFactor(1.0f)
+{
+	mSystem = system;
+}
+
+//-----------------------------------------------------------------------
+LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO()
+{
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::translate(const LLVector3& offset)
+{
+	LLListener::translate(offset);
+
+	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::setPosition(const LLVector3& pos)
+{
+	LLListener::setPosition(pos);
+
+	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::setVelocity(const LLVector3& vel)
+{
+	LLListener::setVelocity(vel);
+
+	mSystem->set3DListenerAttributes(0, nullptr, (FMOD_VECTOR*)mVelocity.mV, nullptr, nullptr);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::orient(const LLVector3& up, const LLVector3& at)
+{
+	LLListener::orient(up, at);
+
+	mSystem->set3DListenerAttributes(0, nullptr, nullptr, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::commitDeferredChanges()
+{
+	if (!mSystem)
+	{
+		return;
+	}
+
+	mSystem->update();
+}
+
+
+void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
+{
+	//An internal FMOD Studio 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 fmod studio, which makes it not skip 3D processing next update call.
+	if (mRolloffFactor != factor)
+	{
+		LLVector3 tmp_pos = mPosition - LLVector3(0.f, 0.f, .1f);
+		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)tmp_pos.mV, nullptr, nullptr, nullptr);
+		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
+	}
+	mRolloffFactor = factor;
+	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
+}
+
+
+F32 LLListener_FMODSTUDIO::getRolloffFactor()
+{
+	return mRolloffFactor;
+}
+
+
+void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor)
+{
+	mDopplerFactor = factor;
+	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
+}
+
+
+F32 LLListener_FMODSTUDIO::getDopplerFactor()
+{
+	return mDopplerFactor;
+}
+
diff --git a/indra/llaudio/lllistener_fmodstudio.h b/indra/llaudio/lllistener_fmodstudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..184cfd0ff4c7383c5e43f00b33d6089b5684641e
--- /dev/null
+++ b/indra/llaudio/lllistener_fmodstudio.h
@@ -0,0 +1,63 @@
+/**
+* @file listener_fmodstudio.h
+* @brief Description of LISTENER class abstracting the audio support
+* as an FMOD Studio implementation (windows and Linux)
+*
+* $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$
+*/
+
+#ifndef LL_LISTENER_FMODSTUDIO_H
+#define LL_LISTENER_FMODSTUDIO_H
+
+#include "lllistener.h"
+
+//Stubs
+namespace FMOD
+{
+	class System;
+}
+
+//Interfaces
+class LLListener_FMODSTUDIO : public LLListener
+{
+public:
+	LLListener_FMODSTUDIO(FMOD::System *system);
+	virtual ~LLListener_FMODSTUDIO();
+
+	void translate(const LLVector3& offset) final override;
+	void setPosition(const LLVector3& pos) final override;
+	void setVelocity(const LLVector3& vel) final override;
+	void orient(const LLVector3& up, const LLVector3& at) final override;
+	void commitDeferredChanges() final override;
+
+	void setDopplerFactor(F32 factor) final override;
+	F32 getDopplerFactor() final override;
+	void setRolloffFactor(F32 factor) final override;
+	F32 getRolloffFactor() final override;
+protected:
+	FMOD::System *mSystem;
+	F32 mDopplerFactor;
+	F32 mRolloffFactor;
+};
+
+#endif
+
diff --git a/indra/llaudio/lllistener_openal.cpp b/indra/llaudio/lllistener_openal.cpp
index 9dd4c8685460ccf29603f406405e0a94b8e39b2d..2d5f1aec879f457ce3b06dca78e66bc61b9504ab 100644
--- a/indra/llaudio/lllistener_openal.cpp
+++ b/indra/llaudio/lllistener_openal.cpp
@@ -31,32 +31,33 @@
 #include "lllistener_openal.h"
 
 LLListener_OpenAL::LLListener_OpenAL()
+	: LLListener(),
+	mRolloffFactor(1.f)
 {
-	init();
 }
 
 LLListener_OpenAL::~LLListener_OpenAL()
 {
 }
 
-void LLListener_OpenAL::translate(LLVector3 offset)
+void LLListener_OpenAL::translate(const LLVector3& offset)
 {
 	//LL_INFOS() << "LLListener_OpenAL::translate() : " << offset << LL_ENDL;
 	LLListener::translate(offset);
 }
 
-void LLListener_OpenAL::setPosition(LLVector3 pos)
+void LLListener_OpenAL::setPosition(const LLVector3& pos)
 {
 	//LL_INFOS() << "LLListener_OpenAL::setPosition() : " << pos << LL_ENDL;
 	LLListener::setPosition(pos);
 }
 
-void LLListener_OpenAL::setVelocity(LLVector3 vel)
+void LLListener_OpenAL::setVelocity(const LLVector3& vel)
 {
 	LLListener::setVelocity(vel);
 }
 
-void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
+void LLListener_OpenAL::orient(const LLVector3& up, const LLVector3& at)
 {
 	//LL_INFOS() << "LLListener_OpenAL::orient() up: " << up << " at: " << at << LL_ENDL;
 	LLListener::orient(up, at);
@@ -64,18 +65,20 @@ void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
 
 void LLListener_OpenAL::commitDeferredChanges()
 {
-	ALfloat orientation[6];
-	orientation[0] = mListenAt.mV[0];
-	orientation[1] = mListenAt.mV[1];
-	orientation[2] = mListenAt.mV[2];
-	orientation[3] = mListenUp.mV[0];
-	orientation[4] = mListenUp.mV[1];
-	orientation[5] = mListenUp.mV[2];
-
-	ALfloat velocity[3];
-	velocity[0] = mVelocity.mV[0];
-	velocity[1] = mVelocity.mV[1];
-	velocity[2] = mVelocity.mV[2];
+	ALfloat orientation[] = {
+		mListenAt.mV[0],
+		mListenAt.mV[1],
+		mListenAt.mV[2],
+		mListenUp.mV[0],
+		mListenUp.mV[1],
+		mListenUp.mV[2],
+	};
+
+	ALfloat velocity[3] = {
+		mVelocity.mV[0],
+		mVelocity.mV[1],
+		mVelocity.mV[2],
+	};
 
 	alListenerfv(AL_ORIENTATION, orientation);
 	alListenerfv(AL_POSITION, mPosition.mV);
diff --git a/indra/llaudio/lllistener_openal.h b/indra/llaudio/lllistener_openal.h
index cb163b11a52acc48760878568931c5800cb68da8..d289c6c0795280e2753bbe98566628ae45120207 100644
--- a/indra/llaudio/lllistener_openal.h
+++ b/indra/llaudio/lllistener_openal.h
@@ -39,16 +39,16 @@ class LLListener_OpenAL  : public LLListener
 	LLListener_OpenAL();
 	virtual ~LLListener_OpenAL();
 
-	virtual void translate(LLVector3 offset);
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
-	virtual void orient(LLVector3 up, LLVector3 at);
-	virtual void commitDeferredChanges();
-
-	virtual void setDopplerFactor(F32 factor);
-	virtual F32 getDopplerFactor();
-	virtual void setRolloffFactor(F32 factor);
-	virtual F32 getRolloffFactor();
+	virtual void translate(const LLVector3& offset) override;
+	virtual void setPosition(const LLVector3& pos) override;
+	virtual void setVelocity(const LLVector3& vel) override;
+	virtual void orient(const LLVector3& up, const LLVector3& at) override;
+	virtual void commitDeferredChanges() override;
+
+	virtual void setDopplerFactor(F32 factor) override;
+	virtual F32 getDopplerFactor() override;
+	virtual void setRolloffFactor(F32 factor) override;
+	virtual F32 getRolloffFactor() override;
 
  protected:
 	F32 mRolloffFactor;
diff --git a/indra/llaudio/llstreamingaudio.h b/indra/llaudio/llstreamingaudio.h
index 93479f9d598e2c6e7576e0ffbff3b3873095bd96..d0509a879ff2fc3c51db8f9b36e7b70377825908 100644
--- a/indra/llaudio/llstreamingaudio.h
+++ b/indra/llaudio/llstreamingaudio.h
@@ -1,52 +1,61 @@
-/** 
- * @file streamingaudio.h
- * @author Tofu Linden
- * @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface
- *
- * $LicenseInfo:firstyear=2009&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$
- */
-
-#ifndef LL_STREAMINGAUDIO_H
-#define LL_STREAMINGAUDIO_H
-
-#include "stdtypes.h" // from llcommon
-
-// Entirely abstract.  Based exactly on the historic API.
-class LLStreamingAudioInterface
-{
- public:
-	virtual ~LLStreamingAudioInterface() {}
-
-	virtual void start(const std::string& url) = 0;
-	virtual void stop() = 0;
-	virtual void pause(int pause) = 0;
-	virtual void update() = 0;
-	virtual int isPlaying() = 0;
-	// use a value from 0.0 to 1.0, inclusive
-	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
+/**
+* @file streamingaudio.h
+* @author Tofu Linden
+* @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface
+*
+* $LicenseInfo:firstyear=2009&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$
+*/
+
+#ifndef LL_STREAMINGAUDIO_H
+#define LL_STREAMINGAUDIO_H
+
+#include "stdtypes.h" // from llcommon
+
+class LLSD;
+
+// Entirely abstract.  Based exactly on the historic API.
+class LLStreamingAudioInterface
+{
+public:
+	virtual ~LLStreamingAudioInterface() {}
+
+	virtual void start(const std::string& url) = 0;
+	virtual void stop() = 0;
+	virtual void pause(int pause) = 0;
+	virtual void update() = 0;
+	virtual int isPlaying() = 0;
+	// use a value from 0.0 to 1.0, inclusive
+	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) {}
+
+	virtual bool supportsMetaData() { return false; }
+	virtual const LLSD *getMetaData() { return nullptr; }
+	virtual const bool hasNewMetaData() { return false; }
+	virtual bool supportsWaveData() { return false; }
+	virtual bool getWaveData(float* arr, S32 count, S32 stride = 1){ return false; }
+};
+
+#endif // LL_STREAMINGAUDIO_H
\ No newline at end of file
diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp
deleted file mode 100644
index 9c9e85c00cb6d93a924390a6b7b51633a52cf028..0000000000000000000000000000000000000000
--- a/indra/llaudio/llstreamingaudio_fmodex.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/** 
- * @file streamingaudio_fmodex.cpp
- * @brief LLStreamingAudio_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 "llmath.h"
-
-#include "fmod.hpp"
-#include "fmod_errors.h"
-
-#include "llstreamingaudio_fmodex.h"
-
-
-class LLAudioStreamManagerFMODEX
-{
-public:
-	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; }
-
-	FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
-protected:
-	FMOD::System* mSystem;
-	FMOD::Channel* mStreamChannel;
-	FMOD::Sound* mInternetStream;
-	bool mReady;
-
-	std::string mInternetStreamURL;
-};
-
-
-
-//---------------------------------------------------------------------------
-// Internet Streaming
-//---------------------------------------------------------------------------
-LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
-	mSystem(system),
-	mCurrentInternetStreamp(NULL),
-	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.
-	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 
-	// to prebuffer 40% of that when we first connect, and we want it 
-	// to rebuffer 80% of that whenever we encounter a buffer underrun.
-
-	// Leave the net buffer properties at the default.
-	//FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
-}
-
-
-LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()
-{
-	// nothing interesting/safe to do.
-}
-
-
-void LLStreamingAudio_FMODEX::start(const std::string& url)
-{
-	//if (!mInited)
-	//{
-	//	LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
-	//	return;
-	//}
-
-	// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
-	stop();
-
-	if (!url.empty())
-	{
-		LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
-		mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
-		mURL = url;
-	}
-	else
-	{
-		LL_INFOS() << "Set internet stream to null" << LL_ENDL;
-		mURL.clear();
-	}
-}
-
-
-void LLStreamingAudio_FMODEX::update()
-{
-	// Kill dead internet streams, if possible
-	std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
-	for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
-	{
-		LLAudioStreamManagerFMODEX *streamp = *iter;
-		if (streamp->stopStream())
-		{
-			LL_INFOS() << "Closed dead stream" << LL_ENDL;
-			delete streamp;
-			mDeadStreams.erase(iter++);
-		}
-		else
-		{
-			iter++;
-		}
-	}
-
-	// Don't do anything if there are no streams playing
-	if (!mCurrentInternetStreamp)
-	{
-		return;
-	}
-
-	unsigned int progress;
-	bool starving;
-	bool diskbusy;
-	FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
-
-	if (open_state == FMOD_OPENSTATE_READY)
-	{
-		// Stream is live
-
-		// start the stream if it's ready
-		if (!mFMODInternetStreamChannelp &&
-			(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
-		{
-			// Reset volume to previously set volume
-			setGain(getGain());
-			mFMODInternetStreamChannelp->setPaused(false);
-		}
-	}
-	else if(open_state == FMOD_OPENSTATE_ERROR)
-	{
-		stop();
-		return;
-	}
-
-	if(mFMODInternetStreamChannelp)
-	{
-		FMOD::Sound *sound = NULL;
-
-		if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
-		{
-			FMOD_TAG tag;
-			S32 tagcount, dirtytagcount;
-
-			if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
-			{
-				for(S32 i = 0; i < tagcount; ++i)
-				{
-					if(sound->getTag(NULL, i, &tag)!=FMOD_OK)
-						continue;
-
-					if (tag.type == FMOD_TAGTYPE_FMOD)
-					{
-						if (!strcmp(tag.name, "Sample Rate Change"))
-						{
-							LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
-							mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
-						}
-						continue;
-					}
-				}
-			}
-
-			if(starving)
-			{
-				bool paused = false;
-				mFMODInternetStreamChannelp->getPaused(&paused);
-				if(!paused)
-				{
-					LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
-					LL_INFOS() << "  (diskbusy="<<diskbusy<<")" << LL_ENDL;
-					LL_INFOS() << "  (progress="<<progress<<")" << LL_ENDL;
-					mFMODInternetStreamChannelp->setPaused(true);
-				}
-			}
-			else if(progress > 80)
-			{
-				mFMODInternetStreamChannelp->setPaused(false);
-			}
-		}
-	}
-}
-
-void LLStreamingAudio_FMODEX::stop()
-{
-	if (mFMODInternetStreamChannelp)
-	{
-		mFMODInternetStreamChannelp->setPaused(true);
-		mFMODInternetStreamChannelp->setPriority(0);
-		mFMODInternetStreamChannelp = NULL;
-	}
-
-	if (mCurrentInternetStreamp)
-	{
-		LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
-		if (mCurrentInternetStreamp->stopStream())
-		{
-			delete mCurrentInternetStreamp;
-		}
-		else
-		{
-			LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
-			mDeadStreams.push_back(mCurrentInternetStreamp);
-		}
-		mCurrentInternetStreamp = NULL;
-		//mURL.clear();
-	}
-}
-
-void LLStreamingAudio_FMODEX::pause(int pauseopt)
-{
-	if (pauseopt < 0)
-	{
-		pauseopt = mCurrentInternetStreamp ? 1 : 0;
-	}
-
-	if (pauseopt)
-	{
-		if (mCurrentInternetStreamp)
-		{
-			stop();
-		}
-	}
-	else
-	{
-		start(getURL());
-	}
-}
-
-
-// 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_FMODEX::isPlaying()
-{
-	if (mCurrentInternetStreamp)
-	{
-		return 1; // Active and playing
-	}
-	else if (!mURL.empty())
-	{
-		return 2; // "Paused"
-	}
-	else
-	{
-		return 0;
-	}
-}
-
-
-F32 LLStreamingAudio_FMODEX::getGain()
-{
-	return mGain;
-}
-
-
-std::string LLStreamingAudio_FMODEX::getURL()
-{
-	return mURL;
-}
-
-
-void LLStreamingAudio_FMODEX::setGain(F32 vol)
-{
-	mGain = vol;
-
-	if (mFMODInternetStreamChannelp)
-	{
-		vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here?
-
-		mFMODInternetStreamChannelp->setVolume(vol);
-	}
-}
-
-///////////////////////////////////////////////////////
-// manager of possibly-multiple internet audio streams
-
-LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) :
-	mSystem(system),
-	mStreamChannel(NULL),
-	mInternetStream(NULL),
-	mReady(false)
-{
-	mInternetStreamURL = url;
-
-	FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream);
-
-	if (result!= FMOD_OK)
-	{
-		LL_WARNS() << "Couldn't open fmod stream, error "
-			<< FMOD_ErrorString(result)
-			<< LL_ENDL;
-		mReady = false;
-		return;
-	}
-
-	mReady = true;
-}
-
-FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
-{
-	// We need a live and opened stream before we try and play it.
-	if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
-	{
-		LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
-		return NULL;
-	}
-
-	if(mStreamChannel)
-		return mStreamChannel;	//Already have a channel for this stream.
-
-	mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
-	return mStreamChannel;
-}
-
-bool LLAudioStreamManagerFMODEX::stopStream()
-{
-	if (mInternetStream)
-	{
-
-
-		bool close = true;
-		switch (getOpenState())
-		{
-		case FMOD_OPENSTATE_CONNECTING:
-			close = false;
-			break;
-		default:
-			close = true;
-		}
-
-		if (close)
-		{
-			mInternetStream->release();
-			mStreamChannel = NULL;
-			mInternetStream = NULL;
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-	else
-	{
-		return true;
-	}
-}
-
-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)
-{
-	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_fmodex.h b/indra/llaudio/llstreamingaudio_fmodex.h
deleted file mode 100644
index 2787840ba1a8581bba725f3574c0620fa9c7ea3e..0000000000000000000000000000000000000000
--- a/indra/llaudio/llstreamingaudio_fmodex.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/** 
- * @file streamingaudio_fmodex.h
- * @brief Definition of LLStreamingAudio_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$
- */
-
-#ifndef LL_STREAMINGAUDIO_FMODEX_H
-#define LL_STREAMINGAUDIO_FMODEX_H
-
-#include "stdtypes.h" // from llcommon
-
-#include "llstreamingaudio.h"
-#include "lltimer.h"
-
-//Stubs
-class LLAudioStreamManagerFMODEX;
-namespace FMOD
-{
-	class System;
-	class Channel;
-}
-
-//Interfaces
-class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
-{
- public:
-	LLStreamingAudio_FMODEX(FMOD::System *system);
-	/*virtual*/ ~LLStreamingAudio_FMODEX();
-
-	/*virtual*/ void start(const std::string& url);
-	/*virtual*/ void stop();
-	/*virtual*/ void pause(S32 pause);
-	/*virtual*/ void update();
-	/*virtual*/ S32 isPlaying();
-	/*virtual*/ void setGain(F32 vol);
-	/*virtual*/ F32 getGain();
-	/*virtual*/ std::string getURL();
-
-	/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
-	/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
-private:
-	FMOD::System *mSystem;
-
-	LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
-	FMOD::Channel *mFMODInternetStreamChannelp;
-	std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;
-
-	std::string mURL;
-	F32 mGain;
-};
-
-
-#endif // LL_STREAMINGAUDIO_FMODEX_H
diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f86176b2ca091fbe754ac9dd281c82beab54195
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
@@ -0,0 +1,679 @@
+/**
+* @file streamingaudio_fmodstudio.cpp
+* @brief LLStreamingAudio_FMODSTUDIO 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_fmodstudio.h"
+
+#include "llsd.h"
+#include "llmath.h"
+#include "llmutex.h"
+
+#include "fmod.hpp"
+#include "fmod_errors.h"
+
+inline bool Check_FMOD_Stream_Error(FMOD_RESULT result, const char *string)
+{
+	if (result == FMOD_OK)
+		return false;
+	LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
+	return true;
+}
+
+class LLAudioStreamManagerFMODSTUDIO
+{
+public:
+	LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
+	FMOD::Channel* startStream();
+	bool stopStream(); // Returns true if the stream was successfully stopped.
+
+	const std::string& getURL() 	{ return mInternetStreamURL; }
+
+	FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = nullptr, bool* starving = nullptr, bool* diskbusy = nullptr);
+protected:
+	FMOD::System* mSystem;
+	FMOD::ChannelGroup* mChannelGroup;
+	FMOD::Channel* mStreamChannel;
+	FMOD::Sound* mInternetStream;
+	bool mReady;
+
+	std::string mInternetStreamURL;
+};
+
+//BD - We don't have C++11 yet.
+/*std::recursive_mutex gWaveDataMutex;	//Just to be extra strict.
+const U32 WAVE_BUFFER_SIZE = 1024;
+U32 gWaveBufferMinSize = 0;
+F32 gWaveDataBuffer[WAVE_BUFFER_SIZE] = { 0.f };
+U32 gWaveDataBufferSize = 0;
+
+FMOD_RESULT F_CALLBACK waveDataCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
+{
+	if (!length || !inchannels)
+		return FMOD_OK;
+	memcpy(outbuffer, inbuffer, length * inchannels * sizeof(float));
+
+	static std::vector<F32> local_buf;
+	if (local_buf.size() < length)
+		local_buf.resize(length, 0.f);
+
+	for (U32 i = 0; i < length; ++i)
+	{
+		F32 total = 0.f;
+		for (S32 j = 0; j < inchannels; ++j)
+		{
+			total += inbuffer[i*inchannels + j];
+		}
+		local_buf[i] = total / inchannels;
+	}
+
+	{
+		gWaveDataMutex.lock();
+
+		for (U32 i = length; i > 0; --i)
+		{
+			if (++gWaveDataBufferSize > WAVE_BUFFER_SIZE)
+			{
+				if (gWaveBufferMinSize)
+					memcpy(gWaveDataBuffer + WAVE_BUFFER_SIZE - gWaveBufferMinSize, gWaveDataBuffer, gWaveBufferMinSize * sizeof(float));
+				gWaveDataBufferSize = 1 + gWaveBufferMinSize;
+			}
+			gWaveDataBuffer[WAVE_BUFFER_SIZE - gWaveDataBufferSize] = local_buf[i - 1];
+		}
+		gWaveDataMutex.unlock();
+	}
+
+	return FMOD_OK;
+}*/
+
+//---------------------------------------------------------------------------
+// Internet Streaming
+//---------------------------------------------------------------------------
+LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) :
+mSystem(system),
+mCurrentInternetStreamp(nullptr),
+mStreamDSP(nullptr),
+mStreamGroup(nullptr),
+mFMODInternetStreamChannelp(nullptr),
+mGain(1.0f),
+mMetaData(nullptr),
+mNewMetadata(true)
+{
+	FMOD_RESULT result;
+
+	// Number of milliseconds of audio to buffer for the audio card.
+	// Must be larger than the usual Second Life frame stutter time.
+	const U32 buffer_seconds = 10;		//sec
+	const U32 estimated_bitrate = 128;	//kbit/sec
+	result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
+	Check_FMOD_Stream_Error(result, "FMOD::System::setStreamBufferSize");
+
+	Check_FMOD_Stream_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
+
+	//BD - We don't have C++11 yet.
+	/*FMOD_DSP_DESCRIPTION dspdesc = {};
+	dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
+	strncpy(dspdesc.name, "Waveform", sizeof(dspdesc.name));
+	dspdesc.numoutputbuffers = 1;
+	dspdesc.read = &waveDataCallback; //Assign callback.
+
+	Check_FMOD_Stream_Error(system->createDSP(&dspdesc, &mStreamDSP), "FMOD::System::createDSP");*/
+}
+
+LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
+{
+	stop();
+	for (U32 i = 0; i < 100; ++i)
+	{
+		if (releaseDeadStreams())
+			break;
+		ms_sleep(10);
+	}
+
+	cleanupWaveData();
+}
+
+void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
+{
+	//if (!mInited)
+	//{
+	//	LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
+	//	return;
+	//}
+
+	// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
+	stop();
+
+	if (!url.empty())
+	{
+		if (mDeadStreams.empty())
+		{
+			LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
+			mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
+			mURL = url;
+			mMetaData = new LLSD;
+		}
+		else
+		{
+			LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
+			mPendingURL = url;
+		}
+	}
+	else
+	{
+		LL_INFOS() << "Set internet stream to null" << LL_ENDL;
+		mURL.clear();
+	}
+}
+
+enum utf_endian_type_t
+{
+	UTF16LE,
+	UTF16BE,
+	UTF16
+};
+
+std::string utf16input_to_utf8(unsigned char* input, U32 len, utf_endian_type_t type)
+{
+	if (type == UTF16)
+	{
+		type = UTF16BE;	//Default
+		if (len > 2)
+		{
+			//Parse and strip BOM.
+			if ((input[0] == 0xFE && input[1] == 0xFF) ||
+				(input[0] == 0xFF && input[1] == 0xFE))
+			{
+				input += 2;
+				len -= 2;
+				type = input[0] == 0xFE ? UTF16BE : UTF16LE;
+			}
+		}
+	}
+	llutf16string out_16((llutf16string::value_type*)input, len / 2);
+	if (len % 2)
+	{
+		out_16.push_back((input)[len - 1] << 8);
+	}
+	if (type == UTF16BE)
+	{
+		for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i)
+		{
+			llutf16string::value_type v = *i;
+			*i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
+		}
+	}
+	return utf16str_to_utf8str(out_16);
+}
+
+void LLStreamingAudio_FMODSTUDIO::update()
+{
+	if (!releaseDeadStreams())
+	{
+		llassert_always(mCurrentInternetStreamp == NULL);
+		return;
+	}
+
+	if (!mPendingURL.empty())
+	{
+		llassert_always(mCurrentInternetStreamp == NULL);
+		LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
+		mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL);
+		mURL = mPendingURL;
+		mMetaData = new LLSD;
+		mPendingURL.clear();
+	}
+
+	// Don't do anything if there are no streams playing
+	if (!mCurrentInternetStreamp)
+	{
+		return;
+	}
+
+	unsigned int progress;
+	bool starving;
+	bool diskbusy;
+	FMOD_OPENSTATE open_state;
+	FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
+
+	if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
+	{
+		stop();
+		return;
+	}
+	else if (open_state == FMOD_OPENSTATE_READY)
+	{
+		// Stream is live
+
+		// start the stream if it's ready
+		if (!mFMODInternetStreamChannelp &&
+			(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
+		{
+			// Reset volume to previously set volume
+			setGain(getGain());
+			if (mStreamDSP)
+			{
+				Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->addDSP(FMOD_CHANNELCONTROL_DSP_TAIL, mStreamDSP), "FMOD::Channel::addDSP");
+			}
+			Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
+		}
+	}
+
+
+	if (mFMODInternetStreamChannelp)
+	{
+		if (!mMetaData)
+			mMetaData = new LLSD;
+
+		FMOD::Sound *sound = nullptr;
+
+		if (mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
+		{
+			FMOD_TAG tag;
+			S32 tagcount, dirtytagcount;
+			if (sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
+			{
+				mMetaData->clear();
+				mNewMetadata = true;
+
+				for (S32 i = 0; i < tagcount; ++i)
+				{
+					if (sound->getTag(nullptr, i, &tag) != FMOD_OK)
+						continue;
+
+					std::string name = tag.name;
+					switch (tag.type)	//Crappy tag translate table.
+					{
+					case(FMOD_TAGTYPE_ID3V2) :
+						if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE";
+						else if (name == "TPE1") name = "ARTIST";
+						break;
+					case(FMOD_TAGTYPE_ASF) :
+						if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE";
+						else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST";
+						break;
+					case(FMOD_TAGTYPE_FMOD) :
+						if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change"))
+						{
+							LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
+							Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency");
+						}
+											continue;
+					default:
+						if (!LLStringUtil::compareInsensitive(name, "TITLE") ||
+							!LLStringUtil::compareInsensitive(name, "ARTIST"))
+							LLStringUtil::toUpper(name);
+						break;
+					}
+
+					switch (tag.datatype)
+					{
+					case(FMOD_TAGDATATYPE_INT) :
+						(*mMetaData)[name] = *(LLSD::Integer*)(tag.data);
+						LL_INFOS() << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
+						break;
+					case(FMOD_TAGDATATYPE_FLOAT) :
+						(*mMetaData)[name] = *(LLSD::Real*)(tag.data);
+						LL_INFOS() << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
+						break;
+					case(FMOD_TAGDATATYPE_STRING) :
+					{
+						std::string out = rawstr_to_utf8(std::string((char*)tag.data, tag.datalen));
+						if (out.length() && out[out.size() - 1] == 0)
+							out.erase(out.size() - 1);
+						(*mMetaData)[name] = out;
+						LL_INFOS() << tag.name << "(RAW): " << out << LL_ENDL;
+					}
+												  break;
+					case(FMOD_TAGDATATYPE_STRING_UTF8) :
+					{
+						U8 offs = 0;
+						if (tag.datalen > 3 && ((unsigned char*)tag.data)[0] == 0xEF && ((unsigned char*)tag.data)[1] == 0xBB && ((unsigned char*)tag.data)[2] == 0xBF)
+							offs = 3;
+						std::string out((char*)tag.data + offs, tag.datalen - offs);
+						if (out.length() && out[out.size() - 1] == 0)
+							out.erase(out.size() - 1);
+						(*mMetaData)[name] = out;
+						LL_INFOS() << tag.name << "(UTF8): " << out << LL_ENDL;
+					}
+													   break;
+					case(FMOD_TAGDATATYPE_STRING_UTF16) :
+					{
+						std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16);
+						if (out.length() && out[out.size() - 1] == 0)
+							out.erase(out.size() - 1);
+						(*mMetaData)[name] = out;
+						LL_INFOS() << tag.name << "(UTF16): " << out << LL_ENDL;
+					}
+														break;
+					case(FMOD_TAGDATATYPE_STRING_UTF16BE) :
+					{
+						std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16BE);
+						if (out.length() && out[out.size() - 1] == 0)
+							out.erase(out.size() - 1);
+						(*mMetaData)[name] = out;
+						LL_INFOS() << tag.name << "(UTF16BE): " << out << LL_ENDL;
+					}
+					default:
+						break;
+					}
+				}
+			}
+			static bool was_starved = false;
+			if (starving)
+			{
+				bool paused = false;
+				if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
+				{
+					LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
+					LL_INFOS() << "  (diskbusy=" << diskbusy << ")" << LL_ENDL;
+					LL_INFOS() << "  (progress=" << progress << ")" << LL_ENDL;
+					Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
+				}
+				was_starved = true;
+			}
+			else if (progress > 80 && was_starved)
+			{
+				was_starved = false;
+				Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
+			}
+		}
+	}
+}
+
+void LLStreamingAudio_FMODSTUDIO::stop()
+{
+	mPendingURL.clear();
+
+	if (mMetaData)
+	{
+		delete mMetaData;
+		mMetaData = nullptr;
+	}
+
+	if (mFMODInternetStreamChannelp)
+	{
+		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
+		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
+		if (mStreamDSP)
+		{
+			Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->removeDSP(mStreamDSP), "FMOD::Channel::removeDSP");
+		}
+		mFMODInternetStreamChannelp = nullptr;
+	}
+
+	if (mCurrentInternetStreamp)
+	{
+		LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
+		if (mCurrentInternetStreamp->stopStream())
+		{
+			delete mCurrentInternetStreamp;
+		}
+		else
+		{
+			LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
+			mDeadStreams.push_back(mCurrentInternetStreamp);
+		}
+		mCurrentInternetStreamp = nullptr;
+	}
+}
+
+void LLStreamingAudio_FMODSTUDIO::pause(S32 pauseopt)
+{
+	if (pauseopt < 0)
+	{
+		pauseopt = mCurrentInternetStreamp ? 1 : 0;
+	}
+
+	if (pauseopt)
+	{
+		if (mCurrentInternetStreamp)
+		{
+			stop();
+		}
+	}
+	else
+	{
+		start(getURL());
+	}
+}
+
+
+// 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_FMODSTUDIO::isPlaying()
+{
+	if (mCurrentInternetStreamp)
+	{
+		return 1; // Active and playing
+	}
+	else if (!mURL.empty() || !mPendingURL.empty())
+	{
+		return 2; // "Paused"
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+
+F32 LLStreamingAudio_FMODSTUDIO::getGain()
+{
+	return mGain;
+}
+
+
+std::string LLStreamingAudio_FMODSTUDIO::getURL()
+{
+	return mURL;
+}
+
+
+void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol)
+{
+	mGain = vol;
+
+	if (mFMODInternetStreamChannelp)
+	{
+		vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here?
+
+		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
+	}
+}
+
+const bool LLStreamingAudio_FMODSTUDIO::hasNewMetaData()
+{
+	if (mCurrentInternetStreamp && mNewMetadata)
+	{
+		mNewMetadata = false;
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+//BD - We don't have C++11 yet.
+/* virtual */
+/*bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride)
+{
+	if (count > (WAVE_BUFFER_SIZE / 2))
+		LL_ERRS("AudioImpl") << "Count=" << count << " exceeds WAVE_BUFFER_SIZE/2=" << WAVE_BUFFER_SIZE << LL_ENDL;
+
+	if (!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
+		return false;
+
+	bool muted = false;
+	FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted);
+	if (res != FMOD_OK || muted)
+		return false;
+	{
+		U32 buff_size;
+		{
+			gWaveDataMutex.lock();
+			gWaveBufferMinSize = count;
+			buff_size = gWaveDataBufferSize;
+			if (!buff_size)
+				return false;
+			memcpy(arr, gWaveDataBuffer + WAVE_BUFFER_SIZE - buff_size, llmin(U32(count), buff_size) * sizeof(float));
+			gWaveDataMutex.unlock();
+		}
+		if (buff_size < U32(count))
+			memset(arr + buff_size, 0, (count - buff_size) * sizeof(float));
+	}
+	return true;
+}*/
+
+///////////////////////////////////////////////////////
+// manager of possibly-multiple internet audio streams
+
+LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) :
+mSystem(system),
+mChannelGroup(group),
+mStreamChannel(nullptr),
+mInternetStream(nullptr),
+mReady(false),
+mInternetStreamURL(url)
+{
+	FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, nullptr, &mInternetStream);
+
+	if (result != FMOD_OK)
+	{
+		LL_WARNS() << "Couldn't open fmod stream, error "
+			<< FMOD_ErrorString(result)
+			<< LL_ENDL;
+		mReady = false;
+		return;
+	}
+
+	mReady = true;
+}
+
+FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream()
+{
+	// We need a live and opened stream before we try and play it.
+	FMOD_OPENSTATE open_state;
+	if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
+	{
+		LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
+		return nullptr;
+	}
+
+	if (mStreamChannel)
+		return mStreamChannel;	//Already have a channel for this stream.
+
+	Check_FMOD_Stream_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
+	return mStreamChannel;
+}
+
+bool LLAudioStreamManagerFMODSTUDIO::stopStream()
+{
+	if (mInternetStream)
+	{
+		bool close = true;
+		FMOD_OPENSTATE open_state;
+		if (getOpenState(open_state) == FMOD_OK)
+		{
+			switch (open_state)
+			{
+			case FMOD_OPENSTATE_CONNECTING:
+				close = false;
+				break;
+			default:
+				close = true;
+			}
+		}
+
+		if (close && mInternetStream->release() == FMOD_OK)
+		{
+			mStreamChannel = nullptr;
+			mInternetStream = nullptr;
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	else
+	{
+		return true;
+	}
+}
+
+FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
+{
+	if (!mInternetStream)
+		return FMOD_ERR_INVALID_HANDLE;
+	FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
+	Check_FMOD_Stream_Error(result, "FMOD::Sound::getOpenState");
+	return result;
+}
+
+void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
+{
+	Check_FMOD_Stream_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
+	FMOD_ADVANCEDSETTINGS settings = {};
+	settings.cbSize = sizeof(settings);
+	settings.defaultDecodeBufferSize = decodebuffertime;//ms
+	Check_FMOD_Stream_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
+}
+
+bool LLStreamingAudio_FMODSTUDIO::releaseDeadStreams()
+{
+	// Kill dead internet streams, if possible
+	std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
+	for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
+	{
+		LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
+		if (streamp->stopStream())
+		{
+			LL_INFOS() << "Closed dead stream" << LL_ENDL;
+			delete streamp;
+			mDeadStreams.erase(iter++);
+		}
+		else
+		{
+			++iter;
+		}
+	}
+
+	return mDeadStreams.empty();
+}
+
+void LLStreamingAudio_FMODSTUDIO::cleanupWaveData()
+{
+	if (mStreamGroup)
+	{
+		Check_FMOD_Stream_Error(mStreamGroup->release(), "FMOD::ChannelGroup::release");
+		mStreamGroup = nullptr;
+	}
+
+	if (mStreamDSP)
+		Check_FMOD_Stream_Error(mStreamDSP->release(), "FMOD::DSP::release");
+	mStreamDSP = nullptr;
+}
\ No newline at end of file
diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..d96d55746338a20e71186e06f36abe528045e915
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.h
@@ -0,0 +1,91 @@
+/**
+* @file streamingaudio_fmodstudio.h
+* @brief Definition of LLStreamingAudio_FMODSTUDIO 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$
+*/
+
+#ifndef LL_STREAMINGAUDIO_FMODSTUDIO_H
+#define LL_STREAMINGAUDIO_FMODSTUDIO_H
+
+#include "stdtypes.h" // from llcommon
+
+#include "llstreamingaudio.h"
+#include "lltimer.h"
+
+//Stubs
+class LLAudioStreamManagerFMODSTUDIO;
+namespace FMOD
+{
+	class System;
+	class Channel;
+	class ChannelGroup;
+	class DSP;
+}
+
+//Interfaces
+class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface
+{
+public:
+	LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
+	/*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
+
+	/*virtual*/ void start(const std::string& url) final override;
+	/*virtual*/ void stop() final override;
+	/*virtual*/ void pause(S32 pause) final override;
+	/*virtual*/ void update() final override;
+	/*virtual*/ S32 isPlaying() final override;
+	/*virtual*/ void setGain(F32 vol) final override;
+	/*virtual*/ F32 getGain() final override;
+	/*virtual*/ std::string getURL() final override;
+
+	/*virtual*/ bool supportsAdjustableBufferSizes() final override { return true; }
+	/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime) final override;
+
+	/*virtual*/ bool supportsMetaData() final override { return true; }
+	/*virtual*/ const LLSD *getMetaData() final override { return mMetaData; }	//return NULL if not playing.
+	/*virtual*/ const bool hasNewMetaData() final override;
+	/*virtual*/ bool supportsWaveData() final override { return true; }
+	//BD - We don't have C++11 yet.
+	/*virtual*/// bool getWaveData(float* arr, S32 count, S32 stride = 1) final override;
+private:
+	bool releaseDeadStreams();
+	void cleanupWaveData();
+
+	FMOD::System *mSystem;
+
+	LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
+	FMOD::DSP* mStreamDSP;
+	FMOD::ChannelGroup* mStreamGroup;
+	FMOD::Channel *mFMODInternetStreamChannelp;
+	std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams;
+
+	std::string mURL;
+	std::string mPendingURL;
+	F32 mGain;
+
+	LLSD *mMetaData;
+	bool mNewMetadata;
+};
+
+
+#endif // LL_STREAMINGAUDIO_FMODSTUDIO_H
\ No newline at end of file
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3d54e81d52ec90292a23a2afb5658b23a5bf07cf..05742c7d4dc92eded87e0177ed677b925320d8c5 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -11,7 +11,7 @@ include(DBusGlib)
 include(DirectX)
 include(DragDrop)
 include(EXPAT)
-include(FMODEX)
+include(FMODSTUDIO)
 include(GLOD)
 include(Hunspell)
 include(JsonCpp)
@@ -59,9 +59,9 @@ if (NOT HAVOK_TPV)
    add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions)
 endif (NOT HAVOK_TPV)
 
-if(FMODEX)
-  include_directories(${FMODEX_INCLUDE_DIR})
-endif(FMODEX)
+if(FMODSTUDIO)
+  include_directories(${FMODSTUDIO_INCLUDE_DIR})
+endif(FMODSTUDIO)
 
 include_directories(
     ${DBUSGLIB_INCLUDE_DIRS}
@@ -1711,15 +1711,15 @@ if (WINDOWS)
 endif (WINDOWS)
 
 if (OPENAL)
-  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")
+  list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_OPENAL=1")
 endif (OPENAL)
 
-if (FMODEX)
-  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX")
-  set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY})
-endif (FMODEX)
+if (FMODSTUDIO)
+  list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_FMODSTUDIO=1")
+  set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY})
+endif (FMODSTUDIO)
 
-set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
+set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_DEFINITIONS "${LLSTARTUP_COMPILE_DEFINITIONS}")
 
 list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
 
@@ -1829,13 +1829,21 @@ if (WINDOWS)
             )
     endif (ADDRESS_SIZE EQUAL 64)
 
-    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)
+    if (FMODSTUDIO)
+      if (ADDRESS_SIZE EQUAL 32)
+        list(APPEND COPY_INPUT_DEPENDENCIES
+             ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
+             ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
+             ${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll
+            )
+      elseif (ADDRESS_SIZE EQUAL 64)
+        list(APPEND COPY_INPUT_DEPENDENCIES
+             ${SHARED_LIB_STAGING_DIR}/Release/fmod64.dll
+             ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod64.dll
+             ${SHARED_LIB_STAGING_DIR}/Debug/fmodL64.dll
+            )
+      endif (ADDRESS_SIZE EQUAL 32)
+    endif (FMODSTUDIO)
     
     add_custom_command(
       OUTPUT  ${CMAKE_CFG_INTDIR}/copy_touched.bat
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 5cd55bf62442c18281c5f769f56aa93d4812ede7..4bb0df2ee18788239d3cead8a1a1045848130ce5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16296,7 +16296,7 @@
     <key>Value</key>
     <real>1.0</real>
   </map>
-  <key>FMODExProfilerEnable</key>
+  <key>FMODProfilerEnable</key>
   <map>
     <key>Comment</key>
     <string>Enable profiler tool if using FMOD Ex</string>
@@ -16307,7 +16307,7 @@
     <key>Value</key>
     <integer>0</integer>
     </map>
-  <key>FMODExDecodeBufferSize</key>
+  <key>FMODDecodeBufferSize</key>
   <map>
     <key>Comment</key>
     <string>Sets the streaming decode buffer size (in milliseconds)</string>
@@ -16318,7 +16318,18 @@
     <key>Value</key>
     <integer>1000</integer>
     </map>
-  <key>FMODExStreamBufferSize</key>
+  <key>FMODResampleMethod</key>
+  <map>
+    <key>Comment</key>
+    <string>Sets the method used for internal resampler 0(Linear), 1(Cubic), 2(Spline)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>FMODStreamBufferSize</key>
   <map>
     <key>Comment</key>
     <string>Sets the streaming buffer size (in milliseconds)</string>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e6200b22a7292389b0d853c99af8113ebaa2abde..01e7f51fe9fa54431b21a5fec7a555c2d023dd55 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1794,13 +1794,6 @@ bool LLAppViewer::cleanup()
 
 	if (gAudiop)
 	{
-        // be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.
-        gAudiop->stopInternetStream();
-        // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
-        LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
-		delete sai;
-		gAudiop->setStreamingAudioImpl(NULL);
-
         // shut down the audio subsystem
         gAudiop->shutdown();
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4a69c9460f4627f602a975c3f9c9112dd32749fa..2f62d0177ef1b188aa718d357798373f3169bdc8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -39,8 +39,8 @@
 #include "llviewermedia_streamingaudio.h"
 #include "llaudioengine.h"
 
-#ifdef LL_FMODEX
-# include "llaudioengine_fmodex.h"
+#ifdef LL_FMODSTUDIO
+#include "llaudioengine_fmodstudio.h"
 #endif
 
 #ifdef LL_OPENAL
@@ -621,21 +621,25 @@ bool idle_startup()
 		if (FALSE == gSavedSettings.getBOOL("NoAudio"))
 		{
 			delete gAudiop;
-			gAudiop = NULL;
-
-#ifdef LL_FMODEX		
+			gAudiop = nullptr;
+
+#ifdef LL_FMODSTUDIO
+			if (!gAudiop
 #if !LL_WINDOWS
-			if (NULL == getenv("LL_BAD_FMODEX_DRIVER"))
+				&& NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER")
 #endif // !LL_WINDOWS
+				)
 			{
-				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable"));
+				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(LLAppViewer::instance()->getSecondLifeTitle(), gSavedSettings.getBOOL("FMODProfilerEnable"), gSavedSettings.getU32("FMODResampleMethod"));
 			}
 #endif
 
 #ifdef LL_OPENAL
+			if (!gAudiop
 #if !LL_WINDOWS
-			if (NULL == getenv("LL_BAD_OPENAL_DRIVER"))
+				&& NULL == getenv("LL_BAD_OPENAL_DRIVER")
 #endif // !LL_WINDOWS
+				)
 			{
 				gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
 			}
@@ -644,7 +648,7 @@ bool idle_startup()
 			if (gAudiop)
 			{
 #if LL_WINDOWS
-				// FMOD Ex on Windows needs the window handle to stop playing audio
+				// FMOD Studio on Windows needs the window handle to stop playing audio
 				// when window is minimized. JC
 				void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
 #else
@@ -659,13 +663,13 @@ bool idle_startup()
 				{
 					LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL;
 					delete gAudiop;
-					gAudiop = NULL;
+					gAudiop = nullptr;
 				}
 
 				if (gAudiop)
 				{
 					// if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins
-					if (NULL == gAudiop->getStreamingAudioImpl())
+					if (!gAudiop->getStreamingAudioImpl())
 					{
 						LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL;
 						gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins());
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 398d3b65843ba0bc3dfc53bb6aa573a1b31cc039..f1b760885043dabe5969e8143970ac7df4304597 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -113,7 +113,7 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)
 
 			LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
 			if(stream && stream->supportsAdjustableBufferSizes())
-				stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+				stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"), gSavedSettings.getU32("FMODDecodeBufferSize"));
 
 			gAudiop->startInternetStream(mNextStreamURI);
 			startFading();
@@ -178,7 +178,7 @@ bool LLViewerAudio::onIdleUpdate()
 				{
 					LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
 					if(stream && stream->supportsAdjustableBufferSizes())
-						stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+						stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"), gSavedSettings.getU32("FMODDecodeBufferSize"));
 
 					gAudiop->startInternetStream(mNextStreamURI);
 				}
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 1b9ddabbb48c7efaea30f1a1b75c992414b7cd14..097e40946dde3e8bd443f5df6445058468b0c07a 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -77,6 +77,7 @@ Much thanks to all Patrons who pledged money via Patreon to support this Viewer'
 The following list contains all Patrons who pledged at any point at least the minimum amount possible.
 
 Akritos Rain (10$)
+Alina (5$)
 AwpGoose / Harriet (5$)
 Baphy (1$)
 Ben F Noviello (1$)
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index f7bdfbb90ca4efda993e023eb8bce84f59e8a2d8..97a05b63a17eb7d601d5a0dd3f1c9ea8241f09a9 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -182,6 +182,9 @@ width="996">
      bg_writeable_color="Black_50" 
      width="990"
      word_wrap="false">
+Changed: Reworked Camera Offset system to not require the preset to be loaded to be edited.
+Changed: Tooltip for Object Cache and added a warning that disabling this option will have negative effects.
+Changed: Version to 3.4.3.
 Fixed: Mouselook offset not working anymore.
 Fixed: Top View preset not properly disabling the "Delete" button.
 Fixed: Preset list not refreshing after deleting a preset.
@@ -189,9 +192,6 @@ Fixed: Camera Preset combobox not showing the currently selected preset when ope
 Fixed: XUI warning about missing Conversation Log Combo, it's a radiobutton now.
 Fixed: Land edit tools selecting the wrong tool.
 Fixed: Land Edit tool selection not selecting "Select Land" as default.
-Changed: Reworked Camera Offset system to not require the preset to be loaded to be edited.
-Changed: Tooltip for Object Cache and added a warning that disabling this option will have negative effects.
-Changed: Version to 3.4.3.
 Misc: Elimiated more unnecessary getChild calls in Preferences.
      </text>
      <view_border
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 85ecba91a211e816249377ec5291df36d472bf1e..1b3c64323976e0e354283241802d2a91c7de9480 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1142,12 +1142,12 @@ def path_optional(src, dst):
                         # dylibs that vary based on configuration
                         if self.args['configuration'].lower() == 'debug':
                             for libfile in (
-                                        "libfmodexL.dylib",
+                                        "libfmodL.dylib",
                                         ):
                                 dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile)
                         else:
                             for libfile in (
-                                        "libfmodex.dylib",
+                                        "libfmod.dylib",
                                         ):
                                 dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)