分析震動波形

本文將說明 Android 裝置上常見的震動致動器「線性共振致動器 (LRA)」,詳細介紹其特性、產生觸覺回饋的方式,以及如何使用 Android API 建立有效的觸覺模式。 keywords_public: > Android 觸覺技術、觸覺致動器、線性共振致動器、LRA、震動、 觸覺回饋、VibratorFrequencyProfile、VibrationEffect、Android UI

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. 論文圖 1 的位移門檻轉換而來,S. J. 等人於 1988 年發表的文章「Four channels mediate the mechanical aspects of touch」(四個管道調解觸覺的機械層面)。

Android 會在 BasicEnvelopeBuilder 中自動處理這個門檻,確認所有效果使用的頻率範圍產生的震動幅度,至少要比人類感知偵測門檻高出 10 分貝。

當頻率增加到約 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. 論文中的圖 8 估算而得。T. 等人於 1969 年發表的文章「Sensation magnitude of vibrotactile stimuli.」。

所需體感程度越高,所需加速度 (以 dB 為單位) 就會增加,且增幅大致相同。舉例來說,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。為獲得最佳結果,請使用裝置預先製作的波形和平台提供的常數,以便執行下列操作:

  • 執行清除效果和基本體。
  • 將這些效果串連在一起,即可組成新的觸覺效果。

這些預先定義的觸覺常數和基本型別可大幅加快工作速度,同時建立高品質的觸覺效果。