From a2b7184916b48983940c6fc3c19ffeb33621d988 Mon Sep 17 00:00:00 2001 From: Pavel Prystinka Date: Mon, 20 Jan 2025 09:39:38 -0800 Subject: [PATCH 1/2] spike raw audio --- .../CallingSDKWrapper.swift | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift b/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift index 10adcff3d..691b03f06 100644 --- a/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift +++ b/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift @@ -23,6 +23,8 @@ class CallingSDKWrapper: NSObject, CallingSDKWrapperProtocol { private var callKitRemoteInfo: CallKitRemoteInfo? private var callingSDKInitializer: CallingSDKInitializer + var rawIncomingAudioStream: RawIncomingAudioStream? + init(logger: Logger, callingEventsHandler: CallingSDKEventsHandling, callConfiguration: CallConfiguration, @@ -117,6 +119,37 @@ class CallingSDKWrapper: NSObject, CallingSDKWrapperProtocol { throw CallCompositeInternalError.callJoinFailed } + let audioStreamOptions = RawIncomingAudioStreamOptions() + let properties = RawIncomingAudioStreamProperties() + properties.format = .pcm16Bit + properties.sampleRate = .hz44100 + properties.channelMode = .stereo + audioStreamOptions.properties = properties + + let incomingAudioOptions = IncomingAudioOptions() + + self.rawIncomingAudioStream = RawIncomingAudioStream(options: audioStreamOptions) + incomingAudioOptions.stream = self.rawIncomingAudioStream + + joinCallOptions.incomingAudioOptions = incomingAudioOptions + + self.rawIncomingAudioStream?.events.onMixedAudioBufferReceived = { args in + // Receive raw audio buffers(AVAudioPCMBuffer) and process them using AVAudioEngine API's. + + guard let audioBuffer = args.audioBuffer.buffer as? AVAudioPCMBuffer else { + print("No audio data received") + return + } + // Process audioBuffer + print("RA frameLength \(audioBuffer.frameLength)") + print("RA frameCapacity \(audioBuffer.frameCapacity)") + print("RA format \(audioBuffer.format)") + } + + self.rawIncomingAudioStream?.events.onStateChanged = { _ in + // To be notified when stream started and stopped. + } + do { let callAgent = try await callingSDKInitializer.setupCallAgent() let joinedCall = try await callAgent.join(with: joinLocator, joinCallOptions: joinCallOptions) From 4ea7f2d7a51240e97d01f701b8665273064b3acb Mon Sep 17 00:00:00 2001 From: Pavel Prystinka Date: Tue, 21 Jan 2025 16:48:58 -0800 Subject: [PATCH 2/2] add player --- .../CallingSDKWrapper.swift | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift b/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift index 691b03f06..26dca27a3 100644 --- a/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift +++ b/AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Service/Calling/AzureCommunicationCalling/CallingSDKWrapper.swift @@ -12,6 +12,8 @@ import Foundation // swiftlint:disable type_body_length class CallingSDKWrapper: NSObject, CallingSDKWrapperProtocol { + let audioPlayer = AudioPlayer() + let callingEventsHandler: CallingSDKEventsHandling private let logger: Logger @@ -144,6 +146,8 @@ class CallingSDKWrapper: NSObject, CallingSDKWrapperProtocol { print("RA frameLength \(audioBuffer.frameLength)") print("RA frameCapacity \(audioBuffer.frameCapacity)") print("RA format \(audioBuffer.format)") + + self.audioPlayer.playAudioBuffer(audioBuffer) } self.rawIncomingAudioStream?.events.onStateChanged = { _ in @@ -719,3 +723,32 @@ extension CallingSDKWrapper: DeviceManagerDelegate { return videoStream } } + +class AudioPlayer { + private let audioEngine = AVAudioEngine() + private let playerNode = AVAudioPlayerNode() + + init() { + audioEngine.attach(playerNode) + audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: nil) + } + + func playAudioBuffer(_ buffer: AVAudioBuffer) { + if let pcmBuffer = buffer as? AVAudioPCMBuffer { + playPCMBuffer(pcmBuffer) + } else { + print("Unable to play: Buffer is not compatible") + } + } + + private func playPCMBuffer(_ buffer: AVAudioPCMBuffer) { + playerNode.scheduleBuffer(buffer, at: nil, options: .loops, completionHandler: nil) + do { + try audioEngine.start() + playerNode.play() + } catch { + print("Error starting audio engine: \(error.localizedDescription)") + } + } + +}