空间音响 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)):
然后,在要用于空间音响插件的音频源的检视面板窗口中,启用空间化 (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]; // Matrix that transforms sourcepos into the local space of the listener
float sourcematrix[16]; // Transform matrix of the Audio Source
float spatialblend; // Distance-controlled spatial blend
float reverbzonemix; // Reverb zone mix level parameter (and curve) on
// the Audio Source
float spread; // Spread parameter of the Audio Source (0..360 degrees)
float stereopan; // Stereo panning parameter of the Audio Source (-1: fully left, 1: fully right)
// The spatializer plugin may override the distance attenuation to
// influence the voice prioritization (leave this callback as NULL
// to use the built-in Audio Source attenuation curve)
UnityAudioEffect_DistanceAttenuationCallback distanceattenuationcallback;
float minDistance; // The minimum distance of the Audio Source.
// This value may be useful for determining when to apply near-field effects.
float maxDistance; // The maximum distance of the Audio Source, or the
// distance where the audio becomes inaudible to the listener.
};
该结构包含的字段对应于检视面板中音频源组件的属性:空间混合 (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 的检视面板窗口中看到的摄像机矩阵的负值。如果摄像机也已旋转,您还需要首先撤消旋转的效果。要对变换-旋转矩阵进行求逆,转置 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; // Similar to the one in the Audio Project Settings
*attenuationOut = 1.0f / max(1.0f, rollOffScale * distanceIn);
return UNITY_AUDIODSP_OK;
}
音频源中还有两个方法,允许从空间音响效果中设置和获取参数:SetSpatializerFloat 和 GetSpatializerFloat。这些方法的工作方式类似于通用原生音频插件接口中 SetFloatParameter 和 GetFloatParameter 方法。但是,SetSpatializerFloat 和 GetSpatializerFloat 会为其必须设置或读取的参数创建索引,而 SetFloatParameter 和 GetFloatParameter 会按名称引用参数。
在 Unity 的音频源检视面板窗口中,布尔属性 AudioSource.spatializer 链接到空间化 (Spatialize) 选项。该属性控制 Unity 如何根据音频项目设置中选择的插件来实例化和取消分配空间音响效果。
如果空间音响效果的实例化非常耗费资源(内存或项目中的其他资源),从预设的“池”中分配空间化效果可能是有效的,这样 Unity 就不必在每次需要时创建一个空间音响的新实例。如果您保持 Unity 插件接口绑定非常轻量级并动态分配音频效果,可以避免项目中出现丢帧或其他性能问题。
由于使用了快速卷积算法,快速移动会导致一些拉链瑕疵,这些瑕疵可以通过使用重叠保存卷积或交叉淡化缓冲来消除。
该代码也不支持倾斜监听器的头部,无论监听器是直接连接到玩家角色,还是位于其他地方的摄像机。