应用定位:音乐创作模拟类小应用
技术栈:HarmonyOS NEXT + ArkTS + Stage模型
源码行数:113行
核心亮点:8音符音阶系统、录音回放、颜色编码按键、音符序列展示、阵列边界管理


一、引言

弹琴模拟器是系列中第一个引入录音回放功能的应用。它允许用户点击琴键弹奏音符,录制一段旋律,然后播放。

从技术角度看,弹琴模拟器的新概念包括:

  • 8音阶系统:Do-Re-Mi-Fa-Sol-La-Si-Do
  • 录音系统:将按下的音符存入数组
  • 播放回放:展示录制的音符序列
  • 颜色编码:每个音符用不同颜色表示
  • 序列管理:限制序列长度(最多10个)

二、需求分析

2.1 功能需求

需求ID 功能 描述
F1 音符按键 8个彩色琴键,点击发声
F2 音符名称 显示Do-Re-Mi-Fa-Sol-La-Si-Do
F3 音阶显示 实时显示已弹奏的音符序列
F4 录音模式 开启后记录所有音符
F5 播放录音 展示录制的音符序列
F6 清空序列 重置已弹奏内容

2.2 数据结构

private notes: string[] = ['1', '2', '3', '4', '5', '6', '7', '1·'];
private noteNames: string[] = ['Do', 'Re', 'Mi', 'Fa', 'Sol', 'La', 'Si', 'Do·'];
private noteColors: string[] = ['#FF5722', '#FF9800', '#FFEB3B', '#4CAF50', '#2196F3', '#3F51B5', '#9C27B0', '#E91E63'];

三个数组通过索引关联——索引0对应音符’1’、名称’Do’、颜色红色。


三、琴键实现

3.1 琴键渲染

Row() {
  ForEach(this.notes, (note: string, idx: number) => {
    Column() {
      Text(note)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
      Text(this.noteNames[idx])
        .fontSize(10)
        .margin({ top: 5 })
    }
    .width(40)
    .height(80)
    .backgroundColor(this.noteColors[idx])
    .borderRadius(8)
    .margin({ right: 3 })
    .onClick(() => {
      this.playNote(idx);
    })
  })
}

每个琴键是一个 Column 容器,包含音符数字和名称。8个琴键横向排列在 Row 中。

3.2 音符颜色设计

private noteColors: string[] = ['#FF5722', '#FF9800', '#FFEB3B', '#4CAF50', '#2196F3', '#3F51B5', '#9C27B0', '#E91E63'];

使用彩虹色系(红橙黄绿蓝靛紫粉),每个音符对应一个颜色。这种色彩编码符合音乐中的"音色"概念——不同音符听感不同,视觉上也不同。


四、录音系统

4.1 录音开关

Button('⏺️ ' + (this.isRecording ? '停止录音' : '开始录音'))
  .backgroundColor(this.isRecording ? '#F44336' : '#4CAF50')
  .onClick(() => {
    this.isRecording = !this.isRecording;
    if (this.isRecording) {
      this.recordNotes = [];
      this.message = '🔴 正在录音... 点击琴键录下旋律';
    } else {
      // 录音结束
    }
  })

按钮文字和颜色随录音状态动态变化:

  • 未录音:绿色"开始录音"
  • 录音中:红色"停止录音"

4.2 录制音符

playNote(idx: number) {
  this.playedNotes.push(this.notes[idx]);
  this.message = '🎵 弹奏了 ' + this.noteNames[idx] + ' (' + this.notes[idx] + ')';
  if (this.isRecording) {
    this.recordNotes.push(this.notes[idx]);
  }
  if (this.playedNotes.length > 10) {
    this.playedNotes.shift();
  }
}

录音分支:如果 isRecording 为 true,额外将音符存入 recordNotes 数组。

序列长度限制playedNotes 超过10个时,使用 shift() 移除最老的音符。这是一种**FIFO(先进先出)**的队列行为。


五、音阶展示

if (this.playedNotes.length > 0) {
  Text('🎼 当前音阶: ' + this.playedNotes.join(' → '))
    .fontSize(13)
    .fontColor('#333')
    .padding(8)
    .backgroundColor('#F5F5F5')
    .borderRadius(8)
    .width('90%')
}

使用 join(' → ') 将音符数组转换为字符串,箭头连接。


六、播放录音

if (this.recordNotes.length > 0) {
  Button('▶️ 播放录音')
    .onClick(() => {
      this.message = '🎶 播放录音中... ' + this.recordNotes.join(' ');
    })
}

当前版本中,"播放"只是展示录音内容。完整的播放功能需要配合定时器逐音符回放:

// 进阶播放实现
playRecording() {
  let i = 0;
  let playInterval = setInterval(() => {
    if (i >= this.recordNotes.length) {
      clearInterval(playInterval);
      return;
    }
    this.message = '🎵 ' + this.recordNotes[i];
    i++;
  }, 500);
}

七、扩展思路

7.1 音高播放

使用 Web Audio API 或鸿蒙 AudioKit 播放实际音高:

import { audio } from '@kit.AudioKit';

playTone(frequency: number) {
  // 播放对应频率的声音
}

7.2 简易乐谱

private songs: string[][] = [
  ['1', '2', '3', '1', '1', '2', '3', '1'], // 两只老虎
  ['3', '4', '5', '3', '4', '5'],           // 小星星片段
];

7.3 和弦模式

同时按下多个键触发和弦:

// 需要支持多点触控
onTouch((event: TouchEvent) => {
  if (event.type === TouchType.Down) {
    // 检测按了哪些键
  }
})

八、总结

弹琴模拟器展示了ArkTS在"音乐创作模拟"场景的开发模式:

  1. 颜色编码:8音符8种颜色对应
  2. 录音系统:状态开关 + 数组记录
  3. 队列管理shift() 限制序列长度
  4. 音符展示join() 序列化数组

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