HarmonyOS分贝检测器开发——实时环境噪音监测实战

HarmonyOS分贝检测器开发——实时环境噪音监测实战

技术栈:HarmonyOS 5.0 + ArkTS + AudioCapturer

适用场景:环境噪音检测、听力保护提醒、声音可视化


前言

分贝仪是一个实用的环境噪音检测工具,可以帮助用户了解所处环境的噪音水平,保护听力健康。本文将详细介绍如何使用HarmonyOS的AudioCapturer实现实时分贝检测。

一、分贝计算原理

1.1 声压级(SPL)

分贝是一个对数单位,用于表示声音强度:

SPL (dB) = 20 × log₁₀(P / P₀)

其中P是测量声压,P₀是参考声压(20μPa)。

1.2 数字音频转换

从数字音频数据计算分贝:

  1. 计算音频样本的均方根(RMS)
  2. 转换为分贝值
  3. 添加校准偏移量

二、代码实现

2.1 分贝检测器类

import audio from '@ohos.multimedia.audio';

/**
 * 分贝检测器
 * 通过麦克风采集环境声音,实时计算分贝值
 */
export class DecibelDetector {
  private audioCapturer: audio.AudioCapturer | null = null;
  private isRecording: boolean = false;
  private callback: (db: number) => void;
  private bufferSize: number = 2048;

  constructor(callback: (db: number) => void) {
    this.callback = callback;
  }

  async start(): Promise<void> {
    if (this.isRecording) return;

    try {
      const audioCapturerOptions: audio.AudioCapturerOptions = {
        streamInfo: {
          samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
          channels: audio.AudioChannel.CHANNEL_1,
          sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
          encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
        },
        capturerInfo: {
          source: audio.SourceType.SOURCE_TYPE_MIC,
          capturerFlags: 0
        }
      };

      this.audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
      await this.audioCapturer.start();
      this.isRecording = true;
      this.readBuffer();
    } catch (e) {
      console.error('DecibelDetector start failed:', e);
    }
  }

  async stop(): Promise<void> {
    if (!this.isRecording) return;
    this.isRecording = false;
    if (this.audioCapturer) {
      await this.audioCapturer.stop();
      await this.audioCapturer.release();
      this.audioCapturer = null;
    }
  }

  private async readBuffer() {
    while (this.isRecording && this.audioCapturer) {
      const buffer = await this.audioCapturer.read(this.bufferSize, true);
      if (buffer) {
        const db = this.calculateDecibel(buffer);
        this.callback(db);
      }
    }
  }

  private calculateDecibel(buffer: ArrayBuffer): number {
    const data = new Int16Array(buffer);
    let sum = 0;
    
    // 计算均方根 (RMS)
    for (let i = 0; i < data.length; i++) {
      sum += data[i] * data[i];
    }
    const rms = Math.sqrt(sum / data.length);
    
    if (rms < 1) return 30; // 极安静环境
    
    // 转换为分贝
    let db = 20 * Math.log10(rms / 32767.0);
    db += 94; // 校准偏移
    
    return Math.min(Math.max(Math.round(db), 20), 120);
  }
}

2.2 权限配置

// module.json5
{
  "requestPermissions": [
    {
      "name": "ohos.permission.MICROPHONE",
      "reason": "$string:microphone_reason",
      "usedScene": {
        "abilities": ["EntryAbility"],
        "when": "inuse"
      }
    }
  ]
}

2.3 动态权限申请

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

private async requestMicrophonePermission(): Promise<boolean> {
  const atManager = abilityAccessCtrl.createAtManager();
  const context = getContext(this);
  const result = await atManager.requestPermissionsFromUser(
    context, 
    ['ohos.permission.MICROPHONE']
  );
  return result.authResults[0] === 0;
}

2.4 页面使用示例

@Entry
@Component
struct DecibelMeterPage {
  @State currentDecibel: number = 0;
  @State maxDecibel: number = 0;
  @State minDecibel: number = 100;
  @State isMonitoring: boolean = false;
  private decibelDetector: DecibelDetector | null = null;

  aboutToAppear(): void {
    this.initDecibelDetector();
  }

  aboutToDisappear(): void {
    this.decibelDetector?.stop();
  }

  private async initDecibelDetector(): Promise<void> {
    if (await this.requestMicrophonePermission()) {
      this.decibelDetector = new DecibelDetector((db: number) => {
        this.currentDecibel = db;
        this.maxDecibel = Math.max(this.maxDecibel, db);
        this.minDecibel = Math.min(this.minDecibel, db);
      });
      await this.decibelDetector.start();
      this.isMonitoring = true;
    }
  }

  build() {
    Column() {
      Text(`${this.currentDecibel}`)
        .fontSize(80)
        .fontWeight(FontWeight.Bold)
      Text('dB')
        .fontSize(24)
      
      Row() {
        Column() {
          Text(`${this.minDecibel}`).fontSize(24)
          Text('最小').fontSize(12).fontColor('#666')
        }
        Column() {
          Text(`${this.maxDecibel}`).fontSize(24)
          Text('最大').fontSize(12).fontColor('#666')
        }
      }
      .justifyContent(FlexAlign.SpaceAround)
      .width('60%')
      .margin({ top: 30 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

三、分贝等级参考表

分贝范围 环境描述 健康影响
20-40 dB 安静的图书馆 理想环境
40-60 dB 正常交谈 舒适环境
60-80 dB 繁忙街道 可能干扰
80-100 dB 工厂噪音 长期暴露有害
100+ dB 摇滚音乐会 可能立即损伤

四、避坑指南

  1. 权限申请:必须在module.json5声明并动态申请麦克风权限
  2. 资源释放:页面销毁时必须调用stop()
  3. 校准值:94是经验值,不同设备可能需要微调
  4. 隐私声明:应用商店审核要求明确说明麦克风用途

总结

本文实现了一个完整的HarmonyOS分贝检测器,可用于环境噪音监测、听力保护提醒等场景。关键点在于正确的RMS计算和分贝转换公式。

posted @ 2025-12-18 11:03  柠果丶  阅读(3)  评论(0)    收藏  举报