设置测试软件

硬件评估使用以下软件:

  • Audacity(安装在 PC 上)
  • MATLAB(安装在 PC 上)
  • 触感反馈测试应用(安装在 DUT 上)

如需详细了解系统要求,请参阅 适用于 Windows 的 Audacity适用于 Mac 的 AudacityMATLAB

设置 Audacity

需要设置 Audacity,以便以特定的数据采样率从 Sound Blaster 声卡接收输入。将 Sound Blaster 连接到计算机的 USB 端口后,打开 Audacity 并按照以下说明操作。

  1. 通过将 CCLD 输出物理连接到 Sound Blaster 的 Line In 输入端口,选择 Line (USB Sound Blaster HD) 作为输入麦克风源。

    麦克风输入

    图 1. 正在选择麦克风输入

  2. Project Rate 菜单中选择 48000,将采样率设置为 48 kHz。

    采样率

    图 2. 设置采样率

下载 MATLAB

  1. 下载 MATLAB 文件

  2. 解压缩该文件,然后找到 Effect1NEffect2_V1p0_2020PM.m(适用于“Effect1”和“Effect 2”)和 Effect3_V1p0_2020PM.m(适用于“Effect 3”)。

在手机上设置测试应用

本部分介绍如何在手机上设置测试应用。

为测试应用做准备

  1. 复制以下 Java 和 Kotlin 代码块中的源代码。 请选择最适合您的选项。
  2. 按照图 3 所示的 GUI 参数编写您自己的代码。根据需要调整布局源代码的详细信息,使其与您的手机相匹配。
  3. 确保您的 GUI 包含三个可点击的按钮和一个视觉指示器,用于定义加速度计的定位区域。

    • 定位加速度计的区域表示通常用手触摸的设备屏幕的面积。
    • 在测量期间,您可以在绿绿色区域内移动加速度计,以找到能够捕获最强信号的屏幕区域。
  4. 在 Android 设备上安装代码。

  5. 如果默认模式设置为按钮,强烈建议将系统导航模式设置为手势模式。

    • 通过设置手势模式,您可以将加速度计尽可能放在手机底部,同时又不会因手机的系统导航 GUI 而中断。

Java 源代码

package com.example.hapticeffectassessment;

import static android.os.VibrationEffect.EFFECT_CLICK;

import android.graphics.Color;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

 private static final long oneShotTiming = 20;
 private static final int oneShotAmplitude = 255;

 private static final long[] waveformTimings = {500, 500};
 private static final int[] waveformAmplitudes = {128, 255};

 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   Vibrator vibrator = getSystemService(Vibrator.class);

   // Click R.id.button1 button to generate Effect 1
   findViewById(R.id.button1).setOnClickListener(
       view -> vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK)));

   // Click R.id.button2 button to generate Effect 2
   findViewById(R.id.button2).setOnClickListener(
       view -> vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude)));

   // Click R.id.button3 button to generate Effect 3
   findViewById(R.id.button3).setOnClickListener(view -> {
     vibrator.vibrate(VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1));

     // See quick results of Effect 3
     Button button = (Button) view;
     if (vibrator.hasAmplitudeControl()) {
       button.setText("Effect 3: PASS");
       button.setBackgroundColor(Color.GREEN);
       button.setTextColor(Color.BLACK);
     } else {
       button.setText("Effect 3: FAIL");
       button.setBackgroundColor(Color.RED);
       button.setTextColor(Color.WHITE);
     }
   });
 }
}

Kotlin 源代码

package com.example.hapticeffectassessment

import android.graphics.Color
import android.os.Bundle
import android.os.VibrationEffect
import android.os.VibrationEffect.EFFECT_CLICK
import android.os.Vibrator
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivityKt : AppCompatActivity() {

 private val oneShotTiming: Long = 20
 private val oneShotAmplitude = 255

 private val waveformTimings = longArrayOf(500, 500)
 private val waveformAmplitudes = intArrayOf(128, 255)

 override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_main)

   val vibrator = getSystemService(Vibrator::class.java)

   // Click button1 to generate Effect 1
   button1.setOnClickListener {
     vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK))
   }

   // Click button2 to generate Effect 2
   button2.setOnClickListener {
     vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude))
   }

   // Click button3 to generate Effect 3
   button3.setOnClickListener {
     vibrator.vibrate(
       VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1))

     // See quick results of Effect 3
     if (vibrator.hasAmplitudeControl()) {
       button3.text = "Effect 3: PASS"
       button3.setBackgroundColor(Color.GREEN)
       button3.setTextColor(Color.BLACK)
     } else {
       button3.text = "Effect 3: FAIL"
       button3.setBackgroundColor(Color.RED)
       button3.setTextColor(Color.WHITE)
     }
   }
 }
}

布局源代码 (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <Button
       android:id="@+id/button1"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 1"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

   <Button
       android:id="@+id/button2"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 2"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button1" />

   <Button
       android:id="@+id/button3"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 3"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button2" />

   <View
       android:id="@+id/divider"
       android:layout_width="363dp"
       android:layout_height="1dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="10dp"
       android:layout_marginEnd="32dp"
       android:background="?android:attr/listDivider"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintHorizontal_bias="0.5"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button3" />

   <androidx.constraintlayout.widget.ConstraintLayout
       android:layout_width="363dp"
       android:layout_height="0dp"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintHorizontal_bias="0.5"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/divider">

       <ImageView
           android:id="@+id/imageView"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:adjustViewBounds="true"
           android:scaleType="fitXY"
           app:layout_constraintBottom_toBottomOf="parent"
           app:layout_constraintEnd_toEndOf="parent"
           app:layout_constraintHorizontal_bias="0.5"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toTopOf="parent"
           app:srcCompat="@drawable/bluebar" />
   </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

加速度计

图 3. 沿 GUI 中建议的区域安装加速度计