diff --git a/.gitignore b/.gitignore
index 4b0ff9ecf0324c74e06fffe5572310001db2f6cd..a73a85e84f83e108a493f448dcb5546f860c45d1 100755
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.bak
 *.diff
 *.orig
+*.patch
 *.pyc
 *.rej
 *.swp
diff --git a/autobuild.xml b/autobuild.xml
index 448b76e8abc4090dcc7864935d711cb6e609b43c..97110d90322128dc26d6ba9c58e34632dd8e0c86 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -729,38 +729,28 @@
         <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 by Firelight Technologies Pty Ltd.</string>
+        <key>description</key>
+        <string>FMOD Studio API</string>
         <key>license</key>
-        <string>fmodex</string>
+        <string>fmod</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>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>ed0d8767652aecd65a7fef3e28645bad</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>
-            </map>
-            <key>name</key>
-            <string>darwin</string>
-          </map>
           <key>darwin64</key>
           <map>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>93257fce19120c01751362775a01b925</string>
+              <string>dc4c9122de8bf77f34cfc8227d10a272</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1545/3481/fmodex-4.44.64.501533-darwin64-501533.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59038/554626/fmodstudio-2.00.07.541681-darwin64-541681.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -770,9 +760,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b847ec838da1ad1dd646df9d74e9b395</string>
+              <string>c491bdc1690f3d920c66be509ccc6ef2</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>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59039/554632/fmodstudio-2.00.07.541681-linux-541681.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -782,9 +772,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>89a75d8719f7b2cbe1e54cd8407bb992</string>
+              <string>ae75cdb1cc9da824c9e270bf97bfdd6c</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>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54589/506866/fmodstudio-2.00.07.538806-linux64-538806.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -794,9 +784,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>601c2fc41a18812a45678ef9a87ef772</string>
+              <string>7f0294b038eab2d89ecc73bbf08b6d94</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1546/3486/fmodex-4.44.64.501533-windows-501533.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59042/554668/fmodstudio-2.00.07.541681-windows-541681.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -806,16 +796,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>e5cde35ae26ebfa256cfe670986e152e</string>
+              <string>da2e8e2b809d8fe635ee437baa2a7386</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1547/3487/fmodex-4.44.64.501533-windows64-501533.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59041/554656/fmodstudio-2.00.07.541681-windows64-541681.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.541681</string>
       </map>
       <key>fontconfig</key>
       <map>
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 84e1c5d6fdee0b417b144d9b314a47817eb8cbac..3a14bf522f0732342bbed80eeac1f059cbeaae0b 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -28,7 +28,6 @@ set(cmake_SOURCE_FILES
     FindAPR.cmake
     FindAutobuild.cmake
     FindBerkeleyDB.cmake
-    FindFMODEX.cmake
     FindGLH.cmake
     FindGoogleBreakpad.cmake
     FindHUNSPELL.cmake
@@ -39,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..82cd5d62e85931060f6bbcc903aa58ccdc6f984b 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 (FMODSTUDIO)
+        set(debug_files ${debug_files} fmodL.dll)
+        set(release_files ${release_files} fmod.dll)
+    endif (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 (FMODSTUDIO)
+      set(debug_files ${debug_files} libfmodL.dylib)
+      set(release_files ${release_files} libfmod.dylib)
+    endif (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 (FMODSTUDIO)
+      set(debug_files ${debug_files} "libfmodL.so")
+      set(release_files ${release_files} "libfmod.so")
+    endif (FMODSTUDIO)
 
 else(WINDOWS)
     message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake
deleted file mode 100644
index 720933d1b794bf369e17b70bd81591f1b79ff274..0000000000000000000000000000000000000000
--- a/indra/cmake/FMODEX.cmake
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- cmake -*-
-
-# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON
-# When building using proprietary binaries though (i.e. having access to LL private servers),
-# we always build with FMODEX.
-# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether
-# they are using USESYSTEMLIBS or not.
-if (INSTALL_PROPRIETARY)
-  set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.")
-endif (INSTALL_PROPRIETARY)
-
-if (FMODEX)
-  if (USESYSTEMLIBS)
-    # In that case, we use the version of the library installed on the system
-    set(FMODEX_FIND_REQUIRED ON)
-    include(FindFMODEX)
-  else (USESYSTEMLIBS)
-    if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
-      # If the path have been specified in the arguments, use that
-      set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
-      MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}")
-    else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
-      # If not, we're going to try to get the package listed in autobuild.xml
-      # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) 
-      # as accessing the private LL location will fail if you don't have the credential
-      include(Prebuilt)
-      use_prebuilt_binary(fmodex)    
-      if (WINDOWS)
-        set(FMODEX_LIBRARY 
-            debug fmodexL_vc
-            optimized fmodex_vc)
-      elseif (DARWIN)
-        set(FMODEX_LIBRARY 
-            debug fmodexL
-            optimized fmodex)
-      elseif (LINUX)
-        set(FMODEX_LIBRARY 
-            debug fmodexL
-            optimized fmodex)
-      endif (WINDOWS)
-      set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
-      set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex)
-    endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
-  endif (USESYSTEMLIBS)
-endif (FMODEX)
-
diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8840354ac6c3d53d7d46040f65019fcc7903d66d
--- /dev/null
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -0,0 +1,38 @@
+# -*- cmake -*-
+
+# FMODSTUDIO can be set when launching the make using the argument -DFMODSTUDIO:BOOL=ON
+# When building using proprietary binaries though (i.e. having access to LL private servers),
+# we always build with FMODSTUDIO.
+if (INSTALL_PROPRIETARY)
+  set(FMODSTUDIO ON CACHE BOOL "Using FMODSTUDIO sound library.")
+endif (INSTALL_PROPRIETARY)
+
+if (FMODSTUDIO)
+  if (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR)
+    # If the path have been specified in the arguments, use that
+    set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY})
+  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)
+      #despite files being called libfmod.dylib, we are searching for fmod
+      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 (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/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index e943dd5d5ccd059100c1ad41507a3f5d377b73d1..8b628a058e0b74b7d8d603185f5a9a3ce76a675e 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)
@@ -42,22 +42,22 @@ set(llaudio_HEADER_FILES
     llwindgen.h
     )
 
-if (FMODEX)
+if (FMODSTUDIO)
     include_directories(
-        ${FMODEX_INCLUDE_DIR}
+        ${FMODSTUDIO_INCLUDE_DIR}
         )
     list(APPEND llaudio_SOURCE_FILES
-         llaudioengine_fmodex.cpp
-         lllistener_fmodex.cpp
-         llstreamingaudio_fmodex.cpp
+         llaudioengine_fmodstudio.cpp
+         lllistener_fmodstudio.cpp
+         llstreamingaudio_fmodstudio.cpp
          )
 
     list(APPEND llaudio_HEADER_FILES
-         llaudioengine_fmodex.h
-         lllistener_fmodex.h
-         llstreamingaudio_fmodex.h
+         llaudioengine_fmodstudio.h
+         lllistener_fmodstudio.h
+         llstreamingaudio_fmodstudio.h
          )
-endif (FMODEX)
+endif (FMODSTUDIO)
 
 if (OPENAL)
   list(APPEND llaudio_SOURCE_FILES
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index f49028aad51955fbc5a606cda3ebcf9f2985e43e..1d447f32ae77ee4f0eb508ff2091e751f4839861 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -111,7 +111,7 @@ void LLAudioEngine::setDefaults()
 }
 
 
