You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中使用AudioKit将MIDI文件转换为Note对象数组?

在Swift中使用AudioKit将单轨MIDI文件转换为自定义Note数组

核心实现步骤

针对单轨MIDI文件,我们可以直接借助AudioKit的MIDI解析工具,将音符事件映射到你定义的Note结构体中,具体流程如下:

1. 导入AudioKit相关模块

确保项目已集成AudioKit及AudioKitEX依赖,先导入必要模块:

import AudioKit
import AudioKitEX

2. 加载本地MIDI文件

从Bundle或指定路径加载MIDI文件,同时处理加载失败的异常情况:

guard let midiFileURL = Bundle.main.url(forResource: "yourMidiFile", withExtension: "mid"),
      let midiFile = try? AKMIDIFile(url: midiFileURL) else {
    print("MIDI文件加载失败")
    return
}

3. 解析音轨并转换为Note数组

由于是单轨MIDI,直接取第一个音轨,遍历其中的MIDI事件,过滤出有效的NoteOn事件(忽略力度为0的事件,这类事件实际代表音符结束),再转换为自定义Note对象:

guard let targetTrack = midiFile.tracks.first else {
    print("MIDI文件中无有效音轨")
    return
}

var noteList: [Note] = []

for event in targetTrack.events {
    // 过滤出有效NoteOn事件(速度>0)
    guard case .noteOn(let noteNumber, let velocity, _) = event, velocity > 0 else {
        continue
    }
    
    // 填充Note结构体的各个属性
    let noteName = AKMIDIConstant.noteName(from: noteNumber)
    // 以A4(MIDI编号69)为基准计算半音距离,可根据需求调整基准音
    let semitoneDistance = Float(noteNumber - 69)
    let noteFrequency = AKMIDIConverters.frequency(forNoteNumber: Float(noteNumber))
    
    noteList.append(Note(name: noteName, distance: semitoneDistance, frequency: noteFrequency))
}

4. 你的自定义Note结构体

直接使用你定义的结构体即可:

struct Note {
    var name: String = ""
    var distance: Float = 0.0
    var frequency: Float = 0.0
}

关键细节说明

  • 音符名称:AKMIDIConstant.noteName(from:)会返回如"C4"、"D#5"这类标准音乐记谱名称,符合通用习惯。
  • 半音距离:示例以A4为基准,若需要以其他音为基准(比如C4对应MIDI编号60),直接修改基准编号即可。
  • 频率计算:AKMIDIConverters.frequency(forNoteNumber:)基于十二平均律计算,精度可靠。
  • 事件过滤:必须忽略力度为0的NoteOn事件,这是MIDI规范中常用的音符结束标记,避免重复统计。

内容的提问来源于stack exchange,提问作者N0ctrn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:15:12