diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 13adc131bf134a7b27183a53612d9f74969b67a9..a68ff67be6aa929047f442d06a0dae7785500d57 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -2,6 +2,17 @@
 <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="llsd.xsd">
   <map>
+    <key>AlchemyLinuxVoiceVariant</key>
+    <map>
+      <key>Comment</key>
+      <string>0 - native, 1 - 32bit wine voice, 2 - 64bit wine voice</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>2</integer>
+    </map>
     <key>AlchemyAutoAcceptAllInventory</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index a8aabe579c14f3aa543ac69f18ccb7e7e0c5c16e..ad94b5d10cdf90ebcf0600045c1cf3fe98a75b5e 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -112,6 +112,18 @@ if [[ !(-u $SANDBOX_BIN) || (-w $SANDBOX_BIN) || !(-x $SANDBOX_BIN) || !(-r $SAN
     pkexec "$SCRIPT_DIR/etc/chrome_sandboxing_permissions_setup.sh"
 fi
 
+#setup wine voice
+if [ -x "$(command -v wine)" ]; then
+    export WINEDEBUG=-all # disable all debug output for wine
+    export WINEPREFIX="$HOME/.alchemynext/wine"
+    if [ ! -d "$WINEPREFIX" ]; then
+        DISPLAY="" wine hostname
+    fi
+else
+    export VIEWER_DISABLE_WINE=1
+    echo "Please install wine to enable full voice functionality."
+fi
+
 # Run the program.
 # Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the
 # command line. But DO quote "${ARGS[@]}": preserve separate args as
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index ed8b9c2c0968b74a8302c38d8046dba2cf9141cd..6f65655ab5385928493cebcd818b719508f16bda 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -513,6 +513,29 @@ bool LLVivoxVoiceClient::writeString(const std::string &str)
 	return result;
 }
 
+enum class EWineMode{ eNoWine, e32Bit, e64Bit };
+EWineMode viewerUsesWineForVoice()
+{
+#ifndef LL_LINUX
+    return EWineMode::eNoWine;
+#else
+    static auto* disable_wine = getenv("VIEWER_DISABLE_WINE");
+    if(disable_wine != nullptr) return EWineMode::eNoWine;
+
+    static LLCachedControl<U32> sVoiceVariant(gSavedSettings, "AlchemyLinuxVoiceVariant", 2);
+	if(sVoiceVariant >= 2)
+		return EWineMode::e64Bit;
+	else if(sVoiceVariant >= 1)
+		return EWineMode::e32Bit;
+
+    return EWineMode::eNoWine;
+#endif
+}
+
+bool viewerChoosesConnectionHandles()
+{
+    return viewerUsesWineForVoice() != EWineMode::eNoWine;
+}
 
 /////////////////////////////
 // session control messages
@@ -528,16 +551,21 @@ void LLVivoxVoiceClient::connectorCreate()
         vivoxLogLevel = "0";
     }
     LL_DEBUGS("Voice") << "creating connector with log level " << vivoxLogLevel << LL_ENDL;
-	
+
+    // Check if using the old SLVoice for Linux. the SDK in that version is too old to handle the extra args
+    std::string strConnectorHandle;
+    if(viewerChoosesConnectionHandles())
+    {
+        strConnectorHandle = "<ConnectorHandle>" + LLVivoxSecurity::getInstance()->connectorHandle() + "</ConnectorHandle>";
+    }
+
 	stream 
 	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.Create.1\">"
 		<< "<ClientName>V2 SDK</ClientName>"
 		<< "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>"
 		<< "<Mode>Normal</Mode>"
+        << strConnectorHandle
         << (gSavedSettings.getBOOL("VoiceMultiInstance") ? "<MinimumPort>30000</MinimumPort><MaximumPort>50000</MaximumPort>" : "")
-#ifndef LL_LINUX
-        << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
-#endif
 		<< "<Logging>"
 		<< "<Folder>" << logdir << "</Folder>"
 		<< "<FileNamePrefix>Connector</FileNamePrefix>"
@@ -935,7 +963,18 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
         gDirUtilp->append(exe_path, "SLVoice");
 #else
         std::string exe_path = gDirUtilp->getExecutableDir();
-        gDirUtilp->append(exe_path, "SLVoice");
+        switch( viewerUsesWineForVoice() )
+        {
+            case EWineMode::eNoWine:
+                gDirUtilp->append(exe_path, "SLVoice"); // native version
+                break;
+            case EWineMode::e32Bit:
+                gDirUtilp->append(exe_path, "win32/SLVoice.exe"); // use bundled win32 version
+                break;
+            case EWineMode::e64Bit:
+                gDirUtilp->append(exe_path, "win64/SLVoice.exe"); // use bundled win64 version
+                break;
+        }
 #endif
         // See if the vivox executable exists
         llstat s;
@@ -943,8 +982,17 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
         {
             // vivox executable exists.  Build the command line and launch the daemon.
             LLProcess::Params params;
+
             params.executable = exe_path;
 
+            if( EWineMode::eNoWine == viewerUsesWineForVoice()  )
+                params.executable = exe_path;
+            else
+            {
+                params.executable = "wine";
+                params.args.add( exe_path );
+            }
+
             std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
             if (loglevel.empty())
             {
@@ -1002,15 +1050,17 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
 
             params.cwd = gDirUtilp->getAppRODataDir();
 
-#ifndef LL_LINUX
-#           ifdef VIVOX_HANDLE_ARGS
-            params.args.add("-ah");
-            params.args.add(LLVivoxSecurity::getInstance()->accountHandle());
+            // Check if using the old SLVoice for Linux. the SDK in that version is too old to handle the extra args
+            if( viewerChoosesConnectionHandles() ) 
+			{
+#               ifdef VIVOX_HANDLE_ARGS
+                params.args.add("-ah");
+                params.args.add(LLVivoxSecurity::getInstance()->accountHandle());
 
-            params.args.add("-ch");
-            params.args.add(LLVivoxSecurity::getInstance()->connectorHandle());
-#           endif // VIVOX_HANDLE_ARGS
-#endif
+                params.args.add("-ch");
+                params.args.add(LLVivoxSecurity::getInstance()->connectorHandle());
+#               endif // VIVOX_HANDLE_ARGS
+            } 
 
             params.postend = sGatewayPump.getName();
             sGatewayPump.listen("VivoxDaemonPump", boost::bind(&LLVivoxVoiceClient::callbackEndDaemon, this, _1));
@@ -2536,14 +2586,19 @@ void LLVivoxVoiceClient::loginSendMessage()
 
 	bool autoPostCrashDumps = gSavedSettings.getBOOL("VivoxAutoPostCrashDumps");
 
+    // Check if using the old SLVoice for Linux. the SDK in that version is too old to handle the extra args
+    std::string strAccountHandle;
+    if(viewerChoosesConnectionHandles())
+    {
+        strAccountHandle = "<AccountHandle>" +  LLVivoxSecurity::getInstance()->accountHandle() + "</AccountHandle>";
+    }
+
 	stream
 	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Login.1\">"
 		<< "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
 		<< "<AccountName>" << mAccountName << "</AccountName>"
         << "<AccountPassword>" << mAccountPassword << "</AccountPassword>"
-#ifndef LL_LINUX
-        << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
-#endif
+        << strAccountHandle
 		<< "<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>"
 		<< "<EnableBuddiesAndPresence>false</EnableBuddiesAndPresence>"
 		<< "<EnablePresencePersistence>0</EnablePresencePersistence>"
@@ -3608,39 +3663,43 @@ void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &st
 
 	if(statusCode == 0)
 	{
-#ifndef LL_LINUX
 		// Connector created, move forward.
-        if (connectorHandle == LLVivoxSecurity::getInstance()->connectorHandle())
+        // Check if using the old SLVoice for Linux. the SDK in that version is too old to handle the extra args
+        if( viewerChoosesConnectionHandles() ) 
+        {
+            if (connectorHandle == LLVivoxSecurity::getInstance()->connectorHandle())
+            {
+                LL_INFOS("Voice") << "Voice connector succeeded, Vivox SDK version is " << versionID << " connector handle " << connectorHandle << LL_ENDL;
+                mVoiceVersion.serverVersion = versionID;
+                mConnectorEstablished = true;
+                mTerminateDaemon = false;
+
+                result["connector"] = LLSD::Boolean(true);
+            }
+            else
+            {
+                // This shouldn't happen - we are somehow out of sync with SLVoice
+                // or possibly there are two things trying to run SLVoice at once
+                // or someone is trying to hack into it.
+                LL_WARNS("Voice") << "Connector returned wrong handle "
+                                    << "(" << connectorHandle << ")"
+                                    << " expected (" << LLVivoxSecurity::getInstance()->connectorHandle() << ")"
+                                    << LL_ENDL;
+                result["connector"] = LLSD::Boolean(false);
+                // Give up.
+                mTerminateDaemon = true;
+            }
+		} 
+        else 
         {
-            LL_INFOS("Voice") << "Voice connector succeeded, Vivox SDK version is " << versionID << " connector handle " << connectorHandle << LL_ENDL;
+            LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
             mVoiceVersion.serverVersion = versionID;
+            LLVivoxSecurity::getInstance()->setConnectorHandle(connectorHandle);
             mConnectorEstablished = true;
             mTerminateDaemon = false;
 
             result["connector"] = LLSD::Boolean(true);
-        }
-        else
-        {
-            // This shouldn't happen - we are somehow out of sync with SLVoice
-            // or possibly there are two things trying to run SLVoice at once
-            // or someone is trying to hack into it.
-            LL_WARNS("Voice") << "Connector returned wrong handle "
-                              << "(" << connectorHandle << ")"
-                              << " expected (" << LLVivoxSecurity::getInstance()->connectorHandle() << ")"
-                              << LL_ENDL;
-            result["connector"] = LLSD::Boolean(false);
-            // Give up.
-            mTerminateDaemon = true;
-        }
-#else
-        LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
-        mVoiceVersion.serverVersion = versionID;
-        LLVivoxSecurity::getInstance()->setConnectorHandle(connectorHandle);
-        mConnectorEstablished = true;
-        mTerminateDaemon = false;
- 
-        result["connector"] = LLSD::Boolean(true);
-#endif
+		}
 	}
     else if (statusCode == 10028) // web request timeout prior to login
     {
@@ -3690,9 +3749,13 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString
 	else
 	{
 		// Login succeeded, move forward.
-#ifdef LL_LINUX
-        LLVivoxSecurity::getInstance()->setAccountHandle(accountHandle);
-#endif
+
+        // Check if voice too old for this
+        if(!viewerChoosesConnectionHandles())
+        {
+            LLVivoxSecurity::getInstance()->setAccountHandle(accountHandle);
+        }
+
 		mAccountLoggedIn = true;
 		mNumberOfAliases = numberOfAliases;
         result["login"] = LLSD::String("response_ok");
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index fca77bc8a3911f8d236da894e5b901ed0396b273..89c69bf0ed48d1d653baab176b4aed23f59d3482 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1316,6 +1316,8 @@ def construct(self):
         # Vivox runtimes
         with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="bin"):
             self.path("SLVoice")
+            self.path("win32")
+            self.path("win64")
 
             # Sentry
             if self.args['sentry'] == 'ON' or self.args['sentry'] == 'TRUE':
@@ -1361,6 +1363,8 @@ def construct(self):
         # Vivox runtimes
         with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="bin"):
             self.path("SLVoice")
+            self.path("win32")
+            self.path("win64")
 
             # Sentry
             if self.args['sentry'] == 'ON' or self.args['sentry'] == 'TRUE':