-bool LLAudioEngine::init(const S32 num_channels, void* userdata)
+bool LLAudioEngine::init(const S32 num_channels, void* userdata, const std::string &app_title)
 {
 	setDefaults();
 
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index f1e1b4e308c79a440115011ed64a53c2dfe0343e..97674f15f7a37494baf8da9ef8030a1d389acfb0 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -99,7 +99,7 @@ class LLAudioEngine
 	virtual ~LLAudioEngine();
 
 	// initialization/startup/shutdown
-	virtual bool init(const S32 num_channels, void *userdata);
+	virtual bool init(const S32 num_channels, void *userdata, const std::string &app_title);
 	virtual std::string getDriverName(bool verbose) = 0;
 	virtual void shutdown();
 
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..70b3a0847388a0b7639e1501a62a8bb8980ad16d
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -0,0 +1,753 @@
+/** 
+ * @file audioengine_fmodstudio.cpp
+ * @brief Implementation of LLAudioEngine class abstracting the audio 
+ * support as a FMODSTUDIO implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llstreamingaudio.h"
+#include "llstreamingaudio_fmodstudio.h"
+
+#include "llaudioengine_fmodstudio.h"
+#include "lllistener_fmodstudio.h"
+
+#include "llerror.h"
+#include "llmath.h"
+#include "llrand.h"
+
+#include "fmodstudio/fmod.hpp"
+#include "fmodstudio/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_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0};
+
+LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler)
+:   mInited(false),
+    mWindGen(NULL),
+    mWindDSP(NULL),
+    mSystem(NULL),
+    mEnableProfiler(enable_profiler),
+    mWindDSPDesc(NULL)
+{
+}
+
+
+LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO()
+{
+    // mWindDSPDesc, mWindGen and mWindDSP get cleaned up on cleanupWind in LLAudioEngine::shutdown()
+    // mSystem gets cleaned up at shutdown()
+}
+
+
+static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
+{
+    if (result == FMOD_OK)
+        return false;
+    LL_DEBUGS("FMOD") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
+    return true;
+}
+
+bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, const std::string &app_title)
+{
+    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, app_title);
+
+    result = mSystem->getVersion(&version);
+    Check_FMOD_Error(result, "FMOD::System::getVersion");
+
+    if (version < FMOD_VERSION)
+    {
+        LL_WARNS("AppInit") << "FMOD Studio version mismatch, actual: " << version
+            << " expected:" << FMOD_VERSION << LL_ENDL;
+    }
+
+    // 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");
+
+    FMOD_ADVANCEDSETTINGS settings;
+    memset(&settings, 0, sizeof(settings));
+    settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS);
+    settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR;
+
+    result = mSystem->setAdvancedSettings(&settings);
+    Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings");
+
+    // FMOD_INIT_THREAD_UNSAFE Disables thread safety for API calls.
+    // Only use this if FMOD is being called from a single thread, and if Studio API is not being used.
+    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)
+    {
+        const char* env_string = getenv("LL_BAD_FMOD_PULSEAUDIO");
+        if (NULL == env_string)
+        {
+            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, const_cast<char*>(app_title.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)
+    {
+        const char* env_string = getenv("LL_BAD_FMOD_ALSA");
+        if (NULL == env_string)
+        {
+            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)
+    {
+        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;
+    default:
+        LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
+    };
+#else // LL_LINUX
+
+    // initialize the FMOD engine
+    // number of channel in this case looks to be identiacal to number of max simultaneously
+    // playing objects and we can set practically any number
+    result = mSystem->init(num_channels + 2, fmod_flags, 0);
+    if (Check_FMOD_Error(result, "Error initializing FMOD Studio with default settins, retrying with other format"))
+    {
+        result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0/*- ignore*/);
+        if (Check_FMOD_Error(result, "Error setting sotware format. Can't init."))
+        {
+            return false;
+        }
+        result = mSystem->init(num_channels + 2, fmod_flags, 0);
+    }
+    if (Check_FMOD_Error(result, "Error initializing FMOD Studio"))
+    {
+        // If it fails here and (result == FMOD_ERR_OUTPUT_CREATEBUFFER),
+        // we can retry with other settings
+        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_FMODSTUDIO(mSystem));
+
+    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL;
+
+    int r_numbuffers, r_samplerate, r_channels;
+    unsigned int r_bufferlength;
+    char r_name[512];
+    int latency = 100;
+    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;
+
+    mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels);
+    r_name[511] = '\0';
+    LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL;
+
+    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)
+{
+    mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem);
+    if (!mListenerp)
+    {
+        LL_WARNS("FMOD") << "Listener creation failed" << LL_ENDL;
+    }
+}
+
+
+void LLAudioEngine_FMODSTUDIO::shutdown()
+{
+    stopInternetStream();
+
+    LL_INFOS("FMOD") << "About to LLAudioEngine::shutdown()" << LL_ENDL;
+    LLAudioEngine::shutdown();
+
+    LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL;
+    if (mSystem)
+    {
+        mSystem->close();
+        mSystem->release();
+    }
+    LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL;
+
+    delete mListenerp;
+    mListenerp = NULL;
+}
+
+
+LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer()
+{
+    return new LLAudioBufferFMODSTUDIO(mSystem);
+}
+
+
+LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel()
+{
+    return new LLAudioChannelFMODSTUDIO(mSystem);
+}
+
+bool LLAudioEngine_FMODSTUDIO::initWind()
+{
+    mNextWindUpdate = 0.0;
+
+    if (!mWindDSPDesc)
+    {
+        mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
+    }
+
+    if (!mWindDSP)
+    {
+        memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc));	//Set everything to zero
+        strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name));
+        mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
+        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;
+
+        int frequency = 44100;
+
+        FMOD_SPEAKERMODE mode;
+        if (Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat"))
+        {
+            cleanupWind();
+            return false;
+        }
+
+        mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
+
+        if (Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData"))
+        {
+            cleanupWind();
+            return false;
+        }
+        if (Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat"))
+        {
+            cleanupWind();
+            return false;
+        }
+    }
+
+    // *TODO:  Should this guard against multiple plays?
+    if (Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP"))
+    {
+        cleanupWind();
+        return false;
+    }
+    return true;
+}
+
+
+void LLAudioEngine_FMODSTUDIO::cleanupWind()
+{
+    if (mWindDSP)
+    {
+        FMOD::ChannelGroup* master_group = NULL;
+        if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup")
+            && master_group)
+        {
+            master_group->removeDSP(mWindDSP);
+        }
+        mWindDSP->release();
+        mWindDSP = NULL;
+    }
+
+    delete mWindDSPDesc;
+    mWindDSPDesc = NULL;
+
+    delete mWindGen;
+    mWindGen = NULL;
+}
+
+
+//-----------------------------------------------------------------------
+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 = NULL;
+    if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::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());
+    }
+}
+
+//
+// LLAudioChannelFMODSTUDIO implementation
+//
+
+LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0)
+{
+}
+
+
+LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO()
+{
+    cleanup();
+}
+
+bool LLAudioChannelFMODSTUDIO::updateBuffer()
+{
+    if (!mCurrentSourcep)
+    {
+        // This channel isn't associated with any source, nothing
+        // to be updated
+        return false;
+    }
+
+    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, NULL /*free channel?*/, true, &mChannelp);
+            Check_FMOD_Error(result, "FMOD::System::playSound");
+        }
+
+        // Setting up channel mChannelID
+    }
+
+    // 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 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;
+    mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES);
+
+    if (cur_pos < (U32)mLastSamplePos)
+    {
+        mLoopedThisFrame = true;
+    }
+    mLastSamplePos = cur_pos;
+}
+
+
+void LLAudioChannelFMODSTUDIO::cleanup()
+{
+    if (!mChannelp)
+    {
+        // Aborting cleanup with no channel handle.
+        return;
+    }
+
+    //Cleaning up channel mChannelID
+    Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop");
+
+    mCurrentBufferp = NULL;
+    mChannelp = NULL;
+}
+
+
+void LLAudioChannelFMODSTUDIO::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_FMODSTUDIO::mChannelGroups[getSource()->getType()])
+        mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]);
+}
+
+
+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;
+    mChannelp->getPaused(&paused);
+    mChannelp->isPlaying(&playing);
+    return !paused && playing;
+}
+
+
+//
+// LLAudioChannelFMODSTUDIO implementation
+//
+
+
+LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystemp(system), mSoundp(NULL)
+{
+}
+
+
+LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO()
+{
+    if (mSoundp)
+    {
+        mSoundp->release();
+        mSoundp = NULL;
+    }
+}
+
+
+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 (!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_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 (since 1.05 fmod studio expects everything in UTF-8)
+    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;
+    mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
+    return length;
+}
+
+
+void LLAudioChannelFMODSTUDIO::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 *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
+{
+    // inbuffer = fmod's original mixbuffer.
+    // outbuffer = the buffer passed from the previous DSP unit.
+    // length = length in samples at this mix time.
+
+    LLWindGen<LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT> *windgen = NULL;
+    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 75%
rename from indra/llaudio/llaudioengine_fmodex.h
rename to indra/llaudio/llaudioengine_fmodstudio.h
index ca389d489fd981359e666ae50b250668a7489c90..f2361df1b618005d5ab9f7db595d0353e394afe5 100644
--- a/indra/llaudio/llaudioengine_fmodex.h
+++ b/indra/llaudio/llaudioengine_fmodstudio.h
@@ -1,11 +1,11 @@
 /** 
- * @file audioengine_fmodex.h
+ * @file audioengine_fmodstudio.h
  * @brief Definition of LLAudioEngine class abstracting the audio 
- * support as a FMODEX implementation
+ * support as a FMODSTUDIO implementation
  *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2014, Linden Research, Inc.
+ * Copyright (C) 2020, 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
@@ -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,14 +44,14 @@ namespace FMOD
 typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
 
 //Interfaces
-class LLAudioEngine_FMODEX : public LLAudioEngine 
+class LLAudioEngine_FMODSTUDIO : public LLAudioEngine 
 {
 public:
-	LLAudioEngine_FMODEX(bool enable_profiler);
-	virtual ~LLAudioEngine_FMODEX();
+	LLAudioEngine_FMODSTUDIO(bool enable_profiler);
+	virtual ~LLAudioEngine_FMODSTUDIO();
 
 	// initialization/startup/shutdown
-	virtual bool init(const S32 num_channels, void *user_data);
+	virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title);
 	virtual std::string getDriverName(bool verbose);
 	virtual void allocateListener();
 
@@ -85,11 +85,11 @@ class LLAudioEngine_FMODEX : public LLAudioEngine
 };
 
 
-class LLAudioChannelFMODEX : public LLAudioChannel
+class LLAudioChannelFMODSTUDIO : public LLAudioChannel
 {
 public:
-	LLAudioChannelFMODEX(FMOD::System *audioengine);
-	virtual ~LLAudioChannelFMODEX();
+    LLAudioChannelFMODSTUDIO(FMOD::System *audioengine);
+    virtual ~LLAudioChannelFMODSTUDIO();
 
 protected:
 	/*virtual*/ void play();
@@ -110,15 +110,15 @@ class LLAudioChannelFMODEX : public LLAudioChannel
 };
 
 
