diff --git a/autobuild.xml b/autobuild.xml
index d75b007d0e660a6ff6dcb79725d38f590cc8e180..a8967e56099cfbca7b5a0bd61571cbf7c177d1ab 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -729,16 +729,18 @@
         <key>version</key>
         <string>2.1.1.500375</string>
       </map>
-      <key>fmodex</key>
+      <key>fmodstudio</key>
       <map>
         <key>copyright</key>
-        <string>COPYRIGHT 2014 FIRELIGHT TECHNOLOGIES PTY LTD. ALL RIGHTS RESERVED</string>
+        <string>FMOD Studio, Copyright (c) Firelight Technologies Pty Ltd.</string>
+        <key>description</key>
+        <string>FMOD Studio audio system library</string>
         <key>license</key>
-        <string>fmodex</string>
+        <string>fmodstudio</string>
         <key>license_file</key>
-        <string>LICENSES/fmodex.txt</string>
+        <string>LICENSES/fmodstudio.txt</string>
         <key>name</key>
-        <string>fmodex</string>
+        <string>fmodstudio</string>
         <key>platforms</key>
         <map>
           <key>darwin</key>
@@ -746,45 +748,25 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ed0d8767652aecd65a7fef3e28645bad</string>
+              <string>21610bcca4e2ff76b6483c1faae8b152</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/fmodex_3p-update-fmodex/rev/297261/arch/Darwin/installer/fmodex-4.44.31.297261-darwin-297261.tar.bz2</string>
+              <string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/darwin/fmodstudio-2.00.07.4-darwin-4.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
           </map>
-          <key>darwin64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>cba1feed7f6bb671d791a517fddf205a</string>
-              <key>url</key>
-              <string>https://downloads.catznip.com/packages/fmodex-44461-darwin-201601300040-r23.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>darwin64</string>
-          </map>
-          <key>linux</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>b847ec838da1ad1dd646df9d74e9b395</string>
-              <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-fmodex/rev/314207/arch/Linux/installer/fmodex-4.44.61.314207-linux-314207.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>linux</string>
-          </map>
           <key>linux64</key>
           <map>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>89a75d8719f7b2cbe1e54cd8407bb992</string>
+              <string>54dbd41322a08a1fc333ca6d96af5502</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1544/3476/fmodex-4.44.64.501533-linux64-501533.tar.bz2</string>
+              <string>https://depot.alchemyviewer.org/pub/linux64/lib/fmodstudio-1.10.00-linux64-201709282320.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -794,9 +776,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>2038da4ab71da8dc086738007c0acdd3</string>
+              <string>d32efb193ffcd73bcba4875ddfd17bf0</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
               <key>url</key>
-              <string>http://viewer.catznip.com/downloads/packages/fmodex-4.44.61-windows-171261212.tar.bz2</string>
+              <string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows/fmodstudio-2.00.07.4-windows-4.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -806,16 +790,18 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b4b73cd64bfd72e7ae84aad429d69cf6</string>
+              <string>0604fd6b53ceaf14ce04d0de1bea51b8</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
               <key>url</key>
-              <string>http://viewer.catznip.com/downloads/packages/fmodex-4.44.61-windows64-171261211.tar.bz2</string>
+              <string>file:///c:/bld/fmodstudio-2.00.07.4-windows64-4.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>4.44.64.501533</string>
+        <string>2.00.07.4</string>
       </map>
       <key>fontconfig</key>
       <map>
@@ -1748,9 +1734,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>da3b1ea90797b189d80ab5d50fdf05d4</string>
+              <string>6bb48e878e7f4e7b6630a6f3a5fd2f89</string>
+              <key>hash_algorithm</key>
+              <string>md5</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15260/98469/kdu-7.10.4.513518-windows64-513518.tar.bz2</string>
+              <string>file:///c:/bld/kdu-7.10.4.200681608-windows64-200681608.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
@@ -2706,9 +2694,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>545954e46a316e469f6b68ecbcb76573</string>
+              <string>8a7f0be5647e07235d205ac00805fb78</string>
               <key>url</key>
-              <string>http://viewer.catznip.com/downloads/packages/openjpeg-1.5.2.171271050-windows-171271050.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1116/2586/openjpeg-1.5.1.501102-windows-501102.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -2718,9 +2706,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a68103651741c8b66356153ee5668d6b</string>
+              <string>398544058036bc27097fcff208934d11</string>
               <key>url</key>
