diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 944c00b6e..46b833b73 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -2021,6 +2021,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_group_call_screen_share_start" = "Share Screen";
 "lng_group_call_screen_share_stop" = "Stop Sharing";
 "lng_group_call_screen_title" = "Screen {index}";
+"lng_group_call_screen_share_audio" = "Share Audio";
 "lng_group_call_unmute_small" = "Unmute";
 "lng_group_call_more" = "More";
 "lng_group_call_unmute" = "Unmute";
diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style
index 19a4fca8e..eaa14ba75 100644
--- a/Telegram/SourceFiles/calls/calls.style
+++ b/Telegram/SourceFiles/calls/calls.style
@@ -1184,6 +1184,16 @@ desktopCaptureSubmit: RoundButton(desktopCaptureCancel) {
 		color: shadowFg;
 	}
 }
+desktopCaptureWithAudio: Checkbox(defaultCheckbox) {
+	textFg: groupCallMembersFg;
+	textFgActive: groupCallMembersFg;
+	rippleBg: groupCallMembersBgRipple;
+	rippleBgActive: groupCallMembersBgRipple;
+	style: semiboldTextStyle;
+}
+desktopCaptureWithAudioCheck: Check(defaultCheck) {
+	untoggledFg: groupCallActiveFg;
+}
 
 groupCallNarrowSkip: 9px;
 groupCallNarrowMembersWidth: 204px;
diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp
index 80cc29975..e13b853d0 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp
+++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp
@@ -613,6 +613,10 @@ QString GroupCall::screenSharingDeviceId() const {
 	return isSharingScreen() ? _screenDeviceId : QString();
 }
 