-class LLAudioBufferFMODEX : public LLAudioBuffer
+class LLAudioBufferFMODSTUDIO : 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;
+	friend class LLAudioChannelFMODSTUDIO;
 protected:
 	FMOD::System *getSystem()	const {return mSystemp;}
 	FMOD::System *mSystemp;
@@ -127,4 +127,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..a38d8291fa900a3e907c17b186920858d2d33133 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -52,7 +52,7 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
 }
 
 // virtual
-bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
+bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata, const std::string &app_title)
 {
 	mWindGen = NULL;
 	LLAudioEngine::init(num_channels, userdata);
@@ -239,6 +239,13 @@ bool LLAudioChannelOpenAL::isPlaying()
 
 bool LLAudioChannelOpenAL::updateBuffer()
 {
+    if (!mCurrentSourcep)
+    {
+        // This channel isn't associated with any source, nothing
+        // to be updated
+        return false;
+    }
+
 	if (LLAudioChannel::updateBuffer())
 	{
 		// Base class update returned true, which means that we need to actually
diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h
index 6639d9dfe648772a5b718c552284765463cffbcf..366f9259e31e825f139763ea04ff7290abe6f9a7 100644
--- a/indra/llaudio/llaudioengine_openal.h
+++ b/indra/llaudio/llaudioengine_openal.h
@@ -40,8 +40,8 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
 		LLAudioEngine_OpenAL();
 		virtual ~LLAudioEngine_OpenAL();
 
-		virtual bool init(const S32 num_channels, void *user_data);
-        	virtual std::string getDriverName(bool verbose);
+        virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title);
+        virtual std::string getDriverName(bool verbose);
 		virtual void allocateListener();
 
 		virtual void shutdown();
diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodex.cpp
deleted file mode 100644
index 31ab47a635f34d93fd1ee3e85676c785affa0e28..0000000000000000000000000000000000000000
--- a/indra/llaudio/lllistener_fmodex.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/** 
- * @file listener_fmodex.cpp
- * @brief Implementation of LISTENER class abstracting the audio
- * support as a FMODEX implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llaudioengine.h"
-#include "lllistener_fmodex.h"
-#include "fmod.hpp"
-
-//-----------------------------------------------------------------------
-// constructor
-//-----------------------------------------------------------------------
-LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
-{
-	mSystem = system;
-	init();
-}
-
-//-----------------------------------------------------------------------
-LLListener_FMODEX::~LLListener_FMODEX()
-{
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::init(void)
-{
-	// do inherited
-	LLListener::init();
-	mDopplerFactor = 1.0f;
-	mRolloffFactor = 1.0f;
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::translate(LLVector3 offset)
-{
-	LLListener::translate(offset);
-
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::setPosition(LLVector3 pos)
-{
-	LLListener::setPosition(pos);
-
-	mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::setVelocity(LLVector3 vel)
-{
-	LLListener::setVelocity(vel);
-
-	mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)
-{
-	LLListener::orient(up, at);
-
-	// Welcome to the transition between right and left
-	// (coordinate systems, that is)
-	// Leaving the at vector alone results in a L/R reversal
-	// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
-	at = -at;
-
-	mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
-}
-
-//-----------------------------------------------------------------------
-void LLListener_FMODEX::commitDeferredChanges()
-{
-	if(!mSystem)
-	{
-		return;
-	}
-
-	mSystem->update();
-}
-
-
-void LLListener_FMODEX::setRolloffFactor(F32 factor)
-{
-	//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
-	//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
-	//In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call.
-	if(mRolloffFactor != factor)
-	{
-		LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f);
-		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
-		mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL);
-	}
-	mRolloffFactor = factor;
-	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
-}
-
-
-F32 LLListener_FMODEX::getRolloffFactor()
-{
-	return mRolloffFactor;
-}
-
-
-void LLListener_FMODEX::setDopplerFactor(F32 factor)
-{
-	mDopplerFactor = factor;
-	mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
-}
-
-
-F32 LLListener_FMODEX::getDopplerFactor()
-{
-	return mDopplerFactor;
-}
-
-
diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..abd5e345b57c9c07ed0839596e911b916d49ef10
--- /dev/null
+++ b/indra/llaudio/lllistener_fmodstudio.cpp
@@ -0,0 +1,136 @@
+/** 
+ * @file listener_fmodstudio.cpp
+ * @brief Implementation of LISTENER class abstracting the audio
+ * support as a FMODSTUDIO implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llaudioengine.h"
+#include "lllistener_fmodstudio.h"
+#include "fmodstudio/fmod.hpp"
+
+//-----------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------
+LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
+{
+    mSystem = system;
+    init();
+}
+
+//-----------------------------------------------------------------------
+LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO()
+{
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::init(void)
+{
+    // do inherited
+    LLListener::init();
+    mDopplerFactor = 1.0f;
+    mRolloffFactor = 1.0f;
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::translate(LLVector3 offset)
+{
+    LLListener::translate(offset);
+
+    mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::setPosition(LLVector3 pos)
+{
+    LLListener::setPosition(pos);
+
+    mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel)
+{
+    LLListener::setVelocity(vel);
+
+    mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at)
+{
+    LLListener::orient(up, at);
+
+    // at = -at; by default Fmod studio is 'left-handed' but we are providing
+    // flag FMOD_INIT_3D_RIGHTHANDED so no correction are needed
+
+    mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMODSTUDIO::commitDeferredChanges()
+{
+    if (!mSystem)
+    {
+        return;
+    }
+
+    mSystem->update();
+}
+
+
+void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
+{
+    //An internal FMOD optimization skips 3D updates if there have not been changes to the 3D sound environment.
+    // (this was true for FMODex, looks to be still true for FMOD STUDIO, but needs a recheck)
+    //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
+    //In short: Changing the position ticks a dirtyflag inside fmod, which makes it not skip 3D processing next update call.
+    if (mRolloffFactor != factor)
+    {
+        LLVector3 pos = mPosition - LLVector3(0.f, 0.f, .1f);
+        mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
+        mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
+    }
+    mRolloffFactor = factor;
+    mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
+}
+
+
+F32 LLListener_FMODSTUDIO::getRolloffFactor()
+{
+    return mRolloffFactor;
+}
+
+
+void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor)
+{
+    mDopplerFactor = factor;
+    mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
+}
+
+
+F32 LLListener_FMODSTUDIO::getDopplerFactor()
+{
+    return mDopplerFactor;
+}
diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodstudio.h
similarity index 53%
rename from indra/llaudio/lllistener_fmodex.h
rename to indra/llaudio/lllistener_fmodstudio.h
index 073b65d53adc5c68f5f486f3e2d3bc68cbdea5b0..6ad85d9700ca161fdebe67d3023fe544808a5474 100644
--- a/indra/llaudio/lllistener_fmodex.h
+++ b/indra/llaudio/lllistener_fmodstudio.h
@@ -1,11 +1,11 @@
 /** 
- * @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 3D implementation
  *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2020, 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
@@ -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,27 +37,27 @@ namespace FMOD
 }
 
 //Interfaces
-class LLListener_FMODEX : public LLListener
+class LLListener_FMODSTUDIO : public LLListener
 {
- public:  
-	LLListener_FMODEX(FMOD::System *system);
-	virtual ~LLListener_FMODEX();
-	virtual void init();  
+public:
+    LLListener_FMODSTUDIO(FMOD::System *system);
+    virtual ~LLListener_FMODSTUDIO();
+    virtual void init();
 
-	virtual void translate(LLVector3 offset);
-	virtual void setPosition(LLVector3 pos);
-	virtual void setVelocity(LLVector3 vel);
-	virtual void orient(LLVector3 up, LLVector3 at);
-	virtual void commitDeferredChanges();
+    virtual void translate(LLVector3 offset);
+    virtual void setPosition(LLVector3 pos);
+    virtual void setVelocity(LLVector3 vel);
+    virtual void orient(LLVector3 up, LLVector3 at);
+    virtual void commitDeferredChanges();
 
-	virtual void setDopplerFactor(F32 factor);
-	virtual F32 getDopplerFactor();
-	virtual void setRolloffFactor(F32 factor);
-	virtual F32 getRolloffFactor();
- protected:
-	 FMOD::System *mSystem;
-	 F32 mDopplerFactor;
-	 F32 mRolloffFactor;
+    virtual void setDopplerFactor(F32 factor);
+    virtual F32 getDopplerFactor();
+    virtual void setRolloffFactor(F32 factor);
+    virtual F32 getRolloffFactor();
+protected:
+    FMOD::System *mSystem;
+    F32 mDopplerFactor;
+    F32 mRolloffFactor;
 };
 
 #endif
diff --git a/indra/llaudio/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..08d19209aadf0a80a43f3a49e0df1bc544a0c645
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
@@ -0,0 +1,392 @@
+/** 
+ * @file streamingaudio_fmodstudio.cpp
+ * @brief LLStreamingAudio_FMODSTUDIO implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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 "fmodstudio/fmod.hpp"
+#include "fmodstudio/fmod_errors.h"
+
+#include "llstreamingaudio_fmodstudio.h"
+
+
+class LLAudioStreamManagerFMODSTUDIO
+{
+public:
+    LLAudioStreamManagerFMODSTUDIO(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_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(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_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
+{
+    // nothing interesting/safe to do.
+}
+
+
+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())
+    {
+        LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
+        mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url);
+        mURL = url;
+    }
+    else
+    {
+        LL_INFOS() << "Set internet stream to null" << LL_ENDL;
+        mURL.clear();
+    }
+}
+
+
+void LLStreamingAudio_FMODSTUDIO::update()
+{
+    // Kill dead internet streams, if possible
+    std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
+    for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
+    {
+        LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
+        if (streamp->stopStream())
+        {
+            LL_INFOS() << "Closed dead stream" << LL_ENDL;
+            delete streamp;
+            mDeadStreams.erase(iter++);
+        }
+        else
+        {
+            iter++;
+        }
+    }
+
+    // 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_FMODSTUDIO::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_FMODSTUDIO::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_FMODSTUDIO::isPlaying()
+{
+    if (mCurrentInternetStreamp)
+    {
+        return 1; // Active and playing
+    }
+    else if (!mURL.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?
+
+        mFMODInternetStreamChannelp->setVolume(vol);
+    }
+}
+
+///////////////////////////////////////////////////////
+// manager of possibly-multiple internet audio streams
+
+LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(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 *LLAudioStreamManagerFMODSTUDIO::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(mInternetStream, NULL, true, &mStreamChannel);
+    return mStreamChannel;
+}
+
+bool LLAudioStreamManagerFMODSTUDIO::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 LLAudioStreamManagerFMODSTUDIO::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
+{
+    FMOD_OPENSTATE state;
+    mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
+    return state;
+}
+
+void LLStreamingAudio_FMODSTUDIO::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_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fc3c54d79bc7fcb2815234b4a01951d5745103b
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.h
@@ -0,0 +1,73 @@
+/** 
+ * @file streamingaudio_fmodstudio.h
+ * @brief Definition of LLStreamingAudio_FMODSTUDIO implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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;
+}
+
+//Interfaces
+class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface
+{
+public:
+    LLStreamingAudio_FMODSTUDIO(FMOD::System *system);
+    /*virtual*/ ~LLStreamingAudio_FMODSTUDIO();
+
+    /*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;
+
+    LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
+    FMOD::Channel *mFMODInternetStreamChannelp;
+    std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams;
+
+    std::string mURL;
+    F32 mGain;
+};
+
+
+#endif // LL_STREAMINGAUDIO_FMODSTUDIO_H
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f76012bdfa1284bf1fba8b0f2124f5d9924e55e4..33fa186a2eb7a2b5a7453ffcb5895c15c9a24e09 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -18,7 +18,7 @@ include(DBusGlib)
 include(DirectX)
 include(DragDrop)
 include(EXPAT)
-include(FMODEX)
+include(FMODSTUDIO)
 include(GLOD)
 include(Hunspell)
 include(JsonCpp)
@@ -63,9 +63,9 @@ if (NOT HAVOK_TPV)
    add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions)
 endif (NOT HAVOK_TPV)
 
-if(FMODEX)
-  include_directories(${FMODEX_INCLUDE_DIR})
-endif(FMODEX)
+if(FMODSTUDIO)
+  include_directories(${FMODSTUDIO_INCLUDE_DIR})
+endif(FMODSTUDIO)
 
 include_directories(
     ${DBUSGLIB_INCLUDE_DIRS}
@@ -1722,12 +1722,13 @@ 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 (FMODSTUDIO)
+  set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO")
+  set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY})
+endif (FMODSTUDIO)
 
 set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
+set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
 
 list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
 
@@ -1842,13 +1843,13 @@ if (WINDOWS)
             )
     endif (ADDRESS_SIZE EQUAL 64)
 
-    if (FMODEX)
+    if (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 (FMODSTUDIO)
 
     add_custom_command(
       OUTPUT  ${CMAKE_CFG_INTDIR}/copy_touched.bat
@@ -1859,6 +1860,7 @@ if (WINDOWS)
         --arch=${ARCH}
         --artwork=${ARTWORK_DIR}
         "--bugsplat=${BUGSPLAT_DB}"
+        "--fmodstudio=${FMODSTUDIO}"
         --build=${CMAKE_CURRENT_BINARY_DIR}
         --buildtype=${CMAKE_BUILD_TYPE}
         "--channel=${VIEWER_CHANNEL}"
@@ -1920,6 +1922,7 @@ if (WINDOWS)
           --arch=${ARCH}
           --artwork=${ARTWORK_DIR}
           "--bugsplat=${BUGSPLAT_DB}"
+          "--fmodstudio=${FMODSTUDIO}"
           --build=${CMAKE_CURRENT_BINARY_DIR}
           --buildtype=${CMAKE_BUILD_TYPE}
           "--channel=${VIEWER_CHANNEL}"
@@ -2065,6 +2068,7 @@ if (LINUX)
         --arch=${ARCH}
         --artwork=${ARTWORK_DIR}
         "--bugsplat=${BUGSPLAT_DB}"
+        "--fmodstudio=${FMODSTUDIO}"
         --build=${CMAKE_CURRENT_BINARY_DIR}
         --buildtype=${CMAKE_BUILD_TYPE}
         "--channel=${VIEWER_CHANNEL}"
@@ -2091,6 +2095,7 @@ if (LINUX)
       --arch=${ARCH}
       --artwork=${ARTWORK_DIR}
       "--bugsplat=${BUGSPLAT_DB}"
+      "--fmodstudio=${FMODSTUDIO}"
       --build=${CMAKE_CURRENT_BINARY_DIR}
       --buildtype=${CMAKE_BUILD_TYPE}
       "--channel=${VIEWER_CHANNEL}"
@@ -2167,6 +2172,7 @@ if (DARWIN)
       --arch=${ARCH}
       --artwork=${ARTWORK_DIR}
       "--bugsplat=${BUGSPLAT_DB}"
+      "--fmodstudio=${FMODSTUDIO}"
       --build=${CMAKE_CURRENT_BINARY_DIR}
       --buildtype=${CMAKE_BUILD_TYPE}
       --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER}
@@ -2201,6 +2207,7 @@ if (DARWIN)
           --arch=${ARCH}
           --artwork=${ARTWORK_DIR}
           "--bugsplat=${BUGSPLAT_DB}"
+          "--fmodstudio=${FMODSTUDIO}"
           --build=${CMAKE_CURRENT_BINARY_DIR}
           --buildtype=${CMAKE_BUILD_TYPE}
           "--channel=${VIEWER_CHANNEL}"
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 133cad286fdf619d1cbbb26931c01f4e180b36a4..49df80bfeb472e079a3463bbb30059ae0d903a05 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.3
+6.4.4
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d11269a6e6e691eb2aff1cb652bec934e06d5882..dfc3c7b89da852cd3dd1f3cabe37eff899794db5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16384,7 +16384,7 @@
   <key>FMODExProfilerEnable</key>
   <map>
     <key>Comment</key>
-    <string>Enable profiler tool if using FMOD Ex</string>
+    <string>Enable profiler tool if using FMOD Ex or FMOD Studio</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
@@ -16395,7 +16395,7 @@
   <key>FMODExDecodeBufferSize</key>
   <map>
     <key>Comment</key>
-    <string>Sets the streaming decode buffer size (in milliseconds)</string>
+    <string>Sets the streaming decode buffer size (in milliseconds) for FMOD Ex or FMOD Studio</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
@@ -16406,7 +16406,7 @@
   <key>FMODExStreamBufferSize</key>
   <map>
     <key>Comment</key>
-    <string>Sets the streaming buffer size (in milliseconds)</string>
+    <string>Sets the streaming buffer size (in milliseconds) for FMOD Ex or FMOD Studio</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt
index e01b9e4bc63548a7d7c8c765ffa73a28a6f675b0..cb8d1af53582be2fd3fb7c464596e730cef883f7 100644
--- a/indra/newview/linux_tools/client-readme.txt
+++ b/indra/newview/linux_tools/client-readme.txt
@@ -187,8 +187,8 @@ The 'secondlife' script which launches Second Life contains some
 configuration options for advanced troubleshooters.
 
 * AUDIO - Edit the 'secondlife' script and you will see these audio
-  options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMOD_ESD, LL_BAD_FMOD_OSS, and
-  LL_BAD_FMOD_ALSA.  Second Life tries to use OpenAL, ESD, OSS, then ALSA
+  options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMODSTUDIO_DRIVER.
+  Second Life tries to use OpenAL, FMODSTUDIO (PULSEAUDIO, ALSA)
   audio drivers in this order; you may uncomment the corresponding LL_BAD_*
   option to skip an audio driver which you believe may be causing you trouble.
 
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index c23401d5a661fd954536fadf9c9b8fa0c7da3779..eb3ead433b742f687384b6a1da1469317a633909 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -4,17 +4,15 @@
 ## These options are for self-assisted troubleshooting during this beta
 ## testing phase; you should not usually need to touch them.
 
-## - Avoids using any FMOD Ex audio driver.
-#export LL_BAD_FMODEX_DRIVER=x
+## - Avoids using any FMOD STUDIO audio driver.
+#export LL_BAD_FMODSTUDIO_DRIVER=x
 ## - Avoids using any OpenAL audio driver.
 #export LL_BAD_OPENAL_DRIVER=x
 
-## - Avoids using the FMOD Ex PulseAudio audio driver.
+## - Avoids using the FMOD Studio or FMOD Ex PulseAudio audio driver.
 #export LL_BAD_FMOD_PULSEAUDIO=x
-## - Avoids using the FMOD or FMOD Ex ALSA audio driver.
+## - Avoids using the FMOD Studio or FMOD Ex ALSA audio driver.
 #export LL_BAD_FMOD_ALSA=x
-## - Avoids using the FMOD or FMOD Ex OSS audio driver.
-#export LL_BAD_FMOD_OSS=x
 
 ## - Avoids the optional OpenGL extensions which have proven most problematic
 ##   on some hardware.  Disabling this option may cause BETTER PERFORMANCE but
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 083a913ef8bb1479d0ad248d0a2209eebeb2f367..e9feae3457bec753b914eec5d3969f3dbcf11469 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -229,6 +229,33 @@ void LLProgressView::drawStartTexture(F32 alpha)
 	gGL.popMatrix();
 }
 
+void LLProgressView::drawLogos(F32 alpha)
+{
+    if (mLogosList.empty())
+    {
+        return;
+    }
+
+    // logos are tied to label,
+    // due to potential resizes we have to figure offsets out on draw or resize
+    LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl");
+    S32 offset_x, offset_y;
+    logos_label->localPointToScreen(0, 0, &offset_x, &offset_y);
+    std::vector<TextureData>::const_iterator iter = mLogosList.begin();
+    std::vector<TextureData>::const_iterator end = mLogosList.end();
+    for (; iter != end; iter++)
+    {
+        gl_draw_scaled_image_with_border(iter->mDrawRect.mLeft + offset_x,
+                             iter->mDrawRect.mBottom + offset_y,
+                             iter->mDrawRect.getWidth(),
+                             iter->mDrawRect.getHeight(),
+                             iter->mTexturep.get(),
+                             UI_VERTEX_COLOR % alpha,
+                             FALSE,
+                             iter->mClipRect,
+                             iter->mOffsetRect);
+    }
+}
 
 void LLProgressView::draw()
 {
@@ -245,6 +272,7 @@ void LLProgressView::draw()
 		}
 		
 		LLPanel::draw();
+		drawLogos(alpha);
 		return;
 	}
 
@@ -257,6 +285,7 @@ void LLProgressView::draw()
 				
 		drawStartTexture(alpha);
 		LLPanel::draw();
+		drawLogos(alpha);
 
 		// faded out completely - remove panel and reveal world
 		if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
@@ -283,7 +312,7 @@ void LLProgressView::draw()
 			// FIXME: this causes a crash that i haven't been able to fix
 			mMediaCtrl->unloadMediaSource();	
 
-			gStartTexture = NULL;
+            releaseTextures();
 		}
 		return;
 	}
@@ -291,6 +320,7 @@ void LLProgressView::draw()
 	drawStartTexture(1.0f);
 	// draw children
 	LLPanel::draw();
+	drawLogos(1.0f);
 }
 
 void LLProgressView::setText(const std::string& text)
@@ -309,6 +339,196 @@ void LLProgressView::setMessage(const std::string& msg)
 	getChild<LLUICtrl>("message_text")->setValue(mMessage);
 }
 
+void LLProgressView::loadLogo(const std::string &path,
+                              const U8 image_codec,
+                              const LLRect &pos_rect,
+                              const LLRectf &clip_rect,
+                              const LLRectf &offset_rect)
+{
+    // We need these images very early, so we have to force-load them, otherwise they might not load in time.
+    if (!gDirUtilp->fileExists(path))
+    {
+        return;
+    }
+
+    LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
+    if (!start_image_frmted->load(path))
+    {
+        LL_WARNS("AppInit") << "Image load failed: " << path << LL_ENDL;
+        return;
+    }
+
+    LLPointer<LLImageRaw> raw = new LLImageRaw;
+    if (!start_image_frmted->decode(raw, 0.0f))
+    {
+        LL_WARNS("AppInit") << "Image decode failed " << path << LL_ENDL;
+        return;
+    }
+    // HACK: getLocalTexture allows only power of two dimentions
+    raw->expandToPowerOfTwo();
+
+    TextureData data;
+    data.mTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+    data.mDrawRect = pos_rect;
+    data.mClipRect = clip_rect;
+    data.mOffsetRect = offset_rect;
+    mLogosList.push_back(data);
+}
+
+void LLProgressView::initLogos()
+{
+    mLogosList.clear();
+
+    const U8 image_codec = IMG_CODEC_PNG;
+    const LLRectf default_clip(0.f, 1.f, 1.f, 0.f);
+    const S32 default_height = 28;
+    const S32 default_pad = 15;
+
+    S32 icon_width, icon_height;
+
+    // We don't know final screen rect yet, so we can't precalculate position fully
+    LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl");
+    S32 texture_start_x = logos_label->getFont()->getWidthF32(logos_label->getText()) + default_pad;
+    S32 texture_start_y = -7;
+
+    // Normally we would just preload these textures from textures.xml,
+    // and display them via icon control, but they are only needed on
+    // startup and preloaded/UI ones stay forever
+    // (and this code was done already so simply reused it)
+    std::string temp_str = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "textures", "3p_icons");
+
+    temp_str += gDirUtilp->getDirDelimiter();
+
+#ifdef LL_FMODSTUDIO
+    // original image size is 264x96, it is on longer side but
+    // with no internal paddings so it gets additional padding
+    icon_width = 77;
+    icon_height = 21;
+    S32 pad_y = 4;
+    texture_start_x++;
+    loadLogo(temp_str + "fmod_logo.png",
+        image_codec,
+        LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
+        default_clip,
+        default_clip);
+
+    texture_start_x += icon_width + default_pad + 1;
+#endif
+    // original image size is 342x113, central element is on a larger side
+    // plus internal padding, so it gets slightly more height than desired 32
+    icon_width = 88;
+    icon_height = 29;
+    pad_y = -1;
+    loadLogo(temp_str + "havok_logo.png",
+        image_codec,
+        LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
+        default_clip,
+        default_clip);
+
+    texture_start_x += icon_width + default_pad;
+
+    // 108x41
+    icon_width = 74;
+    loadLogo(temp_str + "vivox_logo.png",
+        image_codec,
+        LLRect(texture_start_x, texture_start_y + default_height, texture_start_x + icon_width, texture_start_y),
+        default_clip,
+        default_clip);
+}
+
+void LLProgressView::initStartTexture(S32 location_id, bool is_in_production)
+{
+    if (gStartTexture.notNull())
+    {
+        gStartTexture = NULL;
+        LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL;
+    }
+
+    LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL;
+
+    U8 image_codec = IMG_CODEC_PNG;
+    std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
+
+    if ((S32)START_LOCATION_ID_LAST == location_id)
+    {
+        temp_str += LLStartUp::getScreenLastFilename();
+    }
+    else
+    {
+        std::string path = temp_str + LLStartUp::getScreenHomeFilename();
+
+        if (!gDirUtilp->fileExists(path) && is_in_production)
+        {
+            // Fallback to old file, can be removed later
+            // Home image only sets when user changes home, so it will take time for users to switch to pngs
+            temp_str += "screen_home.bmp";
+            image_codec = IMG_CODEC_BMP;
+        }
+        else
+        {
+            temp_str = path;
+        }
+    }
+
+    LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
+
+    // Turn off start screen to get around the occasional readback 
+    // driver bug
+    if (!gSavedSettings.getBOOL("UseStartScreen"))
+    {
+        LL_INFOS("AppInit") << "Bitmap load disabled" << LL_ENDL;
+        return;
+    }
+    else if (!start_image_frmted->load(temp_str))
+    {
+        LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL;
+        gStartTexture = NULL;
+    }
+    else
+    {
+        gStartImageWidth = start_image_frmted->getWidth();
+        gStartImageHeight = start_image_frmted->getHeight();
+
+        LLPointer<LLImageRaw> raw = new LLImageRaw;
+        if (!start_image_frmted->decode(raw, 0.0f))
+        {
+            LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
+            gStartTexture = NULL;
+        }
+        else
+        {
+            // HACK: getLocalTexture allows only power of two dimentions
+            raw->expandToPowerOfTwo();
+            gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+        }
+    }
+
+    if (gStartTexture.isNull())
+    {
+        gStartTexture = LLViewerTexture::sBlackImagep;
+        gStartImageWidth = gStartTexture->getWidth();
+        gStartImageHeight = gStartTexture->getHeight();
+    }
+}
+
+void LLProgressView::initTextures(S32 location_id, bool is_in_production)
+{
+    initStartTexture(location_id, is_in_production);
+    initLogos();
+
+    childSetVisible("panel_icons", mLogosList.empty() ? FALSE : TRUE);
+    childSetVisible("panel_top_spacer", mLogosList.empty() ? TRUE : FALSE);
+}
+
+void LLProgressView::releaseTextures()
+{
+    gStartTexture = NULL;
+    mLogosList.clear();
+
+    childSetVisible("panel_top_spacer", TRUE);
+    childSetVisible("panel_icons", FALSE);
+}
+
 void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
 {
 	mCancelBtn->setVisible( b );
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index 813576b21d181b196061fbe17b12ff044b7fddc6..56377a5889d235eee6973220969a1946ecd5b9c9 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -35,6 +35,7 @@
 class LLImageRaw;
 class LLButton;
 class LLProgressBar;
+class LLViewerTexture;
 
 class LLProgressView : 
 	public LLPanel,
@@ -51,6 +52,7 @@ class LLProgressView :
 
 	/*virtual*/ void draw();
 	void drawStartTexture(F32 alpha);
+	void drawLogos(F32 alpha);
 
 	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
@@ -70,6 +72,10 @@ class LLProgressView :
 
 	void setStartupComplete();
 
+	// we have to preload local textures to make sure they won't be grey
+	void initTextures(S32 location_id, bool is_in_production);
+	void releaseTextures();
+
 	void setCancelButtonVisible(BOOL b, const std::string& label);
 
 	static void onCancelButtonClicked( void* );
@@ -95,6 +101,25 @@ class LLProgressView :
 
 	bool handleUpdate(const LLSD& event_data);
 	static void onIdle(void* user_data);
+    void loadLogo(const std::string &path, const U8 image_codec, const LLRect &pos_rect, const LLRectf &clip_rect, const LLRectf &offset_rect);
+    // logos have unusual location and need to be preloaded to not appear grey, then deleted
+    void initLogos();
+    // Loads a bitmap to display during load
+    void initStartTexture(S32 location_id, bool is_in_production);
+
+private:
+    // We need to draw textures on login, but only once.
+    // So this vector gets filled up for textures to render and gets cleaned later
+    // Some textures have unusual requirements, so we are rendering directly
+    class TextureData
+    {
+    public:
+        LLPointer<LLViewerTexture> mTexturep;
+        LLRect mDrawRect;
+        LLRectf mClipRect;
+        LLRectf mOffsetRect;
+    };
+    std::vector<TextureData> mLogosList;
 };
 
 #endif // LL_LLPROGRESSVIEW_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index b532d9a9b4eaa1fb765a45f19827f0b7c78f8c7c..1be1c4ba9661db65d8e18ae4964e2a11be64d8b7 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -39,8 +39,8 @@
 #include "llviewermedia_streamingaudio.h"
 #include "llaudioengine.h"
 
-#ifdef LL_FMODEX
-# include "llaudioengine_fmodex.h"
+#ifdef LL_FMODSTUDIO
+# include "llaudioengine_fmodstudio.h"
 #endif
 
 #ifdef LL_OPENAL
@@ -623,13 +623,13 @@ bool idle_startup()
 			delete gAudiop;
 			gAudiop = NULL;
 
-#ifdef LL_FMODEX		
+#ifdef LL_FMODSTUDIO
 #if !LL_WINDOWS
-			if (NULL == getenv("LL_BAD_FMODEX_DRIVER"))
+            if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER"))
 #endif // !LL_WINDOWS
-			{
-				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable"));
-			}
+            {
+                gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODExProfilerEnable"));
+            }
 #endif
 
 #ifdef LL_OPENAL
@@ -650,7 +650,7 @@ bool idle_startup()
 #else
 				void* window_handle = NULL;
 #endif
-				bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);
+				bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle, LLAppViewer::instance()->getSecondLifeTitle());
 				if(init)
 				{
 					gAudiop->setMuted(TRUE);
@@ -994,9 +994,8 @@ bool idle_startup()
 
 		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
 
-		init_start_screen(agent_location_id);
-
 		// Display the startup progress bar.
+		gViewerWindow->initTextures(agent_location_id);
 		gViewerWindow->setShowProgress(TRUE);
 		gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
 
@@ -2717,81 +2716,6 @@ std::string LLStartUp::getUserId()
     return gUserCredential->userID();
 }
 