-              <string>http://viewer.catznip.com/downloads/packages/openjpeg-1.5.2.171271046-windows64-171271046.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1115/2581/openjpeg-1.5.1.501102-windows64-501102.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 7864271c02847fef2b75bf76a9ad1d14fcb08c56..3e7b48e6bf73428262a7a7f73ecd9ea85f7d21eb 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 c73a1fdb47b3e78f5de6bfe751d0d76a8b73eb06..da5143631a0724a3430953e4ae73683be380d970 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -62,14 +62,10 @@ if(WINDOWS)
       endif(ADDRESS_SIZE EQUAL 32)
     endif (BUGSPLAT_DB)
 
-    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 (USE_FMODSTUDIO)
+      list(APPEND debug_files fmodL.dll)
+      list(APPEND release_files fmod.dll)
+    endif (USE_FMODSTUDIO)
 
     #*******************************
     # Copy MS C runtime dlls, required for packaging.
@@ -192,10 +188,10 @@ 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 (USE_FMODSTUDIO)
+      list(APPEND debug_files libfmodL.dylib)
+      list(APPEND release_files libfmod.dylib)
+    endif (USE_FMODSTUDIO)
 
 elseif(LINUX)
     # linux is weird, multiple side by side configurations aren't supported
@@ -242,10 +238,10 @@ 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_FMODSTUDIO)
+      list(APPEND debug_files "libfmodL.so")
+      list(APPEND release_files "libfmod.so")
+    endif (USE_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 69d6dd5f6d6a8b77cd4dc11f89f30f366b5f56c6..0000000000000000000000000000000000000000
--- a/indra/cmake/FMODEX.cmake
+++ /dev/null
@@ -1,52 +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)
-        if (ADDRESS_SIZE EQUAL 32)
-            set(FMODEX_LIBRARY
-                debug fmodexL_vc
-                optimized fmodex_vc)
-        else (ADDRESS_SIZE EQUAL 64)
-            set(FMODEX_LIBRARY
-                debug fmodexL64_vc
-                optimized fmodex64_vc)
-        endif (ADDRESS_SIZE EQUAL 32)
-      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..c067ea3fee3fc45ba537d42d6030fb53ab9ad338
--- /dev/null
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+# FMOD can be set when launching the make using the argument -DUSE_FMODSTUDIO: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(USE_FMODSTUDIO ON)
+endif (INSTALL_PROPRIETARY)
+
+if (USE_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)
+        set(FMODSTUDIO_LIBRARY 
+            debug fmodL_vc
+            optimized fmod_vc)
+      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 (USE_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..4562b0ae450aeb2b27ad3905ead1a46ecb5c313b
--- /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
+  )
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index e943dd5d5ccd059100c1ad41507a3f5d377b73d1..77f023f71e7c9d8c1581d8e6e33af43229fc0b47 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 (USE_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 (USE_FMODSTUDIO)
 
 if (OPENAL)
   list(APPEND llaudio_SOURCE_FILES
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index f49028aad51955fbc5a606cda3ebcf9f2985e43e..493a0744652c3792c70b32261ae132d0fcd18497 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,11 +134,15 @@ void LLAudioEngine::shutdown()
 {
 	// Clean up decode manager
 	delete gAudioDecodeMgrp;
-	gAudioDecodeMgrp = NULL;
+	gAudioDecodeMgrp = nullptr;
 
 	// Clean up wind source
 	cleanupWind();
 
+	// Clean up streaming audio
+	delete mStreamingAudioImpl;
+	mStreamingAudioImpl = nullptr;
+
 	// Clean up audio sources
 	source_map::iterator iter_src;
 	for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
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_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2c1a29c4d0a00d324003dbbb0caf958ce5b0d8bb
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -0,0 +1,744 @@
+/** 
+ * @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 <utility>
+#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(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(std::move(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;
+}
diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodstudio.h
similarity index 51%
rename from indra/llaudio/llaudioengine_fmodex.h
rename to indra/llaudio/llaudioengine_fmodstudio.h
index ca389d489fd981359e666ae50b250668a7489c90..16e287cd92db3f7bbe634802ba44d9b4d8ac894c 100644
--- a/indra/llaudio/llaudioengine_fmodex.h
+++ b/indra/llaudio/llaudioengine_fmodstudio.h
@@ -1,7 +1,7 @@
 /** 
- * @file audioengine_fmodex.h
+ * @file audioengine_fmodstudio.h
  * @brief Definition of LLAudioEngine class abstracting the audio 
- * support as a FMODEX implementation
+ * support as a FMOD Studio implementation
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -25,14 +25,14 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_AUDIOENGINE_FMODEX_H
-#define LL_AUDIOENGINE_FMODEX_H
+#ifndef LL_AUDIOENGINE_FMODSTUDIO_H
+#define LL_AUDIOENGINE_FMODSTUDIO_H
 
 #include "llaudioengine.h"
 #include "llwindgen.h"
 
 //Stubs
-class LLAudioStreamManagerFMODEX;
+class LLAudioStreamManagerFMODSTUDIO;
 namespace FMOD
 {
 	class System;
@@ -44,32 +44,38 @@ namespace FMOD
 typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
 
 //Interfaces
-class LLAudioEngine_FMODEX : public LLAudioEngine 
+class LLAudioEngine_FMODSTUDIO final : public LLAudioEngine 
 {
 public:
-	LLAudioEngine_FMODEX(bool enable_profiler);
-	virtual ~LLAudioEngine_FMODEX();
+	enum
+	{
+		RESAMPLE_LINEAR=0,
+		RESAMPLE_CUBIC,
+		RESAMPLE_SPLINE
+	};
+	LLAudioEngine_FMODSTUDIO(std::string app_name, bool enable_profiler, U32 resample_method);
+	virtual ~LLAudioEngine_FMODSTUDIO();
 
 	// initialization/startup/shutdown
-	virtual bool init(const S32 num_channels, void *user_data);
-	virtual std::string getDriverName(bool verbose);
-	virtual void allocateListener();
+	bool init(const S32 num_channels, void *user_data) final override;
+	std::string getDriverName(bool verbose) final override;
+	void allocateListener() final override;
 
-	virtual void shutdown();
+	void shutdown() final override;
 
-	/*virtual*/ bool initWind();
-	/*virtual*/ void cleanupWind();
+	/*virtual*/ bool initWind() final override;
+	/*virtual*/ void cleanupWind() final override;
 
-	/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
+	/*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(); // Get a free buffer, or flush an existing one if you have to.
-	/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
+	/*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);
+	/*virtual*/ void setInternalGain(F32 gain) final override;
 
 	bool mInited;
 
@@ -79,27 +85,29 @@ class LLAudioEngine_FMODEX : public LLAudioEngine
 	FMOD::DSP *mWindDSP;
 	FMOD::System *mSystem;
 	bool mEnableProfiler;
+	U32 mResampleMethod;
+	std::string mAppName;
 
 public:
 	static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
 };
 
 
-class LLAudioChannelFMODEX : public LLAudioChannel
+class LLAudioChannelFMODSTUDIO final : public LLAudioChannel
 {
 public:
-	LLAudioChannelFMODEX(FMOD::System *audioengine);
-	virtual ~LLAudioChannelFMODEX();
+	LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
+	virtual ~LLAudioChannelFMODSTUDIO();
 
 protected:
-	/*virtual*/ void play();
-	/*virtual*/ void playSynced(LLAudioChannel *channelp);
-	/*virtual*/ void cleanup();
-	/*virtual*/ bool isPlaying();
+	/*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();
-	/*virtual*/ void update3DPosition();
-	/*virtual*/ void updateLoop();
+	/*virtual*/ bool updateBuffer() final override;
+	/*virtual*/ void update3DPosition() final override;
+	/*virtual*/ void updateLoop() final override;
 
 	void set3DMode(bool use3d);
 protected:
@@ -110,15 +118,15 @@ class LLAudioChannelFMODEX : public LLAudioChannel
 };
 
 
-class LLAudioBufferFMODEX : public LLAudioBuffer
+class LLAudioBufferFMODSTUDIO final : public LLAudioBuffer
 {
 public:
-	LLAudioBufferFMODEX(FMOD::System *audioengine);
-	virtual ~LLAudioBufferFMODEX();
+	LLAudioBufferFMODSTUDIO(FMOD::System *audioengine);
+	virtual ~LLAudioBufferFMODSTUDIO();
 
-	/*virtual*/ bool loadWAV(const std::string& filename);
-	/*virtual*/ U32 getLength();
-	friend class LLAudioChannelFMODEX;
+	/*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;
@@ -127,4 +135,4 @@ class LLAudioBufferFMODEX : public LLAudioBuffer
 };
 
 
-#endif // LL_AUDIOENGINE_FMODEX_H
+#endif // LL_AUDIOENGINE_FMODSTUDIO_H
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index e6ac586618e3cb2855e76a3b308c2a6ab181a8c4..40600f9be0a9d34eaeefbbce8f5ff20c00fa7f1f 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -46,11 +46,6 @@ LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
 {
 }
 
-// virtual
-LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
-{
-}
-
 // virtual
 bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
 {
diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h
index 6639d9dfe648772a5b718c552284765463cffbcf..32b652ffe1be9c9e434363f44355d15796b563b8 100644
--- a/indra/llaudio/llaudioengine_openal.h
+++ b/indra/llaudio/llaudioengine_openal.h
@@ -38,7 +38,7 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
 {
 	public:
 		LLAudioEngine_OpenAL();
-		virtual ~LLAudioEngine_OpenAL();
+		virtual ~LLAudioEngine_OpenAL() = default;
 
 		virtual bool init(const S32 num_channels, void *user_data);
         	virtual std::string getDriverName(bool verbose);
diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp
index df2366c8c21dda56892e436cadd8f2e4ee7580f8..08e58111d0db59b21fd57059c55a79b5f7171591 100644
--- a/indra/llaudio/lllistener.cpp
+++ b/indra/llaudio/lllistener.cpp
@@ -35,32 +35,21 @@
 // constructor
 //-----------------------------------------------------------------------
 LLListener::LLListener()
+	: mPosition(LLVector3::zero),
+      mVelocity(LLVector3::zero),
+	  mListenAt(DEFAULT_AT),
+	  mListenUp(DEFAULT_UP)
 {
-	init();
 }
 
 //-----------------------------------------------------------------------
-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 +73,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..806ac9c4356eeb590109eca2dd285c71b639a3f8 100644
--- a/indra/llaudio/lllistener.h
+++ b/indra/llaudio/lllistener.h
@@ -44,16 +44,15 @@ class LLListener
  protected:
  public:  
 	LLListener();
-	virtual ~LLListener();
-	virtual void init();  
+	virtual ~LLListener() = default; 
 
-	virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at);
+	virtual void set(const LLVector3& pos, const LLVector3& vel, const LLVector3& up, const LLVector3& at);
 
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
+	virtual void setPosition(const LLVector3& pos);
+	virtual void setVelocity(const LLVector3& vel);
 
-	virtual void orient(LLVector3 up, LLVector3 at);
-	virtual void translate(LLVector3 offset);
+	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_ds3d.h b/indra/llaudio/lllistener_ds3d.h
deleted file mode 100644
index 9150ccd5b929a9f48c6b27467120df18ffd29e66..0000000000000000000000000000000000000000
--- a/indra/llaudio/lllistener_ds3d.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/** 
- * @file listener_ds3d.h
- * @brief Description of LISTENER class abstracting the audio support
- * as a DirectSound 3D implementation (windows only)
- *
- * $LicenseInfo:firstyear=2000&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_DS3D_H
-#define LL_LISTENER_DS3D_H
-
-#include "lllistener.h"
-
-#include <dmusici.h>
-#include <dsound.h>
-#include <ks.h>
-
-class LLListener_DS3D : public LLListener
-{
- private:
- protected:
-	IDirectSound3DListener8 *m3DListener;
- public:
-
- private:
- protected:
- public:  
-	LLListener_DS3D();
-	virtual ~LLListener_DS3D();
-	virtual void init();  
-
-	virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p);
-
-	virtual void translate(LLVector3 offset);
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
-	virtual void orient(LLVector3 up, LLVector3 at);
-
-	virtual void setDopplerFactor(F32 factor);
-	virtual F32 getDopplerFactor();
-	virtual void setRolloffFactor(F32 factor);
-	virtual F32 getRolloffFactor();
-
-	virtual void commitDeferredChanges();
-};
-
-#endif
-
-
diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodstudio.cpp
similarity index 56%
rename from indra/llaudio/lllistener_fmodex.cpp
rename to indra/llaudio/lllistener_fmodstudio.cpp
index 31ab47a635f34d93fd1ee3e85676c785affa0e28..3a9fb8f157e34cf4bfa75223c2643601e51bca3a 100644
--- a/indra/llaudio/lllistener_fmodex.cpp
+++ b/indra/llaudio/lllistener_fmodstudio.cpp
@@ -1,7 +1,7 @@
 /** 
- * @file listener_fmodex.cpp
+ * @file listener_fmodstudio.cpp
  * @brief Implementation of LISTENER class abstracting the audio
- * support as a FMODEX implementation
+ * support as a FMOD Studio implementation
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -27,72 +27,54 @@
 
 #include "linden_common.h"
 #include "llaudioengine.h"
-#include "lllistener_fmodex.h"
+#include "lllistener_fmodstudio.h"
 #include "fmod.hpp"
 
 //-----------------------------------------------------------------------
 // constructor
 //-----------------------------------------------------------------------
-LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
+LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) 
+	: LLListener(),
+	mDopplerFactor(1.0f),
+	mRolloffFactor(1.0f)
 {
 	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)
+void LLListener_FMODSTUDIO::translate(const LLVector3& offset)
 {
 	LLListener::translate(offset);
 
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
 }
 
 //-----------------------------------------------------------------------
-void LLListener_FMODEX::setPosition(LLVector3 pos)
+void LLListener_FMODSTUDIO::setPosition(const LLVector3& pos)
 {
 	LLListener::setPosition(pos);
 
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
 }
 
 //-----------------------------------------------------------------------
-void LLListener_FMODEX::setVelocity(LLVector3 vel)
+void LLListener_FMODSTUDIO::setVelocity(const LLVector3& vel)
 {
 	LLListener::setVelocity(vel);
 
-	mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+	mSystem->set3DListenerAttributes(0, nullptr, (FMOD_VECTOR*)mVelocity.mV, nullptr, nullptr);
 }
 
 //-----------------------------------------------------------------------
-void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)
+void LLListener_FMODSTUDIO::orient(const LLVector3& up, const 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);
+	mSystem->set3DListenerAttributes(0, nullptr, nullptr, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
 }
 
 //-----------------------------------------------------------------------
-void LLListener_FMODEX::commitDeferredChanges()
+void LLListener_FMODSTUDIO::commitDeferredChanges()
 {
 	if(!mSystem)
 	{
@@ -103,36 +85,36 @@ void LLListener_FMODEX::commitDeferredChanges()
 }
 
 
-void LLListener_FMODEX::setRolloffFactor(F32 factor)
+void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
 {
-	//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
+	//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 fmodex, which makes it not skip 3D processing next update call.
+	//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 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);
+		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_FMODEX::getRolloffFactor()
+F32 LLListener_FMODSTUDIO::getRolloffFactor()
 {
 	return mRolloffFactor;
 }
 
 
-void LLListener_FMODEX::setDopplerFactor(F32 factor)
+void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor)
 {
 	mDopplerFactor = factor;
 	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
 }
 
 
-F32 LLListener_FMODEX::getDopplerFactor()
+F32 LLListener_FMODSTUDIO::getDopplerFactor()
 {
 	return mDopplerFactor;
 }
diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodstudio.h
similarity index 61%
rename from indra/llaudio/lllistener_fmodex.h
rename to indra/llaudio/lllistener_fmodstudio.h
index 073b65d53adc5c68f5f486f3e2d3bc68cbdea5b0..ebc9f68d2237225347ab4f26e907fea03ec3cc3a 100644
--- a/indra/llaudio/lllistener_fmodex.h
+++ b/indra/llaudio/lllistener_fmodstudio.h
@@ -1,7 +1,7 @@
 /** 
- * @file listener_fmodex.h
+ * @file listener_fmodstudio.h
  * @brief Description of LISTENER class abstracting the audio support
- * as an FMOD 3D implementation (windows and Linux)
+ * as an FMOD Studio implementation (windows and Linux)
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -25,8 +25,8 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_LISTENER_FMODEX_H
-#define LL_LISTENER_FMODEX_H
+#ifndef LL_LISTENER_FMODSTUDIO_H
+#define LL_LISTENER_FMODSTUDIO_H
 
 #include "lllistener.h"
 
@@ -37,23 +37,22 @@ namespace FMOD
 }
 
 //Interfaces
-class LLListener_FMODEX : public LLListener
+class LLListener_FMODSTUDIO final : public LLListener
 {
  public:  
-	LLListener_FMODEX(FMOD::System *system);
-	virtual ~LLListener_FMODEX();
-	virtual void init();  
+	LLListener_FMODSTUDIO(FMOD::System *system);
+	virtual ~LLListener_FMODSTUDIO() = default;
 
-	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();
+	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;
 
-	virtual void setDopplerFactor(F32 factor);
-	virtual F32 getDopplerFactor();
-	virtual void setRolloffFactor(F32 factor);
-	virtual F32 getRolloffFactor();
+	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;
diff --git a/indra/llaudio/lllistener_openal.cpp b/indra/llaudio/lllistener_openal.cpp
index 9dd4c8685460ccf29603f406405e0a94b8e39b2d..855a75b4c37977d1ce4abc0418d089c8a0a07387 100644
--- a/indra/llaudio/lllistener_openal.cpp
+++ b/indra/llaudio/lllistener_openal.cpp
@@ -31,32 +31,29 @@
 #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 +61,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..0a297b2705f0ad969b2db5d5090110782007288b 100644
--- a/indra/llaudio/lllistener_openal.h
+++ b/indra/llaudio/lllistener_openal.h
@@ -33,22 +33,22 @@
 #include "AL/al.h"
 #include "AL/alut.h"
 
-class LLListener_OpenAL  : public LLListener
+class LLListener_OpenAL final : public LLListener
 {
  public:  
 	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 ~LLListener_OpenAL() = default;
+
+	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_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..0daeac7abacc414c72ef0eaf78db42c44762a225
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
@@ -0,0 +1,673 @@
+/** 
+ * @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;
+};
+
+LLMutex 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;
+	}
+
+	{
+		LLMutexLock lock(&gWaveDataMutex);
+
+		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];
+		}
+	}
+	
+	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");
+
+	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");
+	}
+}
+
+bool LLStreamingAudio_FMODSTUDIO::hasNewMetaData()
+{
+	if (mCurrentInternetStreamp && mNewMetadata)
+	{
+		mNewMetadata = false;
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/* virtual */
+bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride/*=1*/)
+{
+	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;
+		{
+			LLMutexLock lock(&gWaveDataMutex);
+			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));
+		}
+		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
+	for (auto 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;
+}
diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea1b5c81a8357b5bfaf7699283b47fbb5d11b724
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.h
@@ -0,0 +1,90 @@
+/** 
+ * @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 final : public LLStreamingAudioInterface
+{
+ public:
+	LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
+	/*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
+
+	/*virtual*/ void start(const std::string& url) override;
+	/*virtual*/ void stop() override;
+	/*virtual*/ void pause(S32 pause) override;
+	/*virtual*/ void update() override;
+	/*virtual*/ S32 isPlaying() override;
+	/*virtual*/ void setGain(F32 vol) override;
+	/*virtual*/ F32 getGain() override;
+	/*virtual*/ std::string getURL() override;
+
+	/*virtual*/ bool supportsAdjustableBufferSizes() override {return true;}
+	/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime) override;
+
+	/*virtual*/ bool supportsMetaData() override {return true;}
+	/*virtual*/ const LLSD *getMetaData() override { return mMetaData; }	//return NULL if not playing.
+	/*virtual*/ bool hasNewMetaData() override;
+	/*virtual*/ bool supportsWaveData() override {return true;}
+	/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1) 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
diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h
index ec58f76f5fd34c48d824e3cbabac3e794fceb33d..e60e1c8ee3ff685b69e5692e521d875ddbabd355 100644
--- a/indra/llaudio/llwindgen.h
+++ b/indra/llaudio/llwindgen.h
@@ -74,7 +74,7 @@ class LLWindGen
 		bool interp_freq = false; 
 		
 		//if the frequency isn't changing much, we don't need to interpolate in the inner loop
