HarmonyOS NEXT Development Case: Decibel Meter

This article demonstrates how to create a Decibel Meter application using HarmonyOS NEXT, implementing core features including microphone permission management, real-time audio data collection, decibel calculation, and dynamic UI updates. 1. Core Implementation 1.1 Permission Management We implement a complete permission request flow following HarmonyOS permission specifications: // Request microphone permission requestPermissionsFromUser() { const context = getContext(this) as common.UIAbilityContext; const atManager = abilityAccessCtrl.createAtManager(); atManager.requestPermissionsFromUser(context, this.requiredPermissions, (err, data) => { const grantStatus: Array = data.authResults; if (grantStatus.toString() == "-1") { this.showAlertDialog(); } else if (grantStatus.toString() == "0") { this.initialize(); } }); } // Open system settings page openPermissionSettingsPage() { const context = getContext() as common.UIAbilityContext; const bundleInfo = bundleManager.getBundleInfoForSelfSync( bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION); context.startAbility({ bundleName: 'com.huawei.hmos.settings', abilityName: 'com.huawei.hmos.settings.MainAbility', uri: 'application_info_entry', parameters: { pushParams: bundleInfo.name } }); } 1.2 Audio Capture Configuration Configure audio capture parameters according to system specifications: initialize() { const streamInfo: audio.AudioStreamInfo = { samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, channels: audio.AudioChannel.CHANNEL_1, sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW }; const recorderInfo: audio.AudioCapturerInfo = { source: audio.SourceType.SOURCE_TYPE_MIC, capturerFlags: 0 }; const recorderOptions: audio.AudioCapturerOptions = { streamInfo: streamInfo, capturerInfo: recorderInfo }; audio.createAudioCapturer(recorderOptions, (err, recorder) => { if (err) return; this.audioRecorder = recorder; this.audioRecorder.on('readData', (buffer: ArrayBuffer) => { this.currentDecibel = this.calculateDecibel(buffer); this.updateDisplay(); }); this.startRecording(); }); } 1.3 Decibel Calculation Algorithm Implement scientific decibel calculation using PCM data: calculateDecibel(pcm: ArrayBuffer): number { let sum = 0; const pcmView = new DataView(pcm); const numSamples = pcm.byteLength / 2; // PCM data processing for (let i = 0; i

May 11, 2025 - 02:46
 0
HarmonyOS NEXT Development Case: Decibel Meter

Image description

This article demonstrates how to create a Decibel Meter application using HarmonyOS NEXT, implementing core features including microphone permission management, real-time audio data collection, decibel calculation, and dynamic UI updates.

1. Core Implementation

1.1 Permission Management

We implement a complete permission request flow following HarmonyOS permission specifications:

// Request microphone permission
requestPermissionsFromUser() {
  const context = getContext(this) as common.UIAbilityContext;
  const atManager = abilityAccessCtrl.createAtManager();

  atManager.requestPermissionsFromUser(context, this.requiredPermissions, (err, data) => {
    const grantStatus: Array<number> = data.authResults;
    if (grantStatus.toString() == "-1") {
      this.showAlertDialog();
    } else if (grantStatus.toString() == "0") {
      this.initialize();
    }
  });
}

// Open system settings page
openPermissionSettingsPage() {
  const context = getContext() as common.UIAbilityContext;
  const bundleInfo = bundleManager.getBundleInfoForSelfSync(
    bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);

  context.startAbility({
    bundleName: 'com.huawei.hmos.settings',
    abilityName: 'com.huawei.hmos.settings.MainAbility',
    uri: 'application_info_entry',
    parameters: { pushParams: bundleInfo.name }
  });
}

1.2 Audio Capture Configuration

Configure audio capture parameters according to system specifications:

initialize() {
  const streamInfo: audio.AudioStreamInfo = {
    samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
    channels: audio.AudioChannel.CHANNEL_1,
    sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
    encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
  };

  const recorderInfo: audio.AudioCapturerInfo = {
    source: audio.SourceType.SOURCE_TYPE_MIC,
    capturerFlags: 0
  };

  const recorderOptions: audio.AudioCapturerOptions = {
    streamInfo: streamInfo,
    capturerInfo: recorderInfo
  };

  audio.createAudioCapturer(recorderOptions, (err, recorder) => {
    if (err) return;
    this.audioRecorder = recorder;
    this.audioRecorder.on('readData', (buffer: ArrayBuffer) => {
      this.currentDecibel = this.calculateDecibel(buffer);
      this.updateDisplay();
    });
    this.startRecording();
  });
}

1.3 Decibel Calculation Algorithm

Implement scientific decibel calculation using PCM data:

calculateDecibel(pcm: ArrayBuffer): number {
  let sum = 0;
  const pcmView = new DataView(pcm);
  const numSamples = pcm.byteLength / 2;

  // PCM data processing
  for (let i = 0; i < pcm.byteLength; i += 2) {
    const sample = pcmView.getInt16(i, true) / 32767.0;
    sum += sample * sample;
  }

  const meanSquare = sum / numSamples;
  const rmsAmplitude = Math.sqrt(meanSquare);
  const referencePressure = 20e-6;
  const decibels = 20 * Math.log10(rmsAmplitude / referencePressure);

  // Normalize to 0-100 range
  const minDb = 20;
  const maxDb = 100;
  const mappedValue = ((decibels - minDb) / (maxDb - minDb)) * 100;

  return Math.max(0, Math.min(100, mappedValue));
}

2. UI Implementation

2.1 Dynamic Gauge Component

Create an interactive gauge with gradient colors:

@Entry
@Component
struct DecibelMeter {
  @State currentDecibel: number = 0;
  @State displayedDecibel: number = 0;
  @State displayType: string = '';

  build() {
    Column() {
      Gauge({ value: this.currentDecibel, min: 1, max: 100 }) {
        Column() {
          Text(`${this.displayedDecibel}dB`)
            .fontSize(25)
            .fontColor("#323232");

          Text(`${this.displayType}`)
            .fontSize(16)
            .fontColor("#848484");
        }
      }
      .startAngle(225)
      .endAngle(135)
      .colors(this.gaugeColors)
      .height(250);
    }
  }
}

2.2 Noise Level Indicator

Implement dynamic noise level classification:

typeArray: ValueBean[] = [
  new ValueBean("Silent", "0~20dB: Very quiet environment", 0, 20, "#02b003", "#016502"),
  new ValueBean("Quiet", "20~40dB: Quiet conversation", 20, 40, "#7ed709", "#4f8800"),
  new ValueBean("Normal", "40~60dB: Typical indoor level", 40, 60, "#ffef01", "#ad9e04"),
  new ValueBean("Noisy", "60~80dB: Loud speech", 60, 80, "#f88200", "#965001"),
  new ValueBean("Dangerous", "80~100dB: Hearing damage risk", 80, 100, "#f80000", "#9d0001"),
];

3. Best Practices

  1. Performance Optimization:

    Implement 1-second update throttling to reduce UI rendering pressure

  2. Error Handling:

    Add comprehensive error handling for audio device operations

  3. User Guidance:

    Provide clear permission request instructions and settings redirection

  4. Accessibility:

    Use high-contrast color schemes and clear typography

The application follows HarmonyOS design guidelines while maintaining good performance and user experience. Developers can extend functionality by adding features like data logging or historical analysis.