如何在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
相关产品推荐
相关产品推荐