-		if (llabs(mTargetFreq - mCurrentFreq) < (mCurrentFreq * 0.112))
+		if (llabs(mTargetFreq - mCurrentFreq) < (mCurrentFreq * 0.112f))
 		{
 			// calculate resonant filter coefficients
 			mCurrentFreq = mTargetFreq;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index cd564d88145f1beff0e4171324ad4139d157b03e..dbe8b1fbb5bacb82ce30c43d0ea97e48e1e00e9e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -17,7 +17,7 @@ include(CMakeCopyIfDifferent)
 include(DBusGlib)
 include(DragDrop)
 include(EXPAT)
-include(FMODEX)
+include(FMODSTUDIO)
 include(GLOD)
 include(Hunspell)
 include(JsonCpp)
@@ -62,9 +62,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(USE_FMODSTUDIO)
+  include_directories(${FMODSTUDIO_INCLUDE_DIR})
+endif(USE_FMODSTUDIO)
 
 include_directories(
     ${DBUSGLIB_INCLUDE_DIRS}
@@ -1721,10 +1721,10 @@ if (OPENAL)
   set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")
 endif (OPENAL)
 
-if (FMODEX)
-  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX")
-  set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY})
-endif (FMODEX)
+if (USE_FMODSTUDIO)
+  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DUSE_FMODSTUDIO=1")
+  set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY})
+endif (USE_FMODSTUDIO)
 
 set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
 
