分析振动波形

本文档介绍了线性谐振致动器 (LRA),它是 Android 设备上常见的振动致动器,详细介绍了其特性、如何生成触感反馈,以及如何使用 Android API 创建有效的触感模式。 keywords_public: > Android 触感、触感致动器、线性谐振致动器、LRA、振动、触感反馈、VibratorFrequencyProfile、VibrationEffect、Android 界面

Android 设备上最常见的振动致动器是线性共振致动器 (LRA)。LRA 可在无响应的玻璃表面上模拟按钮点击的感觉。清晰明快的点击反馈信号通常持续 10 到 20 毫秒。这种感觉可让用户互动体验更加自然。对于虚拟键盘,这种点击反馈可以提高输入速度并减少错误。

LRA 有几个常见的共振频率:

  • 有些 LRA 的共振频率在 200 到 300 Hz 范围内,这与人皮肤对振动最敏感的频率相符。此频率范围内的振动感通常被描述为平滑、尖锐和穿透。
  • 其他型号的 LRA 的共振频率较低,约为 150 Hz。这种感觉在质量上更柔和、更饱满(在维度上)。
组件包括(从上到下):盖子、板、中间磁铁、2 个侧面磁铁、质量块、2 个弹簧、线圈、柔性电路、底座和粘合剂。
线性共振致动器 (LRA) 的组件。

在两个不同频率下提供相同的输入电压时,振动输出幅度可能会有所不同。频次与 LRA 的共振频次相差越远,其振动幅度就越小。

给定设备的触感效果同时使用振动致动器及其驱动程序。 包含过驱动和主动制动功能的触感驱动器可以缩短 LRA 的上升时间和振铃时间,从而实现更灵敏、更清晰的振动。

振动器输出加速度

频次与输出加速度的映射关系 (FOAM) 描述了在给定振动频率(以赫兹为单位)下可实现的最大输出加速度(以 G 峰值为单位)。从 Android 16(API 级别 36)开始,平台通过 VibratorFrequencyProfile 为此映射提供内置支持。您可以将此类与基本和高级波封 API 搭配使用,以创建触感反馈效果。

大多数 LRA 电机在其 FOAM 中都有一个峰值,通常接近其共振频率。一般来说,随着频率偏离此范围,加速度会呈指数级下降。该曲线可能不对称,并且在共振频率附近可能呈现平台状,以保护电机免受损坏。

邻近的图显示了 LRA 电机的一个 FOAM 示例。

当频率增加到大约 120 Hz 时,加速度会呈指数级增加。然后,加速度在 180 Hz 左右保持稳定,之后逐渐减小。
LRA 电机的 FOAM 示例。

人类感知检测阈值

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

相邻的图显示了人类触觉感知检测阈值(以加速度为单位)与时间频率的关系。阈值数据根据 Bolanowski Jr.、韩J. 等人 1988 年发表的文章《Four channels mediate the mechanical aspects of touch》。

Android 会在 BasicEnvelopeBuilder 中自动处理此阈值,该阈值可验证所有效果使用的频率范围是否能产生至少比人类感知检测阈值高 10 dB 的振动幅度。

当频率增加到大约 20 Hz 时,人类的检测阈值会以对数方式上升到大约 -35 dB。在 200 Hz 左右,阈值保持稳定,之后在 -20 dB 范围内大致呈线性增加。
人类触感感知检测阈值。

在线教程进一步解释了加速度振幅与位移振幅之间的转换。

振动加速度级别

人类对振动强度的感知(一种感知度量)不会随着振幅(一种物理参数)呈线性增长。感知强度以感觉级 (SL) 为特征,感觉级定义为在相同频率下高于检测阈值的 dB 量。

相应的振动加速度幅度(以 G 峰值表示)可按如下方式计算:

$$ Amplitude(G) = 10^{Amplitude(db)/20} $$

…其中,振幅(分贝)是声源强度 (SL) 和检测阈值的总和,即相邻图中纵轴上的值(在特定频率下)。

邻近的图显示了在 10、20、30、40 和 50 dB SL 下的振动加速度水平,以及人类触觉感知检测阈值(0 dB SL),作为时间频率的函数。数据根据 Verrillo, R. T. 等人 1969 年发表的文章《Sensation magnitude of vibrotactile stimuli》(振动触觉刺激的感觉强度)。

随着所需感觉水平的增加,所需的加速度(以分贝为单位)大致会增加相同的量。例如,100 Hz 振动的 10 dB 感觉级约为 -20 dB,而不是 -30 dB。
振动加速度级别。

Android 会在 BasicEnvelopeBuilder 中自动处理此转换,该函数会以感觉级空间 (dB SL) 中的归一化强度作为输入值,并将其转换为输出加速度。另一方面,WaveformEnvelopeBuilder 不会应用此转换,而是将值作为加速度空间 (Gs) 中归一化的输出加速度幅度。信封 API 假定,当设计者或开发者考虑振动强度变化时,他们希望感知到的强度遵循分段线性信封。

设备上的默认波形平滑处理

为便于说明,请考虑自定义波形模式在通用设备上的行为:

Kotlin

val timings: LongArray = longArrayOf(50, 50, 50, 50, 50, 100, 350, 250)
val amplitudes: IntArray = intArrayOf(77, 79, 84, 99, 143, 255, 0, 255)
val repeatIndex = -1 // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))

Java

long[] timings = new long[] { 50, 50, 50, 50, 50, 100, 350, 250 };
int[] amplitudes = new int[] { 77, 79, 84, 99, 143, 255, 0, 255 };
int repeatIndex = -1 // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));

以下图表显示了与上述代码段对应的输入波形和输出加速度。请注意,每当模式中的振幅发生阶跃变化时(即在 0 毫秒、150 毫秒、200 毫秒、250 毫秒和 700 毫秒时),加速度都会逐渐增加,而不是突然增加。此外,在每次振幅变化时,都会出现过冲;当输入振幅突然降至 0 时,会出现明显的振铃,持续时间至少为 50 毫秒。

阶跃函数输入波形图。
实际测量的波形图,显示了更多级别之间的自然过渡。

改进了触感模式

为避免过冲并缩短振铃时间,请更缓慢地更改振幅。以下是修订版波形图和加速度图:

Kotlin

val timings: LongArray = longArrayOf(
    25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
    300, 25, 25, 150, 25, 25, 25
)
val amplitudes: IntArray = intArrayOf(
    38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
    0, 85, 170, 255, 170, 85, 0
)
val repeatIndex = -1 // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))

Java

long[] timings = new long[] {
        25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
        300, 25, 25, 150, 25, 25, 25
    };
int[] amplitudes = new int[] {
        38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
        0, 85, 170, 255, 170, 85, 0
    };
int repeatIndex = -1; // Don't repeat.

vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));

包含其他步骤的输入波形图。
显示平滑过渡的测量波形图。

创建更复杂的触感反馈效果

令人满意的点击响应中的其他元素则更为复杂,需要了解设备中使用的 LRA。为获得最佳效果,请使用设备预制的波形和平台提供的常量,这样您便可以执行以下操作:

  • 执行清晰效果和基元。
  • 将它们连接起来以组成新的触感效果。

这些预定义的触感常量和基元可以极大地加快您创建高质量触感效果的速度。