-// Loads a bitmap to display during load
-void init_start_screen(S32 location_id)
-{
-	if (gStartTexture.notNull())
-	{
-		gStartTexture = NULL;
-		LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL;
-	}
-
-	LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL;
-
-	U8 image_codec = IMG_CODEC_PNG;
-	std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
-
-	if ((S32)START_LOCATION_ID_LAST == location_id)
-	{
-		temp_str += LLStartUp::getScreenLastFilename();
-	}
-	else
-	{
-		std::string path = temp_str + LLStartUp::getScreenHomeFilename();
-		
-		if (!gDirUtilp->fileExists(path) && LLGridManager::getInstance()->isInProductionGrid())
-		{
-			// Fallback to old file, can be removed later
-			// Home image only sets when user changes home, so it will take time for users to switch to pngs
-			temp_str += "screen_home.bmp";
-			image_codec = IMG_CODEC_BMP;
-		}
-		else
-		{
-			temp_str = path;
-		}
-	}
-
-	LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec);
-
-	// Turn off start screen to get around the occasional readback 
-	// driver bug
-	if(!gSavedSettings.getBOOL("UseStartScreen"))
-	{
-		LL_INFOS("AppInit")  << "Bitmap load disabled" << LL_ENDL;
-		return;
-	}
-	else if(!start_image_frmted->load(temp_str) )
-	{
-		LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL;
-		gStartTexture = NULL;
-	}
-	else
-	{
-		gStartImageWidth = start_image_frmted->getWidth();
-		gStartImageHeight = start_image_frmted->getHeight();
-
-		LLPointer<LLImageRaw> raw = new LLImageRaw;
-		if (!start_image_frmted->decode(raw, 0.0f))
-		{
-			LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
-			gStartTexture = NULL;
-		}
-		else
-		{
-			raw->expandToPowerOfTwo();
-			gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;
-		}
-	}
-
-	if(gStartTexture.isNull())
-	{
-		gStartTexture = LLViewerTexture::sBlackImagep ;
-		gStartImageWidth = gStartTexture->getWidth() ;
-		gStartImageHeight = gStartTexture->getHeight() ;
-	}
-}
-
 
 // frees the bitmap
 void release_start_screen()
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index e197591ef86b7f42c22018420861b4430f4ade1b..c966b7d4f93712af29cdd9e7ca5db60be82f221a 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1902,7 +1902,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
                     // If there is a new music URL and it's valid, play it.
                     if (music_url.size() > 12)
                     {
-                        if (music_url.substr(0, 7) == "http://")
+                        if (music_url.substr(0, 7) == "http://"
+                            || music_url.substr(0, 8) == "https://")
                         {
                             LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
                             optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index f64dfcf0d462f1c98e29a60cbad6cb1415e3c776..44d02b42248fdc847874ad47dcdcb14100b8f339 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -5119,6 +5119,14 @@ void LLViewerWindow::revealIntroPanel()
 	}
 }
 