@@ -1841,13 +1841,13 @@ if (WINDOWS)
             )
     endif (ADDRESS_SIZE EQUAL 64)
 
-    if (FMODEX)
+    if (USE_FMODSTUDIO)
       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
+           ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
+           ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
+           ${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll
           )
-    endif (FMODEX)
+    endif (USE_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 68252505d0c16fa5f80633d1253de97391a93f9c..a120f9ecd03c74563c75878c84b1fe0ed91ff176 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16665,18 +16665,18 @@
     <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>
+    <string>Enable profiler tool if using FMOD Studio</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
     <string>Boolean</string>
     <key>Value</key>
     <integer>0</integer>
-    </map>
-  <key>FMODExDecodeBufferSize</key>
+  </map>
+  <key>FMODDecodeBufferSize</key>
   <map>
     <key>Comment</key>
     <string>Sets the streaming decode buffer size (in milliseconds)</string>
@@ -16686,8 +16686,19 @@
     <string>U32</string>
     <key>Value</key>
     <integer>1000</integer>
-    </map>
-  <key>FMODExStreamBufferSize</key>
+  </map>
+  <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 8678bf764dec2ed92780d752002c8af3183bf641..3d0360b2a377d68ed1ade446a96184336ebaf8cd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1789,18 +1789,11 @@ 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
+		// shut down the audio subsystem
         gAudiop->shutdown();
 
 		delete gAudiop;
-		gAudiop = NULL;
+		gAudiop = nullptr;
 	}
 
 	// Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3d8c8b5201e341f4c1f46597bad281b49f0d459a..743522451d0f84de9d48f9ff7b2c60e526538dbc 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"
