实现分段线性封套效果

分段线性包络 (PWLE) 效应是定义振动频率和加速度随时间变化的点的序列。PWLE 可提供更丰富、更动态的触感反馈。

Android 16 及更高版本提供了两个应用开发者 API 来帮助创建 PWLE 效果:

  • 基本 PWLE API:简单,但有局限性。适合快速入门。您可以在 BasicEnvelopeBuilder 中找到此功能。
  • 高级 PWLE API:提供更强的控制力和灵活性,但需要具备触感知识并对硬件有一定的了解。可在 WaveformEnvelopeBuilder 上使用。

为了支持这些 API,设备必须实现以下 HAL API:

  • 频次与输出加速度的映射 (FOAM):提供振动频次与设备可实现的最大输出加速度的映射。
  • Compose PWLE:播放由振动波形的 PWLE 定义的振动。

基本 PWLE API

如需快速创建 PWLE 效果,而无需深入了解硬件或人类感知的细微差别,开发者可以使用基本 PWLE API,该 API 使用以下参数定义:

  • 范围为 [0, 1] 的强度值表示感知到的振动强度。例如,0.5 值表示设备可达到的全局最大强度的二分之一。
  • 范围为 [0, 1] 的清晰度值表示振动的清晰度。值越低,振动越平缓;值越高,振动越强烈。
  • 时长是指从上一个 PWLE 点(即强度和清晰度对)过渡到新点所用的时间(以毫秒为单位)。

以下是一个波形示例,它在 500 毫秒内将强度从低音调逐渐增加到高音调的最大强度振动,然后在 100 毫秒内逐渐减小到 0(关闭):

VibrationEffect effect = new VibrationEffect.BasicEnvelopeBuilder()
          .setInitialSharpness(0.0f)
          .addControlPoint(1.0f, 1.0f, 500)
          .addControlPoint(0.0f, 1.0f, 100)
          .build();

约束条件

为了打造顺畅无缝的触感体验,PWLE 效果必须以 0.0 的强度开始和结束。该 API 通过将起始强度固定为 0 来强制执行此操作,如果结束强度不为 0,则会抛出异常。此限制可防止因振幅不连续而导致振动中出现不良动态效果,从而避免对用户的触感感知产生负面影响。

为了确保在整个 Android 生态系统中实现一致的 PWLE 效果呈现,框架要求支持此功能的设备能够处理 PWLE 点之间至少 10 毫秒的最小时长,并至少支持 16 个 PWLE 效果点。这些要求通过 VTS 测试强制执行,有助于确保在各种 Android 设备上实现可靠的 PWLE 效果。

高级 PWLE API

在触感方面具有丰富知识的开发者可以使用以下条件定义 PWLE 效果:

  • 范围为 [0, 1] 的振幅值表示在给定频率下可实现的强度,由设备 FOAM 确定。例如,0.5 的值会生成在给定频率下可实现的最大输出加速度的一半。
  • 频次直接以赫兹为单位指定。
  • 时长是指从上一个 PWLE 点过渡到新点所用的时间(以毫秒为单位)。

以下是一个波形示例,它会在 100 毫秒内将振动器从关闭状态以 120 Hz 的频率逐渐调至最大振幅,保持该状态 200 毫秒,然后在 100 毫秒内逐渐调回:

VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
          .addControlPoint(1.0f, 120f, 100)
          .addControlPoint(1.0f, 120f, 200)
          .addControlPoint(0.0f, 120f, 100)
          .build();

约束条件

框架不会修改开发者提供的请求的频率和振幅值,但会添加 0 振幅起始点,以确保平稳过渡。

开发者有责任确保其 PWLE 效果中指定的频次在设备支持的范围内(由设备的 FOAM 定义)。如果值超出这些限制,设备不会播放任何振动。

频次与输出加速度的映射关系 (FOAM)

准确表示设备的频次与输出加速度功能对于支持 PWLE API 至关重要。本部分详细介绍了此数据的重要性、PWLE API 如何使用此数据以及生成此数据的过程。

了解映射

支持 PWLE 效果的设备需要提供频次到输出加速度映射 (FOAM)。FOAM 是由 HAL 生成的数据结构,用于将振动频率(以赫兹为单位)映射到致动器在该频率下可实现的最大输出加速度(以 G 峰值为单位)。此映射对于了解支持的频率范围内的振动输出如何变化以及定义基本 PWLE API 至关重要。

下图显示了典型谐振致动器的 FOAM 示例,其中输入电压在谐振频率附近受到限制,以保护电机:

示例
FOAM

图 1. 典型谐振致动器的 FOAM 示例。

