Agora provides spatial audio effects to give users an immersive audio experience in scenarios such as esports competitions and online conferences.
Agora provides users with local Cartesian coordinate system calculation solution:
This solution uses the AgoraLocalSpatialAudioKit
class to implement spatial audio effects, and calculates the relative position of the local user and the remote user through the SDK. You need to call updateSelfPosition
and updateRemotePosition
to update the spatial coordinates of the local and remote users respectively, so that the local user can hear the remote user's spatial audio effects.
Agora provides media player with local Cartesian coordinate system calculation solution:
This solution calculates the relative positions of the local user and the media player through the SDK. You need to call updateSelfPosition
and updatePlayerPositionInfo
in the AgoraLocalSpatialAudioKit
classes respectively to update the spatial coordinates of the local user and the media player, so that the local user can hear the spatial audio effect of the media player.
This solution implements spatial audio effect through the AgoraLocalSpatialAudioKit
class. The API call sequence and operation steps are as follows:
Before calling other Agora APIs, call sharedEngineWithAppId
and fill in your App ID to initialize the AgoraRtcEngineKit
object.
Before calling other APIs of the AgoraLocalSpatialAudioKit
class, call sharedLocalSpatialAudioWithConfig
to initialize the AgoraLocalSpatialAudioKit
object.
Call setAudioProfile
to set the profile
parameter to AgoraAudioProfileDefault
and the scenario
to AgoraAudioScenarioGameStreaming
.
Call joinChannelByToken
with the mediaOptions
parameter to join channel (using RTC Token). Set channelProfile
to AgoraChannelProfileLiveBroadcasting
and clientRoleType
to AgoraClientRoleBroadcaster
in AgoraRtcChannelMediaOptions
.
Agora subscribes to the audio streams of all remote users by default. You need to call muteAllRemoteAudioStreams(true)
of AgoraRtcEngineKit
to unsubscribe all remote users, otherwise the audio reception range you set in step 6 will be invalid.
Call the following method to set the audio reception range:
setMaxAudioRecvCount
to set the maximum number of audio streams that a user can receive in a specified audio reception range.setAudioRecvRange
to set the audio reception range (meters) of the local user.setDistanceUnit
to set the length (meters) of the game engine unit distance.You need to call updateSelfPosition
and updateRemotePosition
to update the spatial coordinates of the local and the remote users successively, so that the local user can hear the remote user's spatial audio effects.
If you do not need to experience spatial audio effects, call clearRemotePositions
to delete the spatial position information of all remote users. After the deletion, the local user cannot hear all remote users.
Call destroy
of AgoraLocalSpatialAudioKit
to destroy the AgoraLocalSpatialAudioKit
object.
AgoraLocalSpatialAudioKit
object must be destroyed before calling destroy
of the AgoraRtcEngineKit
.Call leaveChannel
and destroy
of the AgoraRtcEngineKit
class to leave the channel and destroy the AgoraRtcEngineKit
object.
This solution implements spatial audio effect through the updateSelfPosition
and updatePlayerPositionInfo
in the AgoraLocalSpatialAudioKit
class. Taking the AgoraLocalSpatialAudioKit
class as an example, the operation steps are as follows:
Before calling other Agora APIs, call sharedEngineWithAppId
and fill in your App ID to initialize the AgoraRtcEngineKit
object.
Before calling other APIs of the AgoraLocalSpatialAudioKit
class, call sharedLocalSpatialAudioWithConfig
to initialize the AgoraLocalSpatialAudioKit
object.
Call setAudioProfile
to set the profile
to AgoraAudioProfileDefault
and the scenario
to AgoraAudioScenarioGameStreaming
.
Call joinChannelByToken
with the mediaOptions
parameter to join channel (using RTC Token). Set channelProfile
to AgoraChannelProfileLiveBroadcasting
and clientRoleType
to AgoraClientRoleBroadcaster
in AgoraRtcChannelMediaOptions
.
Agora subscribes to the audio streams of all remote users by default. You need to call muteAllRemoteAudioStreams(true)
of AgoraRtcEngineKit
to unsubscribe all remote users, otherwise the audio reception range you set in step 6 will be invalid.
Call the following method to set the audio reception range:
setMaxAudioRecvCount
to set the maximum number of audio streams that a user can receive in a specified audio reception range.setAudioRecvRange
to set the audio reception range (meters) of the local user.setDistanceUnit
to set the length (meters) of the game engine unit distance.You need to call updateSelfPosition
and updateRemotePosition
to update the spatial coordinates of the local and the remote users successively, so that the local user can hear the remote user's spatial audio effects.
Call destroy
of AgoraLocalSpatialAudioKit
to destroy the AgoraLocalSpatialAudioKit
object.
AgoraLocalSpatialAudioKit
object must be destroyed before calling destroy
of the AgoraRtcEngineKit
.Call destroy
of the AgoraRtcEngineKit
to destroy the AgoraRtcEngineKit
object.
This section shows sample code that uses the local Cartesian coordinate system calculation solution to implement the spatial audio effects for the media player:
// Swift
class SpatialAudioMain: BaseViewController {
var agoraKit: AgoraRtcEngineKit!
var mediaPlayer: AgoraRtcMediaPlayerProtocol!
var localSpatial: AgoraLocalSpatialAudioKit!
override func viewDidLoad() {
// Initialize the AgoraRtcEngineKit
agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: KeyCenter.AppId, delegate: self)
// Set the channel profile as liveBroadcasting
config.channelProfile = .liveBroadcasting
// Set the client role as the host.
agoraKit.setClientRole(.broadcaster)
// Set audio profile and scenario
agoraKit.setAudioProfile(.default, scenario: .gameStreaming)
guard let filePath = Bundle.main.path(forResource: "audiomixing", ofType: "mp3") else {return}
// Create a media player
mediaPlayer = agoraKit.createMediaPlayer(with: self)
// Opens a media resource
mediaPlayer.open(filePath, startPos: 0)
// Initialize the AgoraLocalSpatialAudioKit
let localSpatialConfig = AgoraLocalSpatialAudioConfig()
localSpatialConfig.rtcEngine = agoraKit
localSpatial = AgoraLocalSpatialAudioKit.sharedLocalSpatialAudio(with: localSpatialConfig)
// Set the audio reception range (meters)
localSpatial.setAudioRecvRange(50)
// Set the length (meters) of the game engine distance per unit.
localSpatial.setDistanceUnit(1)
// Updates the spatial position of the local user.
let pos = [NSNumber(0.0), NSNumber(0), NSNumber(0.0)]
let forward = [NSNumber(1.0), NSNumber(0.0), NSNumber(0.0)]
let right = [NSNumber(0.0), NSNumber(1.0), NSNumber(0.0)]
let up = [NSNumber(0.0), NSNumber(0.0), NSNumber(1.0)]
self.localSpatial.updateSelfPosition(pos, axisForward: forward, axisRight: right, axisUp: up)
}
override func willMove(toParent parent: UIViewController?) {
if parent == nil {
// Destroy the AgoraLocalSpatialAudioKit
AgoraLocalSpatialAudioKit.destroy()
// Destroy the AgoraRtcEngineKit object.
AgoraRtcEngineKit.destroy()
}
}
// Updates the spatial position of the media player.
func updateRemoteUserSpatialAudioPositon() {
let maxR = UIScreen.main.bounds.height / 2.0
let maxSpatailDistance = 30.0
let spatialDistance = currentDistance * maxSpatailDistance / maxR
let posForward = spatialDistance * cos(currentAngle);
let posRight = spatialDistance * sin(currentAngle);
let position = [NSNumber(value: posForward), NSNumber(value: posRight), NSNumber(0.0)]
let forward = [NSNumber(1.0), NSNumber(0.0), NSNumber(0.0)]
let positionInfo = AgoraRemoteVoicePositionInfo()
positionInfo.position = position
positionInfo.forward = forward
localSpatial.updatePlayerPositionInfo(mediaPlayer.getMediaPlayerId(), positionInfo);
}
}
Agora provides an open source sample project SpatialAudio on GitHub. You can download the sample project to try it out or refer to the source code.