> **技术栈**:HarmonyOS 5.0 + ArkTS + AudioRenderer

>

> **适用场景**:听力健康应用、医疗辅助工具

---

## 前言

纯音测听(Pure Tone Audiometry)是临床上最常用的听力检测方法。本文将介绍如何在HarmonyOS应用中实现一个专业的纯音测听功能。

## 一、纯音测听原理

### 1.1 测试频率

标准纯音测听使用以下频率:

- **125Hz, 250Hz, 500Hz**:低频

- **1000Hz, 2000Hz**:中频(语音频率)

- **4000Hz, 8000Hz**:高频

### 1.2 听阈分级(WHO标准)

| 听阈 (dB) | 听力等级 |

|----------|---------|

| ≤25 | 正常 |

| 26-40 | 轻度损失 |

| 41-55 | 中度损失 |

| 56-70 | 中重度损失 |

| 71-90 | 重度损失 |

| >90 | 极重度损失 |

## 二、数据结构设计

```typescript

export interface PureToneFrequencyResult {

  frequency: number;        // 测试频率 Hz

  leftEarThreshold: number; // 左耳听阈 dB,-1表示未测试

  rightEarThreshold: number;// 右耳听阈 dB

}

export interface PureToneTestResult {

  id: string;

  timestamp: number;

  results: PureToneFrequencyResult[];

  leftEarAverage: number;

  rightEarAverage: number;

  overallLevel: string;

  leftEarLevel: string;

  rightEarLevel: string;

}

```

## 三、测试页面实现

### 3.1 页面状态管理

```typescript

@Entry

@Component

struct PureToneTestPage {

  @StorageLink('appDarkMode') isDarkMode: boolean = true;

  @State currentEar: string = 'left';

  @State currentFrequencyIndex: number = 0;

  @State currentVolume: number = 30;

  @State isPlaying: boolean = false;

  @State testResults: PureToneFrequencyResult[] = [];

  @State testPhase: string = 'intro';

  private testFrequencies: number[] = [125, 250, 500, 1000, 2000, 4000, 8000];

  private audioEngine: AudioEngine = AudioEngine.getInstance();

  aboutToAppear(): void {

    this.initTestResults();

    this.audioEngine.init();

  }

  private initTestResults(): void {

    this.testResults = this.testFrequencies.map((freq: number) => ({

      frequency: freq,

      leftEarThreshold: -1,

      rightEarThreshold: -1

    }));

  }

}

```

### 3.2 播放测试音

```typescript

private async playTestTone(): Promise<void> {

  if (this.isPlaying) {

    await this.audioEngine.stop();

    this.isPlaying = false;

    return;

  }

  this.isPlaying = true;

  const frequency = this.testFrequencies[this.currentFrequencyIndex];

  const safeVolume = Math.max(0.1, this.currentVolume / 100);

  this.audioEngine.setAudioType('tone');

  this.audioEngine.setWaveformType('sine');

  this.audioEngine.setFrequency(frequency);

  this.audioEngine.setVolume(safeVolume);

  await this.audioEngine.start(3);

  setTimeout(() => { this.isPlaying = false; }, 3000);

}

```

### 3.3 记录听阈

```typescript

private recordThreshold(): void {

  const result = this.testResults[this.currentFrequencyIndex];

  if (this.currentEar === 'left') {

    result.leftEarThreshold = this.currentVolume;

  } else {

    result.rightEarThreshold = this.currentVolume;

  }

  // 震动反馈

  vibrator.startVibration({ type: 'time', duration: 50 }, { id: 0, usage: 'notification' });

  this.nextTest();

}

private nextTest(): void {

  if (this.currentEar === 'left') {

    this.currentEar = 'right';

    this.currentVolume = 30;

  } else {

    this.currentEar = 'left';

    this.currentFrequencyIndex++;

    this.currentVolume = 30;

   

    if (this.currentFrequencyIndex >= this.testFrequencies.length) {

      this.testPhase = 'completed';

      this.saveResults();

    }

  }

}

```

### 3.4 计算平均听阈

```typescript

static async savePureToneTestResult(results: PureToneFrequencyResult[]): Promise<PureToneTestResult> {

  const speechFrequencies = [500, 1000, 2000, 4000];

  let leftSum = 0, rightSum = 0, leftCount = 0, rightCount = 0;

  for (const r of results) {

    if (speechFrequencies.includes(r.frequency)) {

      if (r.leftEarThreshold >= 0) {

        leftSum += r.leftEarThreshold;

        leftCount++;

      }

      if (r.rightEarThreshold >= 0) {

        rightSum += r.rightEarThreshold;

        rightCount++;

      }

    }

  }

  const leftAvg = leftCount > 0 ? Math.round(leftSum / leftCount) : -1;

  const rightAvg = rightCount > 0 ? Math.round(rightSum / rightCount) : -1;

  return {

    id: `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,

    timestamp: Date.now(),

    results: results,

    leftEarAverage: leftAvg,

    rightEarAverage: rightAvg,

    overallLevel: getHearingLevelByThreshold(Math.max(leftAvg, rightAvg)),

    leftEarLevel: getHearingLevelByThreshold(leftAvg),

    rightEarLevel: getHearingLevelByThreshold(rightAvg)

  };

}

static getHearingLevelByThreshold(threshold: number): string {

  if (threshold < 0) return '未测试';

  if (threshold <= 25) return '正常';

  if (threshold <= 40) return '轻度损失';

  if (threshold <= 55) return '中度损失';

  if (threshold <= 70) return '中重度损失';

  if (threshold <= 90) return '重度损失';

  return '极重度损失';

}

```

## 四、UI界面示例

```typescript

build() {

  Column() {

    // 进度指示

    Row() {

      ForEach(this.testFrequencies, (freq: number, index: number) => {

        Circle()

          .width(12).height(12)

          .fill(index < this.currentFrequencyIndex ? '#2D7FF9' :

                index === this.currentFrequencyIndex ? '#34C759' : '#333')

      })

    }.justifyContent(FlexAlign.SpaceEvenly).width('100%')

    Text(`${this.testFrequencies[this.currentFrequencyIndex]} Hz`)

      .fontSize(48).fontWeight(FontWeight.Bold)

   

    Text(`${this.currentEar === 'left' ? '左耳' : '右耳'}`)

      .fontSize(20)

    Slider({ value: this.currentVolume, min: 0, max: 100, step: 5 })

      .onChange((value: number) => { this.currentVolume = value; })

    Row() {

      Button('播放').onClick(() => this.playTestTone())

      Button('听到了').onClick(() => this.recordThreshold())

    }.justifyContent(FlexAlign.SpaceEvenly)

  }

}

```

## 五、避坑指南

1. **音量校准**:不同设备音量输出不同,建议添加校准功能

2. **测试环境**:提醒用户在安静环境中使用耳机测试

3. **免责声明**:明确说明仅供参考,不能替代专业医学检查

4. **数据保护**:测试结果仅存储在本地

## 总结

本文实现了一个专业的纯音测听功能,包括标准频率测试、听阈记录、等级评估等。该功能可帮助用户初步了解自己的听力状况。

---

**🎓 我的HarmonyOS开发课堂**:[点击进入课堂学习](https://developer.huawei.com/consumer/cn/training/classDetail/03d6a547f8124d35aab33fc40840288f?type=1?ha_source=hmosclass&ha_sourceId=89000248)

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