+void LLViewerWindow::initTextures(S32 location_id)
+{
+    if (mProgressView)
+    {
+        mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInProductionGrid());
+    }
+}
+
 void LLViewerWindow::setShowProgress(const BOOL show)
 {
 	if (mProgressView)
@@ -5172,7 +5180,6 @@ void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string&
 	}
 }
 
-
 LLProgressView *LLViewerWindow::getProgressView() const
 {
 	return mProgressView;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 385bbd57e542d9950f417a569663ebd0abbd1081..44c1fbd066a2ca4e58af80f5f41680ef4727e164 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -303,6 +303,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	BOOL            getCursorHidden() { return mCursorHidden; }
 	void			moveCursorToCenter();								// move to center of window
 													
+	void			initTextures(S32 location_id);
 	void			setShowProgress(const BOOL show);
 	BOOL			getShowProgress() const;
 	void			setProgressString(const std::string& string);
diff --git a/indra/newview/skins/default/textures/3p_icons/fmod_logo.png b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a50e0ad34b54c63357a87094a102ba26d0782d6
Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png differ
diff --git a/indra/newview/skins/default/textures/3p_icons/havok_logo.png b/indra/newview/skins/default/textures/3p_icons/havok_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..ff1ea3a72e8baf13cf235021482f9d57bab2ef08
Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/havok_logo.png differ
diff --git a/indra/newview/skins/default/textures/3p_icons/vivox_logo.png b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f20e87b7ae817116bad7d2939b545cea3029c3e
Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b041e6197cdc9e78b23200262e0adbd6b231b833..7325d836d28f105dfda4a91d9798cca917ef4a0c 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -497,6 +497,7 @@ with the same filename but different name
   <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />
   
   <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
+  <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
   <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
 
   <texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
diff --git a/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec0926bfa1cbc70b172f51704227bc30e418cf6b
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
index a8342e723bc28d35ef6dee32b7d92e55514c7354..d783d1e23c513d060daf3955052644400b88e585 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -2,7 +2,7 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="488"
+ height="466"
  layout="topleft"
  name="Inventory Finder"
  help_topic="inventory_finder"
@@ -202,7 +202,7 @@
      left="8"
      mouse_opaque="true"
      name="icon_settings"
-     top="262"
+     top="242"
      width="16" />
     <check_box
      height="16"
@@ -220,7 +220,7 @@
      layout="topleft"
      left="8"
      name="All"
-     top="282"
+     top="262"
      width="100" />
     <button
      height="20"
@@ -368,6 +368,6 @@
      layout="topleft"
      name="Close"
      right="-6"
-     top="454"
+     top="434"
      width="76" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 860caf2d217a91a117c9c8da05b799f90f8ea7b3..e77d097d5f6db9cbec8669a19ff03b7c44a178d0 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -44,68 +44,129 @@
                  width="670" />
                 <layout_panel
                  auto_resize="false"
-                 height="250"
+                 height="275"
                  layout="topleft"
-                 min_height="250"
+                 min_height="275"
                  name="panel4"
                  width="670">
                     <icon
                      color="LoginProgressBoxCenterColor"
                      follows="left|right|bottom|top"
-                     height="250"
+                     height="275"
                      image_name="Rounded_Square"
                      layout="topleft"
                      left="0"
                      top="0"
                      width="670" />
-                    <text
-                     follows="left|right|top"
-                     font="SansSerifHuge"
-                     font_shadow="none"
-                     halign="left"
-                     height="20"
-                     layout="topleft"
-                     left_delta="47"
-                     name="title_text"
-                     text_color="LoginProgressBoxTextColor"
-                     top_delta="50"
-                     right="-47"/>
-                    <text
-                     follows="left|right|top"
-                     font="SansSerif"
-                     font_shadow="none"
-                     halign="left"
-                     height="20"
-                     layout="topleft"
-                     left_delta="0"
-                     name="progress_text"
-                     text_color="LoginProgressBoxTextColor"
-                     top_pad="5"
-                     right="-47"
-                     word_wrap="true"/>
-                    <progress_bar
-                     bottom="115"
-                     color_bar="1 1 1 0.96"
-                     follows="left|right|top"
-                     height="16"
-                     layout="topleft"
-                     left="45"
-                     name="login_progress_bar"
-                     right="-45" />
-                    <text
+                    <layout_stack
                      follows="left|right|top|bottom"
-                     font="SansSerifLarge"
-                     font_shadow="none"
-                     halign="left"
-                     height="100"
+                     height="275"
                      layout="topleft"
-                     left="45"
-                     line_spacing.pixels="2"
-                     name="message_text"
-                     text_color="LoginProgressBoxTextColor"
-                     top="145"
-                     right="-90"
-                     word_wrap="true"/>
+                     left="0"
+                     orientation="vertical"
+                     name="vertical_centering"
+                     animate="false"
+                     top="0"
+                     width="670">
+                      <layout_panel
+                       auto_resize="false"
+                       height="30"
+                       layout="topleft"
+                       min_height="30"
+                       name="panel_top_spacer"
+                       width="670">
+                      </layout_panel>
+                      <layout_panel
+                       auto_resize="false"
+                       height="100"
+                       layout="topleft"
+                       min_height="100"
+                       name="panel_login"
+                       width="670">
+                        <text
+                         follows="left|right|top"
+                         layout="topleft"
+                         font="SansSerifHuge"
+                         font_shadow="none"
+                         halign="left"
+                         height="20"
+                         left="47"
+                         top="32"
+                         right="-47"
+                         name="title_text"
+                         text_color="LoginProgressBoxTextColor"/>
+                        <text
+                         follows="left|right|top"
+                         layout="topleft"
+                         font="SansSerif"
+                         font_shadow="none"
+                         halign="left"
+                         height="20"
+                         top_pad="5"
+                         right="-47"
+                         left_delta="0"
+                         name="progress_text"
+                         text_color="LoginProgressBoxTextColor"
+                         word_wrap="true"/>
+                        <progress_bar
+                         color_bar="0 0.67 0.9 0.96"
+                         follows="left|right|top"
+                         layout="topleft"
+                         image_fill="ProgressBarSolid"
+                         height="16"
+                         left="45"
+                         top_pad="5"
+                         name="login_progress_bar"
+                         right="-45" />
+                      </layout_panel>
+                      <layout_panel
+                       auto_resize="false"
+                       height="110"
+                       layout="topleft"
+                       min_height="110"
+                       name="panel_motd"
+                       width="670">
+                        <text
+                         follows="left|right|top|bottom"
+                         font="SansSerifLarge"
+                         font_shadow="none"
+                         halign="left"
+                         valign="center"
+                         height="100"
+                         layout="topleft"
+                         left="45"
+                         line_spacing.pixels="2"
+                         name="message_text"
+                         text_color="LoginProgressBoxTextColor"
+                         top="7"
+                         right="-90"
+                         word_wrap="true"/>
+                      </layout_panel>
+                      <layout_panel
+                       auto_resize="false"
+                       height="40"
+                       layout="topleft"
+                       min_height="40"
+                       name="panel_icons"
+                       width="670">
+                        <!--Logos are tied to following label from code-->
+                        <text
+                         follows="left|right|top"
+                         layout="topleft"
+                         font="SansSerifLarge"
+                         font_shadow="none"
+                         halign="left"
+                         height="16"
+                         width="240"
+                         left="47"
+                         top="6"
+                         line_spacing.pixels="2"
+                         name="logos_lbl"
+                         text_color="LoginProgressBoxTextColor">
+                          Second Life uses
+                        </text>
+                      </layout_panel>
+                    </layout_stack>
                 </layout_panel>
                 <layout_panel
                  height="200"
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 41eb40c9984ba12e774f6b974fa5ceb103e27044..b385717dbe9216195ef23d11d294e4db11f1c317 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -516,14 +516,12 @@ 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")
+            # Get fmodstudio dll if needed
+            if self.args['fmodstudio'] == 'ON':
+                if(self.args['configuration'].lower() == 'debug'):
+                    self.path("fmodL.dll")
                 else:
-                    self.path("fmodex.dll")
-            except:
-                print "Skipping fmodex audio library(assuming other audio engine)"
+                    self.path("fmod.dll")
 
             # For textures
             self.path("openjpeg.dll")
@@ -1048,17 +1046,18 @@ def path_optional(src, dst):
                                 ):
                     self.path2basename(relpkgdir, libfile)
 