+#if USE_FMODSTUDIO
+# include "llaudioengine_fmodstudio.h"
 #endif
 
 #ifdef LL_OPENAL
@@ -625,12 +625,14 @@ bool idle_startup()
 			delete gAudiop;
 			gAudiop = NULL;
 
-#ifdef LL_FMODEX		
+#if USE_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
 
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index f2226b5cbdbc52c1cbdfc58adc41378aeaa02563..41a1f6a091c5b8d4e2a442d91819dbb6d4559d3a 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/viewer_manifest.py b/indra/newview/viewer_manifest.py
index a403760670eeff299cf61d3b389e8fc5a054955e..c74dbb9e30230f389fa22f8e5486524747de25ce 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -513,14 +513,11 @@ def construct(self):
                 print err.message
                 print "Skipping GLOD library (assumming linked statically)"
 
-            # Get fmodex dll, continue if missing
-            try:
-                if(self.address_size == 64):
-                    self.path("fmodex64.dll")
-                else:
-                    self.path("fmodex.dll")
-            except:
-                print "Skipping fmodex audio library(assuming other audio engine)"
+            # Get fmodstudio dll, continue if missing
+            if self.args['configuration'].lower() == 'debug':
+                self.path("fmodL.dll")
+            else:
+                self.path("fmod.dll")
 
             # For textures
             self.path("openjpeg.dll")
@@ -1049,12 +1046,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)
 
@@ -1520,14 +1517,12 @@ def construct(self):
                 pass
 
             try:
-                self.path("libfmodex-*.so")
-                self.path("libfmodex.so")
+                self.path_optional("libfmod.so*")
                 pass
             except:
-                print "Skipping libfmodex.so - not found"
+                print "Skipping libfmod.so - not found"
                 pass
 
-
         # Vivox runtimes
         with self.prefix(src=relpkgdir, dst="bin"):
             self.path("SLVoice")