分析震動波形

Android 裝置上最常見的震動致動器是線性共振致動器 (LRAs)。LRAs 會模擬按鈕在玻璃表面上點擊的感受,而玻璃表面不會有任何反應。清晰的點擊回饋信號通常會持續 10 到 20 毫秒。這種感覺可讓使用者互動更自然。對於虛擬鍵盤,這項點擊回饋功能可加快輸入速度並減少錯誤。

LRAs 有幾個常見的共振頻率

  • 部分 LRAs 的共振頻率介於 200 到 300 Hz,這與人類皮膚對振動的敏感頻率相符。在這個頻率範圍內,震動的感覺通常被形容為平滑、尖銳和穿透。
  • 其他型號的 LRAs 共振頻率較低,約為 150 Hz。這種感覺在質地上較為柔軟、飽滿 (在維度上)。
元件包括 (由上而下) 護套、板、中間磁鐵、2 個側邊磁鐵、質量、2 個彈簧、線圈、軟性電路、底座和黏著劑。
線性諧振致動器 (LRA) 的元件。

在兩種不同頻率下,相同的輸入電壓可能會產生不同的振動輸出幅度。頻率離 LRA 的諧振頻率越遠,振動幅度就越低。

特定裝置的觸覺回饋效果會同時使用震動致動器和驅動程式。搭載超速和主動煞車功能的觸覺感應驅動器,可縮短 LRAs 的升溫時間和振鈴時間,進而提供更靈敏且清晰的震動效果。

震動器輸出加速

頻率至輸出加速度對應 (FOAM) 會說明在特定振動頻率 (以赫茲為單位) 下,可達到的最大輸出加速度 (以 G 峰值為單位)。從 Android 16 (API 級別 36) 開始,平台會透過 VibratorFrequencyProfile 提供此對應的內建支援功能。您可以使用這個類別,搭配基本進階包函 API,建立觸覺效果。

大多數 LRA 馬達的 FOAM 只有一個峰值,通常位於共振頻率附近。加速度通常會隨著頻率偏離此範圍而以指數方式降低。曲線可能不對稱,且可能會在共振頻率附近呈現平坦狀態,以保護馬達免於損壞。

下方圖表顯示 LRA 馬達的 FOAM 範例。

頻率增加至約 120 Hz 時,加速度會以指數方式增加。加速度會在 180 Hz 左右保持穩定,之後會逐漸減弱。
LRA 馬達的泡沫示例。

人類感知偵測門檻

「人類感知偵測門檻」是指人類可可靠偵測到的振動最小加速度。這項等級會因震動頻率而異。

下方圖表顯示人類觸覺感知偵測閾值 (以加速度表示),以時間頻率做為函數。閾值資料是根據 Bolanowski Jr. 圖 1 中的位移閾值轉換而來,S. 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} $$

其中振幅 dB 是特定頻率下 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));

下列圖表顯示輸入波形和輸出加速度,對應前述程式碼片段。請注意,每當模式中的振幅出現階梯式變化 (即 0ms、150ms、200ms、250ms 和 700ms) 時,加速度會逐漸增加,而非突然增加。在每個振幅階梯變化時,也會出現過衝現象,而且當輸入振幅突然降至 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 // Do not 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; // Do not repeat.

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

含有額外步驟的輸入波形圖表。
繪製測量波形,顯示更順暢的轉換。

建立更複雜的觸覺技術效果

滿意點擊回應中的其他元素則較為複雜,需要瞭解裝置中使用的 LRA。為了獲得最佳結果,請使用裝置預先建構的波形和平台提供的常數,以便執行下列操作:

  • 執行清晰效果和基本元素
  • 將這些音效串連起來,組合成新的觸覺效果。

這些預先定義的觸覺常數和基本元素可大幅加快您的工作速度,同時創造高品質的觸覺效果。