-                # dylibs that vary based on configuration
-                if self.args['configuration'].lower() == 'debug':
-                    for libfile in (
-                                "libfmodexL.dylib",
-                                ):
-                        dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile)
-                else:
-                    for libfile in (
-                                "libfmodex.dylib",
-                                ):
-                        dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
+                # Fmod studio dylibs (vary based on configuration)
+                if self.args['fmodstudio'] == 'ON':
+                    if self.args['configuration'].lower() == 'debug':
+                        for libfile in (
+                                    "libfmodL.dylib",
+                                    ):
+                            dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile)
+                    else:
+                        for libfile in (
+                                    "libfmod.dylib",
+                                    ):
+                            dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
 
                 # our apps
                 executable_path = {}
@@ -1530,13 +1529,15 @@ def construct(self):
                 print "tcmalloc files not found, skipping"
                 pass
 
-            try:
-                self.path("libfmodex-*.so")
-                self.path("libfmodex.so")
-                pass
-            except:
-                print "Skipping libfmodex.so - not found"
-                pass
+            if self.args['fmodstudio'] == 'ON':
+                try:
+                    self.path("libfmod.so.11.7")
+                    self.path("libfmod.so.11")
+                    self.path("libfmod.so")
+                    pass
+                except:
+                    print "Skipping libfmod.so - not found"
+                    pass
 
 
         # Vivox runtimes
@@ -1566,6 +1567,7 @@ def construct(self):
     extra_arguments = [
         dict(name='bugsplat', description="""BugSplat database to which to post crashes,
              if BugSplat crash reporting is desired""", default=''),
+        dict(name='fmodstudio', description="""Indication if fmod studio libraries are needed""", default='OFF'),
         ]
     try:
         main(extra=extra_arguments)