FOAM 有以下三个主要用途:

  • 定义完整频段:FOAM 通过指定支持的最小和最大振动频率来定义设备的完整频段。
  • 定义强度和清晰度值:基本 PWLE API 基于人类对强度和清晰度的感知度进行操作,然后使用 FOAM 中的输出加速度值将其映射到硬件频率和振幅参数。此映射有助于确保根据硬件功能呈现触感效果。清晰度范围由可感知的最低阈值定义,对应于设备可以产生用户可感知的触感效果的频率。该框架会根据所选频率下的目标输出加速度将强度值映射到振幅。这有助于确保在设备能力范围内达到所选的强度级别。
  • 公开硬件功能:FOAM 在 VibratorFrequencyProfile 中向开发者公开,提供完整的频率来输出加速度数据集,详细说明设备的某些触感反馈功能。借助这些数据,使用高级 PWLE API 的开发者可以创建超出框架定义的基本强度和清晰度范围的自定义振动效果。

FOAM 和基本 PWLE API

FOAM 在塑造振动效果方面发挥着至关重要的作用。它用于计算基本包络线 API 的清晰度范围,确保用户可以感知到振动。此范围对应的频率是指输出加速度高于人类感知检测阈值(即可感知的最低水平)至少 10 dB 的频率。这样可确保振动足够强,能够被感知到。

此外,该框架还使用 FOAM 数据将基本 PWLE API 中使用的强度和清晰度值映射到相应的振幅和频率值。此映射有助于在不同设备上产生可感知的触感反馈。

VTS 测试旨在确保支持包络效应的设备具有可产生可感知振动的非空频段。这有助于确保设备能够产生足够强度的振动,以便用户清晰地感受到。

FOAM 和高级 PWLE API

FOAM 通过 VibratorFrequencyProfile 向开发者公开,其中包含以下信息:

开发者可以在使用高级 PWLE API 创建包络效果时使用此信息。例如,当指定输出加速度(以 G 为单位)时,必须将其归一化为 [0.0, 1.0] 范围内的值,相对于设备的最大输出加速度。

借助高级 PWLE API,开发者可以使用整个频率范围,因此提供的 FOAM 数据对于振动器来说必须是安全的,并且不得超出其能力范围。

人类感知检测阈值

人类感知检测阈值是指人能够可靠检测到的振动的最小加速度。此级别因振动频率而异。

下图显示了人类触觉感知检测阈值1(以加速度表示)与时间频率的关系:

人类触觉感知检测阈值

图 2. 人类触感感知检测阈值。

为了让用户能够始终如一地感受到触感反馈效果,VTS 测试会验证具有包络功能的设备是否具有可产生振动幅度的频率范围,该振动幅度超出人类感知检测阈值 10 dB。

感知到的振动强度与振动加速度振幅

人类对振动强度的感知(一种感知度量)不会随着振动幅度(一种物理参数)线性增长。PWLE API 假定,当设计者或开发者考虑振动强度变化时,他们希望感知到的强度遵循 PWLE。感知强度以感觉级 (SL) 为特征,定义为在相同频率下高于检测阈值的 dB。因此,振动加速度振幅(以 G 峰值表示)的计算方式如下:

\(Amplitude(G) =10^\frac{Amplitude(db)}{20}\)

其中,振幅(分贝)是特定频率下的声源强度和检测阈值(以下图表中纵坐标上的值)之和。

这样一来,PWLE API 即可确保感知强度在连续的控制点对之间呈线性变化。

下图显示了在 10、20、30、40 和 50 dB SL 下的振动加速度水平2,以及人类触觉感知检测阈值(0 dB SL),它们都是时间频率的函数。

振动加速度级别

图 3. 振动加速度级别。

确定达到最大输出的加速度曲线的频率

本部分提供了一般性指南,介绍如何从设备获取频次与最大输出加速度曲线,以便您使用该曲线生成 FOAM 数据。

获取最大电压曲线 (V)

V 是在振动器的工作频率范围内可安全施加到振动器的最大电压。这样可确保振动器在安全范围内运行,防止损坏并最大限度地提高振动输出。

如果硬件包含电压限制功能,请使用该功能直接测量支持的频率范围内的最大可实现电压。

计算最大加速度 (M)

M 是最大加速度,您可以通过各种方法计算得出。本部分介绍了一种适用于使用线性谐振致动器 (LRA) 的设备的方法。

此方法将给定频率下的最大施加电压转换为相应的最大加速度值(以 G 峰值表示)。

此转换所用的核心等式为:

