空间音效
声网为电子竞技、在线会议等场景提供空间音效功能,让用户拥有沉浸式的音频体验。
- 通过更新用户的空间位置,用户可以实时感受到其他用户距离、方位、朝向的变化。
- 通过更新媒体播放器的空间位置,用户可以为背景音、伴奏等媒体资源增添空间感。
- 通过设置参数,体验声音模糊、空气衰减等效果。
空间音效功能当前处于实验阶段,请联系 sales@shengwang.cn 开通空间音效功能,如果需要技术支持,请联系技术支持。
技术原理
用户的空间音效
声网为用户提供本地直角坐标系计算方案设置空间音效:
使用 ILocalSpatialAudioEngine
类实现空间音效,通过 SDK 计算本地用户与远端用户的相对位置。你需要分别调用 updateSelfPosition
和 updateRemotePosition
更新本地和远端用户的空间坐标,本地用户才能听到远端用户的空间音效。
媒体播放器的空间音效
声网为媒体播放器提供本地直角坐标系计算方案设置空间音效:
通过 SDK 计算本地用户和媒体播放器的相对位置。你需要在 ILocalSpatialAudioEngine
类中分别调用 updateSelfPosition
和 updatePlayerPositionInfo
更新本地用户和媒体播放器的空间坐标,本地用户才能听到媒体播放器的空间音效。
前提条件
- 在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。
- 当用户在空间音效场景下使用蓝牙耳机时,需确保使用 A2DP 传输协议,即:仅使用蓝牙耳机进行音频播放,同时使用其他设备进行音频采集。否则,会导致用户上麦时自己无法听到空间音效。
实现方法
用户的空间音效
该方案通过 ILocalSpatialAudioEngine
类实现空间音效,API 调用时序与操作步骤如下:
-
在调用其他声网 API 前,先后调用
IRtcEngine
类的createAgoraRtcEngine
和initialize
并填入你的 App ID,初始化IRtcEngine
对象。 -
在调用
ILocalSpatialAudioEngine
类的其他 API 前,调用ILocalSpatialAudioEngine
类的initialize
初始化ILocalSpatialAudioEngine
对象。 -
调用
setAudioProfile
,将profile
(音频编码属性)设置为你想要的编码属性,将scenario
(音频应用场景)设置为AUDIO_SCENARIO_GAME_STREAMING
。 -
调用带
options
参数的joinChannel
加入频道(使用 RTC Token)。你需要在ChannelMediaOptions
中设置channelProfile
(频道场景)为CHANNEL_PROFILE_LIVE_BROADCASTING
(直播场景)、clientRoleType
(用户角色)为CLIENT_ROLE_BROADCASTER
(主播)。 -
声网默认订阅所有远端用户的音频流,你需要调用
IRtcEngine
的muteAllRemoteAudioStreams(true)
取消订阅所有远端用户,否则你在步骤 6 中设置的音频接收范围会无效。 -
设置音频接收范围:
- 调用
setMaxAudioRecvCount
设置音频接收范围内最多可接收的音频流数。 - 调用
setAudioRecvRange
设置音频接收范围(米)。
- 调用
-
先后调用
updateSelfPosition
和updateRemotePosition
更新本地和远端用户的空间位置,体验空间音效。 -
如果无需体验空间音效,则调用
clearRemotePositions
删除所有远端用户的空间位置信息。删除后,本地用户会听不到所有远端用户。 -
调用
ILocalSpatialAudioEngine
的release
销毁ILocalSpatialAudioEngine
对象。注意必须在调用
IRtcEngine
的release
前销毁ILocalSpatialAudioEngine
对象。 -
调用
IRtcEngine
的leaveChannel
和release
离开频道并销毁IRtcEngine
对象。
媒体播放器的空间音效
该方案通过 ILocalSpatialAudioEngine
类中的 updateSelfPosition
和 updatePlayerPositionInfo
实现空间音效。以 ILocalSpatialAudioEngine
类为例,操作步骤如下:
-
在调用其他声网 API 前,先后调用
IRtcEngine
类的createAgoraRtcEngine
和initialize
并填入你的 App ID,初始化IRtcEngine
对象。 -
在调用
ILocalSpatialAudioEngine
类的其他 API 前,调用initialize
初始化ILocalSpatialAudioEngine
对象。 -
调用
setAudioProfile
设置profile
(音频编码属性)为AUDIO_PROFILE_DEFAULT
、scenario
(音频应用场景)为AUDIO_SCENARIO_GAME_STREAMING
。 -
调用带
options
参数的joinChannel
加入频道(使用 RTC Token)。你需要在ChannelMediaOptions
中设置channelProfile
(频道场景)为CHANNEL_PROFILE_LIVE_BROADCASTING
(直播场景)、clientRoleType
(用户角色)为CLIENT_ROLE_BROADCASTER
(主播)。 -
声网默认订阅所有远端用户的音频流,你需要调用
IRtcEngine
的muteAllRemoteAudioStreams(true)
取消订阅所有远端用户,否则你在步骤 6 中设置的音频接收范围会无效。 -
调用下列方法,设置音频接收范围:
- 调用
setMaxAudioRecvCount
设置音频接收范围内最多可接收的音频流数。 - 调用
setAudioRecvRange
设置音频接收范围(米)。
- 调用
-
先后调用
updateSelfPosition
和updatePlayerPositionInfo
更新本地用户和媒体播放器的空间位置,体验空间音效。 -
调用
ILocalSpatialAudioEngine
的release
销毁ILocalSpatialAudioEngine
对象。注意必须在调用
IRtcEngine
的release
前销毁ILocalSpatialAudioEngine
对象。 -
调用
IRtcEngine
的release
销毁IRtcEngine
对象。
示例代码
本节展示使用本地球坐标系计算方案实现用户空间音效的示例代码:
bool CAgoraSpatialAudioDlg::InitAgora()
{
// 创建 IRtcEngine
m_rtcEngine = createAgoraRtcEngine();
RtcEngineContext context;
std::string strAppID = GET_APP_ID;
context.appId = strAppID.c_str();
context.eventHandler = &m_eventHandler;
// 初始化 IRtcEngine
int ret = m_rtcEngine->initialize(context);
// 设置频道场景
m_rtcEngine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING);
// 设置用户角色
m_rtcEngine->setClientRole(CLIENT_ROLE_BROADCASTER);
// 加入频道
ChannelMediaOptions options;
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
options.clientRoleType = CLIENT_ROLE_BROADCASTER;
m_rtcEngine->joinChannel("Your token", szChannelId.c_str(), 0, options);
// 开启空间音效
m_rtcEngine->enableSpatialAudio(true);
}
void CAgoraSpatialAudioDlg::UnInitAgora()
{
if (m_rtcEngine) {
if (m_joinChannel)
// 离开频道
m_joinChannel = !m_rtcEngine->leaveChannel();
// 销毁 IRtcEngine
m_rtcEngine->release(true);
m_rtcEngine = NULL;
}
}
// 开启媒体播放器的空间音效
void CAgoraSpatialAudioDlg::SetSpatialAudioParam()
{
POINT ptLocal = { rcLocal.left + localWidth / 2.0f,rcLocal.top + localWidth / 2.0f };
POINT ptRemote = { rcRemote.left + remoteWidth / 2.0f,rcRemote.top + remoteWidth / 2.0f };
SpatialAudioParams spatial_audio_params;
int deltaX = ptRemote.x - ptLocal.x;
int deltaY = ptLocal.y - ptRemote.y;
int tanAngle = 0;
float tanValue = 1;
if (deltaX == 0) {
if (deltaY > 0)
tanAngle = 360;
else if (deltaY < 0)
tanAngle = 180;
}else{
tanValue = fabs(deltaY) / fabs(deltaX);
tanAngle = atan(tanValue) * 180.0 / 3.1415926;
}
int spatialAngle = 0.0;
if (deltaX > 0 && deltaY > 0) {
spatialAngle = 270.0 + tanAngle;
}
else if (deltaX < 0 && deltaY > 0) {
spatialAngle = 90.0 - tanAngle;
}
else if (deltaX < 0 && deltaY < 0) {
spatialAngle = 90.0 + tanAngle;
}
else if (deltaX > 0 && deltaY < 0) {
spatialAngle = 270.0 - tanAngle;
}
CString str;
str.Format(_T("%d\n"), spatialAngle);
OutputDebugString(str);
int spatialDistance = sqrt(deltaX*deltaX + deltaY * deltaY) / distanceRate;
spatial_audio_params.speaker_distance = 0;
spatial_audio_params.speaker_azimuth = spatialAngle;
spatial_audio_params.speaker_elevation = 0;
spatial_audio_params.speaker_orientation = 0;
m_rtcEngine->setRemoteUserSpatialAudioParams(uid, spatial_audio_params);
}
}
相关文档
示例项目
声网在 GitHub 上提供开源的示例项目 SpatialAudio。你可以前往下载,或查看其中的源代码。