空间音响 SDK 提供了相应的控制,用于更改您的应用程序将音频从音频源传输到周围空间的方式。它是原生音频插件 SDK 的扩展。
音频源的内置平移是一种简单的空间形式。它获取音频源并根据音频监听器与音频源之间的距离和角度来调节左耳和右耳效应的增益。在水平面上为玩家提供了简洁的方向提示。
为了提供处理音频空间化的灵活性和支持,Unity 提供了一个开放接口,即空间音响 SDK,作为原生音频插件 SDK 之上的扩展。您可以将 Unity 中的标准平移器替换为更高级的平移器,并提供有关计算所需的音频源和监听器的重要元数据的访问权。
有关本机空间音响音频插件的示例,请参阅 Unity 原生音频插件 SDK。此插件仅支持直接的相关传输函数 (Head-Related Transfer Function, HRTF),目的仅限于提供示例。
您可以使用插件随附一个简单的混响,将音频数据从空间音响插件路由到混响插件。HRTF 过滤基于 KEMAR 数据集的修改版本。有关 KEMAR 数据集的更多信息,请参阅麻省理工学院媒体实验室的文档和测量文件。
如果您想探索从人类受试者获得的数据集,请参阅 IRCAM 的数据集。
Unity 在音频源解码音频数据后直接应用空间音响效果。这会产生一个音频数据流,其中每个源都有自己单独的效果实例。Unity 仅处理来自该源的音频及其相应的效果实例。
要使插件作为空间音响工作,需要在效果的描述位字段中设置一个标志:
definition.flags |= UnityAudioEffectDefinitionFlags_IsSpatializer;
如果您设置了 UnityAudioEffectDefinitionFlags_IsSpatializer
标志,Unity 会在插件扫描阶段将插件识别为空间音响。在 Unity 创建此插件的实例时会为 UnityAudioEffectState
结构的 spatializerdata
成员分配 UnityAudioSpatializerData
结构。
要在项目中使用空间音响,请在项目设置中进行选择(菜单:Edit > Project Settings > Audio)。
然后,在要用于空间音响插件的音频源的 Inspector 窗口中,启用 Spatialize:
您也可以使用 AudioSource.spatialize
属性通过 C# 脚本为音频源启用空间音响。
在具有大量音频的游戏中,您可希望仅对附近的声音启用空间音响,而对远处的声音使用传统方案,从而减少空间音响效果的混合线程上的 CPU 负载。
如果您希望 Unity 将空间数据传递给非空间音响的音频混音器插件,可以在描述位字段中使用以下标志:
definition.flags |= UnityAudioEffectDefinitionFlags_NeedsSpatializerData;
如果插件使用 UnityAudioEffectDefinitionFlags_NeedsSpatializerData
标志初始化,该插件将接受 UnityAudioSpatializerData
结构,但仅 listenermatrix
字段有效。有关 UnityAudioSpatializerData 的更多信息,请参阅空间音响效果元数据部分。
要阻止 Unity 替空间音响插件应用距离衰减,请使用以下标志:
definition.flags |= UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation;
UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation
标志告知 Unity 将由空间音响来应用距离衰减。有关距离衰减的更多信息,请参阅衰减曲线和可听度部分。
与在混合声音上运行的其他 Unity 音频效果不同,Unity 在音频源解码音频数据后直接应用空间音响。空间音响效果的每个实例都有一个自身的 UnityAudioSpatializerData
实例,该实例主要与音频源的数据相关联。
struct UnityAudioSpatializerData
{
float listenermatrix[16]; // 此矩阵用于将音频源位置变换为监听器的本地空间
float sourcematrix[16]; // 音频源的变换矩阵
float spatialblend; // 距离控制的空间混合
float reverbzonemix; // 音频源上的混响区混音级别参数
// (和曲线)
float spread; // 音频源的传播参数(0 到 360 度)
float stereopan; // 音频源的立体声平移参数(-1:全左,1:全右)
// 空间音响插件可以重写距离衰减
// 以便影响语音优先级(将此回调保留为 NULL 可使用
// 内置音频源衰减曲线)
UnityAudioEffect_DistanceAttenuationCallback distanceattenuationcallback;
float minDistance; // 音频源的最小距离。
// 该值可用于确定何时应用近场效果。
float maxDistance; // 音频源的最大距离,
// 或监听器听不见音频的距离。
};
该结构包含的字段对应于 Inspector 中音频源组件的属性:Spatial Blend、Reverb Zone Mix、Spread、Stereo Pan、Minimum Distance 和 Maximum Distance。
UnityAudioSpatializerData
结构包含用于音频监听器和音频源的完整 4x4 变换矩阵。已计算监听器矩阵的逆矩阵,因此可将两个矩阵相乘以获得相对方向矢量。监听器矩阵始终是正交的,因此可以快速计算逆矩阵。
Unity 的音频系统仅将原始源声音作为立体声信号提供。即使源是单声道或多声道,信号也是立体声的,并且 Unity 根据需要使用向上或向下混合。
sourcematrix
字段包含与音频源相关联的变换矩阵的副本。对于游戏对象上未旋转的默认音频源,这是一个转换矩阵,在元素 12、13 和 14 位置处编码。
listenermatrix
字段包含音频监听器的变换矩阵的逆矩阵。
您可以确定从音频监听器到音频源的方向矢量,如下所示,其中 L 是 listenermatrix
,S 是sourcematrix
:
float dir_x = L[0] * S[12] + L[4] * S[13] + L[ 8] * S[14] + L[12];
float dir_y = L[1] * S[12] + L[5] * S[13] + L[ 9] * S[14] + L[13];
float dir_z = L[2] * S[12] + L[6] * S[13] + L[10] * S[14] + L[14];
(L[12], L[13], L[14]) 中的位置实际上是您在 Unity 的 Inspector 窗口中看到的摄像机矩阵的负值。如果摄像机也已旋转,您还需要首先撤消旋转的效果。要对变换-旋转矩阵进行求逆,转置 L 的左上角 3x3 旋转矩阵,并按如下所示来计算位置:
float listenerpos_x = -(L[0] * L[12] + L[ 1] * L[13] + L[ 2] * L[14]);
float listenerpos_y = -(L[4] * L[12] + L[ 5] * L[13] + L[ 6] * L[14]);
float listenerpos_z = -(L[8] * L[12] + L[ 9] * L[13] + L[10] * L[14]);
有关空间音响插件代码中的示例,请参阅 Plugin_Spatializer.cpp 文件 中的第 215 行。
除非您按照初始化 Unity 空间音响一节所述指定了 UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation
标志,Unity 音频系统仍将控制距离衰减。Unity 在声音进入空间化阶段之前对其应用距离衰减,并让音频系统知道音频源的近似可听度。音频系统根据重要性使用近似可听度进行声音的动态虚拟化,以匹配用户定义的 Max Real Voices 限制。
Unity 并不从实际信号水平测量中获得可听度信息,而是对应于我们从距离控制衰减曲线、Volume 属性和混音器应用的衰减中读取的值的组合结果。
您可以直接覆盖衰减曲线,或者使用通过音频源的曲线计算出的值作为修改基础。要覆盖该值,使用 UnityAudioSpatializerData
结构中回调,如下所示:
typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK* UnityAudioEffect_DistanceAttenuationCallback)(
UnityAudioEffectState* state,
float distanceIn,
float attenuationIn,
float* attenuationOut);
您也可以使用一个简单的自定义对数曲线,如下所示:
UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SimpleLogAttenuation(
UnityAudioEffectState* state,
float distanceIn,
float attenuationIn,
float* attenuationOut)
{
const float rollOffScale = 1.0f; // 类似于音频项目设置
*attenuationOut = 1.0f / max(1.0f, rollOffScale * distanceIn);
return UNITY_AUDIODSP_OK;
}
音频源中还有两个方法,允许从空间音响效果中设置和获取参数:SetSpatializerFloat
和 GetSpatializerFloat
。这些方法的工作方式类似于通用原生音频插件接口中 SetFloatParameter
和 GetFloatParameter
方法。但是,SetSpatializerFloat
和 GetSpatializerFloat
接受必须设置或读取的参数的索引,而 SetFloatParameter
和 GetFloatParameter
按名称引用这些参数。
在 Unity 的音频源的 Inspector 窗口中,布尔属性 AudioSource.spatializer
链接到 Spatialize 选项。该属性控制 Unity 如何根据音频项目设置中选择的插件来实例化和取消分配空间音响效果。
如果空间音响效果的实例化非常耗费资源(内存或项目中的其他资源),从预设的“池”中分配空间化效果可能是有效的,这样 Unity 就不必在每次需要时创建一个空间音响的新实例。如果您保持 Unity 插件接口绑定非常轻量级并动态分配音响效果,可以避免项目中出现丢帧或其他性能问题。
由于使用了快速卷积算法,快速移动会导致一些拉链瑕疵,这些瑕疵可以通过使用重叠保存卷积或交叉淡化缓冲来消除。
该代码也不支持倾斜监听器的头部,无论监听器是直接连接到玩家角色,还是位于其他地方的摄像机。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.