Skip to content

Commit

Permalink
Merge pull request #27 from AgoraIO/ios-voice-effects
Browse files Browse the repository at this point in the history
Ios voice effects
  • Loading branch information
maxxfrazer authored Nov 28, 2023
2 parents 208cabc + da30314 commit 5871fe3
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 3 deletions.
38 changes: 38 additions & 0 deletions Example-App/Docs-Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
F37BC5B02A964BD500935601 /* AgoraManager+Permissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37BC5AF2A964BD500935601 /* AgoraManager+Permissions.swift */; };
F38269622B0CFE2B00F2E003 /* ScreenShareAndVolumeView+macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38269612B0CFE2A00F2E003 /* ScreenShareAndVolumeView+macOS.swift */; };
F38269642B0CFE9700F2E003 /* ScreenShareAndVolumeView+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38269632B0CFE9700F2E003 /* ScreenShareAndVolumeView+iOS.swift */; };
F382696A2B0F597600F2E003 /* AudioVoiceEffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38269692B0F597600F2E003 /* AudioVoiceEffectsView.swift */; };
F382696F2B0F9C8E00F2E003 /* AINoiseSuppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F382696D2B0F9C8E00F2E003 /* AINoiseSuppView.swift */; };
F38269722B0FA72D00F2E003 /* AINS in Frameworks */ = {isa = PBXBuildFile; productRef = F38269712B0FA72D00F2E003 /* AINS */; };
F38636502AA24392006A8D7C /* ReplayKit in Frameworks */ = {isa = PBXBuildFile; productRef = F386364F2AA24392006A8D7C /* ReplayKit */; };
F38636522AA24392006A8D7C /* RtcBasic in Frameworks */ = {isa = PBXBuildFile; productRef = F38636512AA24392006A8D7C /* RtcBasic */; };
F38636542AA24392006A8D7C /* VirtualBackground in Frameworks */ = {isa = PBXBuildFile; productRef = F38636532AA24392006A8D7C /* VirtualBackground */; };
Expand Down Expand Up @@ -131,6 +134,10 @@
F37BC5AF2A964BD500935601 /* AgoraManager+Permissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AgoraManager+Permissions.swift"; sourceTree = "<group>"; };
F38269612B0CFE2A00F2E003 /* ScreenShareAndVolumeView+macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "ScreenShareAndVolumeView+macOS.swift"; path = "../../../../product-workflow/ScreenShareAndVolumeView+macOS.swift"; sourceTree = "<group>"; };
F38269632B0CFE9700F2E003 /* ScreenShareAndVolumeView+iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "ScreenShareAndVolumeView+iOS.swift"; path = "../../../../product-workflow/ScreenShareAndVolumeView+iOS.swift"; sourceTree = "<group>"; };
F38269692B0F597600F2E003 /* AudioVoiceEffectsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AudioVoiceEffectsView.swift; path = "../../../../audio-and-voice-effects/AudioVoiceEffectsView.swift"; sourceTree = "<group>"; };
F382696C2B0F9C8500F2E003 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = "../../../../audio-and-voice-effects/README.md"; sourceTree = "<group>"; };
F382696D2B0F9C8E00F2E003 /* AINoiseSuppView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AINoiseSuppView.swift; path = "../../../../ai-noise-suppression/AINoiseSuppView.swift"; sourceTree = "<group>"; };
F382696E2B0F9C8E00F2E003 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = "../../../../ai-noise-suppression/README.md"; sourceTree = "<group>"; };
F3A88CCC2A1DE629000B2292 /* GettingStartedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GettingStartedView.swift; path = "../../../../get-started-sdk/GettingStartedView.swift"; sourceTree = "<group>"; };
F3A88CCD2A1DE629000B2292 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = "../../../../get-started-sdk/README.md"; sourceTree = "<group>"; };
F3A88CD12A1DE645000B2292 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = "../../../../ensure-channel-quality/README.md"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -173,6 +180,7 @@
files = (
F3C2054F2AE67EB400736E6F /* SpatialAudio in Frameworks */,
F38636502AA24392006A8D7C /* ReplayKit in Frameworks */,
F38269722B0FA72D00F2E003 /* AINS in Frameworks */,
F38636522AA24392006A8D7C /* RtcBasic in Frameworks */,
F38636542AA24392006A8D7C /* VirtualBackground in Frameworks */,
);
Expand Down Expand Up @@ -312,6 +320,24 @@
path = "virtual-background";
sourceTree = "<group>";
};
F38269682B0F587D00F2E003 /* audio-and-voice-effects */ = {
isa = PBXGroup;
children = (
F382696C2B0F9C8500F2E003 /* README.md */,
F38269692B0F597600F2E003 /* AudioVoiceEffectsView.swift */,
);
path = "audio-and-voice-effects";
sourceTree = "<group>";
};
F382696B2B0F9C6200F2E003 /* ai-noise-suppression */ = {
isa = PBXGroup;
children = (
F382696E2B0F9C8E00F2E003 /* README.md */,
F382696D2B0F9C8E00F2E003 /* AINoiseSuppView.swift */,
);
path = "ai-noise-suppression";
sourceTree = "<group>";
};
F3A88CCA2A1DE5FE000B2292 /* app-stories */ = {
isa = PBXGroup;
children = (
Expand All @@ -325,7 +351,9 @@
F3A88CDF2A1DF27F000B2292 /* product-workflow */,
F3A88CDA2A1DEEE0000B2292 /* custom-video-and-audio */,
F34266572A6AD2660086B920 /* stream-raw-audio-and-video */,
F38269682B0F587D00F2E003 /* audio-and-voice-effects */,
F32F96572AE294840090C560 /* spatial-audio */,
F382696B2B0F9C6200F2E003 /* ai-noise-suppression */,
F31BF86E2A6BB676002E7AC2 /* geofencing */,
F37BC5A42A96149200935601 /* virtual-background */,
);
Expand Down Expand Up @@ -491,6 +519,7 @@
F38636512AA24392006A8D7C /* RtcBasic */,
F38636532AA24392006A8D7C /* VirtualBackground */,
F3C2054E2AE67EB400736E6F /* SpatialAudio */,
F38269712B0FA72D00F2E003 /* AINS */,
);
productName = "Docs-Examples";
productReference = F310F63429C8D02E006DB727 /* Docs-Examples.app */;
Expand Down Expand Up @@ -649,7 +678,9 @@
F32AF89A2A8A9A7B00A27ED1 /* MultiChannelInputView.swift in Sources */,
F3FBDEA32A6BA94A00DAB164 /* ModifyAudioFrameDelegate.swift in Sources */,
F31BF8712A6BB69A002E7AC2 /* GeofencingView.swift in Sources */,
F382696F2B0F9C8E00F2E003 /* AINoiseSuppView.swift in Sources */,
F3D7BD4729DB30680014DEC0 /* AgoraManager.swift in Sources */,
F382696A2B0F597600F2E003 /* AudioVoiceEffectsView.swift in Sources */,
F344EDA02A496FF400B3C313 /* AgoraCustomVideoCanvasView.swift in Sources */,
F37BC5B02A964BD500935601 /* AgoraManager+Permissions.swift in Sources */,
F3A88CCE2A1DE629000B2292 /* GettingStartedView.swift in Sources */,
Expand Down Expand Up @@ -842,6 +873,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -881,6 +913,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -995,6 +1028,11 @@
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
F38269712B0FA72D00F2E003 /* AINS */ = {
isa = XCSwiftPackageProductDependency;
package = F386364E2AA24392006A8D7C /* XCRemoteSwiftPackageReference "AgoraRtcEngine_iOS" */;
productName = AINS;
};
F386364F2AA24392006A8D7C /* ReplayKit */ = {
isa = XCSwiftPackageProductDependency;
package = F386364E2AA24392006A8D7C /* XCRemoteSwiftPackageReference "AgoraRtcEngine_iOS" */;
Expand Down
8 changes: 6 additions & 2 deletions Example-App/Docs-Examples/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,15 @@ struct ContentView: View {
NavigationLink("Integrate an extension") {}.disabled(true)
}
Section("Integrate Features") {
NavigationLink("Audio and voice effects") {}.disabled(true)
NavigationLink(AudioVoiceEffectsView.docTitle) {
ChannelInputView(continueTo: AudioVoiceEffectsView.self)
}
NavigationLink(SpatialAudioView.docTitle) {
ChannelInputView(continueTo: SpatialAudioView.self)
}
NavigationLink("AI Noise Suppression") {}.disabled(true)
NavigationLink(AINoiseSuppView.docTitle) {
ChannelInputView(continueTo: AINoiseSuppView.self)
}
NavigationLink(GeofencingView.docTitle) {
GeofenceInputView(continueTo: GeofencingView.self)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ extension CallQualityView: HasChannelInput {}
extension ScreenShareAndVolumeView: HasChannelInput {}
extension RawMediaProcessingView: HasChannelInput {}
extension VirtualBackgroundView: HasChannelInput {}
extension AudioVoiceEffectsView: HasChannelInput {}
extension SpatialAudioView: HasChannelInput {}
extension AINoiseSuppView: HasChannelInput {}

/// A view that takes a user inputted `channelId` string and navigates to a view
/// which conforms to the `HasChannelInput` protocol.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ extension CallQualityView: AgoraStoryViewProtocol {}
extension ScreenShareAndVolumeView: AgoraStoryViewProtocol {}
extension CustomAudioVideoView: AgoraStoryViewProtocol {}
extension RawMediaProcessingView: AgoraStoryViewProtocol {}
extension AudioVoiceEffectsView: AgoraStoryViewProtocol {}
extension SpatialAudioView: AgoraStoryViewProtocol {}
extension AINoiseSuppView: AgoraStoryViewProtocol {}
extension GeofencingView: AgoraStoryViewProtocol {}
extension VirtualBackgroundView: AgoraStoryViewProtocol {}
Empty file.
69 changes: 69 additions & 0 deletions ai-noise-suppression/AINoiseSuppView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import SwiftUI
import AgoraRtcKit

class NoiseSuppressionManager: AgoraManager {
@discardableResult
func setNoiseSuppression(_ enable: Bool, mode: AUDIO_AINS_MODE) -> Int32 {
self.agoraEngine.setAINSMode(enable, mode: mode)
}
}

enum AinsModes: String {
case none
case aggressive
case balanced
case ultraLowLatency
var agoraCase: AUDIO_AINS_MODE? {
switch self {
case .none: nil
case .aggressive: AUDIO_AINS_MODE.AINS_MODE_AGGRESSIVE
case .balanced: AUDIO_AINS_MODE.AINS_MODE_BALANCED
case .ultraLowLatency: AUDIO_AINS_MODE.AINS_MODE_ULTRALOWLATENCY
}
}
}

/// A view that encrypts your channel connection through Agora.
struct AINoiseSuppView: View {
/// The Agora SDK manager.
@ObservedObject var agoraManager = NoiseSuppressionManager(
appId: DocsAppConfig.shared.appId, role: .broadcaster
)
@State var ainsMode: AinsModes = .none

var body: some View {
ZStack {
VStack {
self.basicScrollingVideos
Picker("Choose Noise Suppression", selection: $ainsMode) {
ForEach([
AinsModes.none, .balanced, .aggressive, .ultraLowLatency
], id: \.rawValue) { Text($0.rawValue).tag($0) }
}.pickerStyle(SegmentedPickerStyle())
}.onChange(of: ainsMode) { newValue in
if let agoraCase = newValue.agoraCase {
self.agoraManager.setNoiseSuppression(true, mode: agoraCase)
} else {
self.agoraManager.setNoiseSuppression(false, mode: .AINS_MODE_BALANCED)
}
}
ToastView(message: $agoraManager.label)
}.onAppear {
await agoraManager.joinChannel(DocsAppConfig.shared.channel)
}.onDisappear { agoraManager.leaveChannel() }
}

/// Initializes a new `MediaEncryptionView`.
///
/// - Parameters:
/// - channelId: The channel ID to join.
public init(channelId: String) {
DocsAppConfig.shared.channel = channelId
}
static let docPath = getFolderName(from: #file)
static let docTitle = LocalizedStringKey("ai-noise-suppression-title")
}

#Preview {
AINoiseSuppView(channelId: "test")
}
31 changes: 31 additions & 0 deletions ai-noise-suppression/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# AI noise suppression

Agora's AI Noise Suppression, enables you to suppress hundreds of types of noise and reduce distortion in human voices when multiple people speak at the same time. In scenarios such as online meetings, online chat rooms, video consultations with doctors, and online gaming, AI Noise Suppression makes virtual communication as smooth as face-to-face interaction.

AI Noise Suppression reduces the following types of noise:

* Television
* Kitchen
* Street, such as birds chirping, traffic, and subway sounds
* Machine, such as fans, air conditioners, vacuum cleaners, and copiers
* Office, such as keyboard and mouse clicks
* Household, such as doors opening, creaking chairs, crying babies, and house renovations
* Constant knocking
* Beeps and clapping
* Music

This sample project shows you how to enable AI noise suppression in your client.

## Understand the code

For context on this sample, and a full explanation of the essential code snippets used in this project, read the **AI Noise Suppression** document for your product of interest:

* [Video calling](https://docs.agora.io/en/video-calling/enable-features/ai-noise-suppression?platform=ios)
* [Interactive live Streaming](https://docs.agora.io/en/interactive-live-streaming/enable-features/ai-noise-suppression?platform=ios)
* [Broadcast streaming](https://docs.agora.io/en/broadcast-streaming/enable-features/ai-noise-suppression?platform=ios)

For the UI implementation of this example, refer to [`AINoiseSuppView.swift`](./AINoiseSuppView.swift).

## How to run this example

To see how to run this example, refer to the [README](../README.md) in the root folder or one of the complete product guides.
Loading

0 comments on commit 5871fe3

Please sign in to comment.