\(\text{Accel}(w)= (\text{Vsys}\times\text{BLsys}\times\text{Loc_coeff}/\text{Rsys}/\text{MPhone})\times{w^2}/\text{Psys_abs}/{9.81}\)

其中:

Vsys:应用于触感反馈执行器的实际电压电平

BLsys:振动电机的磁场强度 (B) 与导体长度 (L) 的乘积

Loc_coeff:用于将模块级加速度转换为手机级加速度的位置系数

Rsys:振动电机线圈的电阻

MPhone:设备的质量(例如手机)

w:驱动信号的角频率(弧度/秒),计算公式如下:

\(w = 2 \pi f\)

Psys_abs:二阶质量、阻尼器和弹簧系统的振幅响应,计算公式如下:

\(\text{Psys_abs} = (\text{Wnsys}^2-w^2)^2+({w}\times(\text{Wnsys}/\text{Qsys}))^2\)

Wnsys:振动系统的固有频率

Qsys:振动系统的品质因数

Loc_coeff 是手机级测得的加速度与模块级测得的加速度之比。此比率用于将模块级加速度读数转换为等效的手机级加速度读数。在手机级别,由于模块运动的角加速度,加速度会被放大,而此系数考虑了这种效应。计算公式如下:

\(\text{Loc_coeff} = \text{phone_acceleration} / \text{module_acceleration}\)

例如,如果模块加速度为 1 g,手机加速度为 2.5 g,则 Loc_coeff = 2.5。这表示放大倍数为 2.5 倍。

Android 框架以赫兹为单位获取频率,因此 HAL 在生成 FOAM 数据时需要将频率单位从每秒弧度转换为赫兹。

生成 FOAM 曲线

结合最大电压曲线 (V) 和加速度计算 (M) 来确定 FOAM 曲线:

  • 对于所需范围内的每个频次 (f),从最大电压曲线中找到相应的最大电压 V(f)
  • 使用上述公式计算该频率下的最大加速度,将 Vsys 替换为 V(f),并将相应的 w 替换为 f。 这样您就可以使用 M(V(f), f) 了。
  • 此计算出的加速度就是您的 FOAM(f) 值。

公开 FOAM 数据

生成 FOAM 曲线后,HAL 会将该曲线表示为 FrequencyAccelerationMapEntry 对象的列表。每个条目都定义了映射中的一个点,用于指定频率(以赫兹为单位)及其对应的最大输出加速度(以 G 峰值为单位)。

虽然对 FOAM 的分辨率没有严格的要求,但我们建议定义具有一个最大峰值的曲线。在基本包络线 API 中,仅使用第一个峰值来映射振动效果。为了在确定中间加速度值时优化线性插值的准确性,建议在峰值附近定义高频分辨率。例如,在峰值频率的 +/- 10 Hz 范围内,使用 1 Hz 的步长。

设备功能和限制

对于 Android 16 及更高版本,为了帮助开发者优化 PWLE 效果并确保跨设备的兼容性,Android 包含用于查询设备 PWLE 功能的 HAL API。这些方法可提供有关设备限制的信息,例如最小或最大 PWLE 原基时长以及 PWLE 合成中允许的原基数量。

HAL API 包括:

  • CAP_COMPOSE_PWLE_EFFECTS_V2:当设备支持此功能时,由 IVibrator.getCapabilities 返回。
  • getFrequencyToOutputAccelerationMap:检索 FOAM 数据。
  • getPwleV2PrimitiveDurationMinMillis:检索任何原始 PWLE 允许的最小时长(以毫秒为单位)。
  • getPwleV2PrimitiveDurationMaxMillis:检索任何原始 PWLE 允许的最大时长(以毫秒为单位)。
  • getPwleV2CompositionSizeMax:检索 IVibrator.composePwleV2 支持的 PWLE 基元数量上限。

此信息会向开发者公开,以便他们根据目标设备的特定功能调整效果,尤其是在使用高级 PWLE API 时。

框架在处理使用基本 API 创建的效果时也会使用这些 API。如果效果超出设备的限制(例如,PWLE 点过多或时长超出最大值),框架会自动调整效果,使其在允许的范围内。此调整过程会尽可能保留设计的原始意图和风格。


  1. 阈值数据是从 Bolanowski Jr. 论文(见图 1)中的位移阈值转换而来,韩J. 等。“四种通道介导触觉的机械方面。”Journal of the Acoustical Society of America 84(5): 1680-1694 (1988). 此在线教程介绍了加速度振幅与位移振幅之间的换算关系。

  2. 数据根据 Verrillo, R. 论文中的图 8 估算得出。T., 等。“振动触觉刺激的感觉强度。” Perception & Psychophysics 6: 366-372 (1969)。