+bool GroupCall::screenSharingWithAudio() const {
+	return isSharingScreen() && _screenWithAudio;
+}
+
 bool GroupCall::mutedByAdmin() const {
 	const auto mute = muted();
 	return mute == MuteState::ForceMuted || mute == MuteState::RaisedHand;
@@ -635,7 +639,9 @@ void GroupCall::toggleVideo(bool active) {
 		: Webrtc::VideoState::Inactive;
 }
 
-void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
+void GroupCall::toggleScreenSharing(
+		std::optional<QString> uniqueId,
+		bool withAudio) {
 	if (!_instance || !_id) {
 		return;
 	} else if (!uniqueId) {
@@ -645,10 +651,14 @@ void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
 	const auto changed = (_screenDeviceId != *uniqueId);
 	const auto wasSharing = isSharingScreen();
 	_screenDeviceId = *uniqueId;
+	_screenWithAudio = withAudio;
 	_screenState = Webrtc::VideoState::Active;
 	if (changed && wasSharing && isSharingScreen()) {
 		_screenCapture->switchToDevice(uniqueId->toStdString());
 	}
+	if (_screenInstance) {
+		_screenInstance->setIsMuted(!withAudio);
+	}
 }
 
 bool GroupCall::hasVideoWithFrames() const {
@@ -2281,9 +2291,7 @@ bool GroupCall::tryCreateScreencast() {
 	_screenInstance = std::make_unique<tgcalls::GroupInstanceCustomImpl>(
 		std::move(descriptor));
 
-#ifdef Q_OS_WIN
-	_screenInstance->setIsMuted(false);
-#endif // Q_OS_WIN
+	_screenInstance->setIsMuted(!_screenWithAudio);
 
 	return true;
 }
diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h
index 64c49901a..4d23110c5 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_call.h
+++ b/Telegram/SourceFiles/calls/group/calls_group_call.h
@@ -380,8 +380,11 @@ public:
 	[[nodiscard]] bool isCameraPaused() const;
 	[[nodiscard]] const std::string &cameraSharingEndpoint() const;
 	[[nodiscard]] QString screenSharingDeviceId() const;
+	[[nodiscard]] bool screenSharingWithAudio() const;
 	void toggleVideo(bool active);
-	void toggleScreenSharing(std::optional<QString> uniqueId);
+	void toggleScreenSharing(
+		std::optional<QString> uniqueId,
+		bool withAudio = false);
 	[[nodiscard]] bool hasVideoWithFrames() const;
 	[[nodiscard]] rpl::producer<bool> hasVideoWithFramesValue() const;
 
@@ -614,6 +617,7 @@ private:
 	rpl::variable<Webrtc::VideoState> _screenState;
 	rpl::variable<bool> _isSharingScreen = false;
 	QString _screenDeviceId;
+	bool _screenWithAudio = false;
 
 	base::flags<SendUpdateType> _pendingSelfUpdates;
 	bool _requireARGB32 = true;
diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
index 022b0f299..eef148ca2 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
+++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp
@@ -260,12 +260,26 @@ QString Panel::chooseSourceActiveDeviceId() {
 	return _call->screenSharingDeviceId();
 }
 
+bool Panel::chooseSourceActiveWithAudio() {
+	return _call->screenSharingWithAudio();
+}
+
+bool Panel::chooseSourceWithAudioSupported() {
+#ifdef Q_OS_WIN
+	return true;
+#else // Q_OS_WIN
+	return false;
+#endif // Q_OS_WIN
+}
+
 rpl::lifetime &Panel::chooseSourceInstanceLifetime() {
 	return lifetime();
 }
 
-void Panel::chooseSourceAccepted(const QString &deviceId) {
-	_call->toggleScreenSharing(deviceId);
+void Panel::chooseSourceAccepted(
+		const QString &deviceId,
+		bool withAudio) {
+	_call->toggleScreenSharing(deviceId, withAudio);
 }
 
 void Panel::chooseSourceStop() {
@@ -1185,7 +1199,7 @@ void Panel::chooseShareScreenSource() {
 			if (_call->isSharingScreen()) {
 				_call->toggleScreenSharing(std::nullopt);
 			} else {
-				chooseSourceAccepted(*source);
+				chooseSourceAccepted(*source, false);
 			}
 		} else {
 			Ui::DesktopCapture::ChooseSource(this);
diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.h b/Telegram/SourceFiles/calls/group/calls_group_panel.h
index e1cd8dad3..4cfc3bbcb 100644
--- a/Telegram/SourceFiles/calls/group/calls_group_panel.h
+++ b/Telegram/SourceFiles/calls/group/calls_group_panel.h
@@ -169,8 +169,12 @@ private:
 
 	QWidget *chooseSourceParent() override;
 	QString chooseSourceActiveDeviceId() override;
+	bool chooseSourceActiveWithAudio() override;
+	bool chooseSourceWithAudioSupported() override;
 	rpl::lifetime &chooseSourceInstanceLifetime() override;
-	void chooseSourceAccepted(const QString &deviceId) override;
+	void chooseSourceAccepted(
+		const QString &deviceId,
+		bool withAudio) override;
 	void chooseSourceStop() override;
 
 	const not_null<GroupCall*> _call;
diff --git a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp
index 2203195b0..76f301e78 100644
--- a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp
+++ b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "ui/widgets/scroll_area.h"
 #include "ui/widgets/labels.h"
 #include "ui/widgets/buttons.h"
+#include "ui/widgets/checkbox.h"
 #include "ui/effects/ripple_animation.h"
 #include "ui/image/image.h"
 #include "ui/platform/ui_platform_window_title.h"
@@ -62,6 +63,8 @@ public:
 
 	[[nodiscard]] rpl::producer<> activations() const;
 	void setActive(bool active);
+	[[nodiscard]] bool isWindow() const;
+	[[nodiscard]] QString deviceIdKey() const;
 	[[nodiscard]] rpl::lifetime &lifetime();
 
 private:
@@ -94,6 +97,7 @@ private:
 	void setupGeometryWithParent(not_null<QWidget*> parent);
 	void fillSources();
 	void setupSourcesGeometry();
+	void updateButtonsVisibility();
 	void destroy();
 
 	static base::flat_map<
@@ -107,6 +111,7 @@ private:
 	const not_null<RpWidget*> _bottom;
 	const not_null<RoundButton*> _submit;
 	const not_null<RoundButton*> _finish;
+	const not_null<Checkbox*> _withAudio;
 
 	std::vector<std::unique_ptr<Source>> _sources;
 	Source *_selected = nullptr;
@@ -166,6 +171,14 @@ rpl::producer<> Source::activations() const {
 	return _activations.events();
 }
 
+bool Source::isWindow() const {
+	return _source.isWindow();
+}
+
+QString Source::deviceIdKey() const {
+	return QString::fromStdString(_source.deviceIdKey());
+}
+
 void Source::setActive(bool active) {
 	if (_active != active) {
 		_active = active;
@@ -255,7 +268,13 @@ ChooseSourceProcess::ChooseSourceProcess(
 	CreateChild<RoundButton>(
 		_bottom.get(),
 		tr::lng_group_call_screen_share_stop(),
-		st::desktopCaptureFinish)) {
+		st::desktopCaptureFinish))
+, _withAudio(
+	CreateChild<Checkbox>(
+		_bottom.get(),
+		tr::lng_group_call_screen_share_audio(tr::now),
+		false,
+		st::desktopCaptureWithAudio)) {
 	setupPanel();
 	setupSources();
 	activate();
@@ -336,7 +355,9 @@ void ChooseSourceProcess::setupPanel() {
 			return;
 		}
 		const auto weak = MakeWeak(_window.get());
-		_delegate->chooseSourceAccepted(_selectedId);
+		_delegate->chooseSourceAccepted(
+			_selectedId,
+			!_withAudio->isHidden() && _withAudio->checked());
 		if (const auto strong = weak.data()) {
 			strong->close();
 		}
@@ -375,6 +396,18 @@ void ChooseSourceProcess::setupPanel() {
 			bottomSkip);
 	}, _bottom->lifetime());
 
+	_withAudio->widthValue(
+	) | rpl::start_with_next([=](int width) {
+		const auto top = (bottomHeight - _withAudio->heightNoMargins()) / 2;
+		_withAudio->moveToLeft(bottomSkip, top);
+	}, _withAudio->lifetime());
+
+	_withAudio->setChecked(_delegate->chooseSourceActiveWithAudio());
+	_withAudio->checkedChanges(
+	) | rpl::start_with_next([=] {
+		updateButtonsVisibility();
+	}, _withAudio->lifetime());
+
 	const auto sharing = !_delegate->chooseSourceActiveDeviceId().isEmpty();
 	_finish->setVisible(sharing);
 	_submit->setVisible(!sharing);
@@ -420,6 +453,8 @@ void ChooseSourceProcess::fillSources() {
 	auto screensManager = tgcalls::DesktopCaptureSourceManager(Type::Screen);
 	auto windowsManager = tgcalls::DesktopCaptureSourceManager(Type::Window);
 
+	_withAudio->setVisible(false);
+
 	auto screenIndex = 0;
 	auto windowIndex = 0;
 	const auto active = _delegate->chooseSourceActiveDeviceId();
@@ -435,9 +470,13 @@ void ChooseSourceProcess::fillSources() {
 		const auto id = source.deviceIdKey();
 		_sources.push_back(std::make_unique<Source>(_inner, source, title));
 
+		const auto withAudioSupported = !source.isWindow()
+			&& _delegate->chooseSourceWithAudioSupported();
+
 		const auto raw = _sources.back().get();
 		if (!active.isEmpty() && active.toStdString() == id) {
 			_selected = raw;
+			_withAudio->setVisible(withAudioSupported);
 			raw->setActive(true);
 		}
 		_sources.back()->activations(
@@ -448,15 +487,8 @@ void ChooseSourceProcess::fillSources() {
 				_selected->setActive(false);
 			}
 			_selected = raw;
-			_selectedId = QString::fromStdString(id);
-			if (_selectedId == _delegate->chooseSourceActiveDeviceId()) {
-				_selectedId = QString();
-				_finish->setVisible(true);
-				_submit->setVisible(false);
-			} else {
-				_finish->setVisible(false);
-				_submit->setVisible(true);
-			}
+			_withAudio->setVisible(withAudioSupported);
+			updateButtonsVisibility();
 		}, raw->lifetime());
 	};
 	for (const auto &source : screensManager.sources()) {
@@ -467,6 +499,27 @@ void ChooseSourceProcess::fillSources() {
 	}
 }
 
+void ChooseSourceProcess::updateButtonsVisibility() {
+	const auto withAudioSupported = _selected
+		&& !_selected->isWindow()
+		&& _delegate->chooseSourceWithAudioSupported();
+	const auto selectedId = _selected
+		? _selected->deviceIdKey()
+		: QString();
+	if (selectedId == _delegate->chooseSourceActiveDeviceId()
+		&& (!withAudioSupported
+			|| (_withAudio->checked()
+				== _delegate->chooseSourceActiveWithAudio()))) {
+		_selectedId = QString();
+		_finish->setVisible(true);
+		_submit->setVisible(false);
+	} else {
+		_selectedId = selectedId;
+		_finish->setVisible(false);
+		_submit->setVisible(true);
+	}
+}
+
 void ChooseSourceProcess::setupSourcesGeometry() {
 	if (_sources.empty()) {
 		destroy();
diff --git a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.h b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.h
index 82f0fb9e5..03da88a46 100644
--- a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.h
+++ b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.h
@@ -20,8 +20,12 @@ class ChooseSourceDelegate {
 public:
 	virtual QWidget *chooseSourceParent() = 0;
 	virtual QString chooseSourceActiveDeviceId() = 0;
+	virtual bool chooseSourceActiveWithAudio() = 0;
+	virtual bool chooseSourceWithAudioSupported() = 0;
 	virtual rpl::lifetime &chooseSourceInstanceLifetime() = 0;
-	virtual void chooseSourceAccepted(const QString &deviceId) = 0;
+	virtual void chooseSourceAccepted(
+		const QString &deviceId,
+		bool withAudio) = 0;
 	virtual void chooseSourceStop() = 0;
 };
 
diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls
index 3cf1822a7..07e0484a5 160000
--- a/Telegram/ThirdParty/tgcalls
+++ b/Telegram/ThirdParty/tgcalls
@@ -1 +1 @@
-Subproject commit 3cf1822a70e3b84f6a762755e5249b26e915d321
+Subproject commit 07e0484a583121870316f3039aa2047ed030cd6d
diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake
index d513b1ce3..02456b144 100644
--- a/Telegram/cmake/lib_tgcalls.cmake
+++ b/Telegram/cmake/lib_tgcalls.cmake
@@ -49,9 +49,13 @@ PRIVATE
     Message.h
     NetworkManager.cpp
     NetworkManager.h
+    SctpDataChannelProviderInterfaceImpl.cpp
+    SctpDataChannelProviderInterfaceImpl.h
     StaticThreads.cpp
     StaticThreads.h
     ThreadLocalObject.h
+    TurnCustomizerImpl.cpp
+    TurnCustomizerImpl.h
     VideoCaptureInterface.cpp
     VideoCaptureInterface.h
     VideoCaptureInterfaceImpl.cpp
diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc
index 5d16a97b5..3bd9b94e9 160000
--- a/Telegram/lib_webrtc
+++ b/Telegram/lib_webrtc
@@ -1 +1 @@
-Subproject commit 5d16a97b57f0399d552e0c9dd72d27e81f6a8316
+Subproject commit 3bd9b94e928b2ce963290d773926240ec2612d6a
diff --git a/docs/building-msvc-x64.md b/docs/building-msvc-x64.md
index dc8808ebb..5b19175c2 100644
--- a/docs/building-msvc-x64.md
+++ b/docs/building-msvc-x64.md
@@ -110,9 +110,9 @@ Open **x64 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
     cmake --build . --config Release
     cd ..
 
-    git clone https://github.com/kcat/openal-soft.git
+    git clone https://github.com/telegramdesktop/openal-soft.git
     cd openal-soft
-    git checkout openal-soft-1.21.0
+    git checkout wasapi_exact_device_time
     cd build
     cmake .. ^
         -G "Visual Studio 16 2019" ^
diff --git a/docs/building-msvc.md b/docs/building-msvc.md
index 7c91562ed..155c6768c 100644
--- a/docs/building-msvc.md
+++ b/docs/building-msvc.md
@@ -110,9 +110,9 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
     cmake --build . --config Release
     cd ..
 
-    git clone https://github.com/kcat/openal-soft.git
+    git clone https://github.com/telegramdesktop/openal-soft.git
     cd openal-soft
-    git checkout openal-soft-1.21.0
+    git checkout wasapi_exact_device_time
     cd build
     cmake .. ^
         -G "Visual Studio 16 2019" ^