AudioKit Apple Sequencer初始化报错:Invalid beat range or track is empty
问题描述
已将AudioKit SDK接入简易项目,参照AudioKit Cookbook中的鼓序列器示例创建基础序列。已复制示例中的MIDI和音频文件到Xcode项目并确认路径正确,但初始化AppleSequencer时始终报错:
2023-06-11 20:13:22.124246-0600 NoteFlow[4788:2349120] [midi] MIDI.swift:init():52:Initializing MIDI (MIDI.swift:init():52)
2023-06-11 20:13:22.694782-0600 NoteFlow[4788:2349120] [seq] SequenceTrack.cpp:977 Clear: Invalid beat range or track is empty
已注释所有sequencer相关代码、开启后台音频模式,问题仍存在。代码如下:
import AudioKit import AudioKitEX import AVFoundation class DrumSequencerConductor: ObservableObject, HasAudioEngine { let engine = AudioEngine() let drums = MIDISampler(name: nil) var sequencer: AppleSequencer = AppleSequencer(fromURL: Bundle.main.url(forResource: "4tracks", withExtension: "mid")!) init() { engine.output = drums do { let clapURL: URL = Bundle.main.url(forResource: "clap_D#1", withExtension: "wav", subdirectory: "Samples")! let clapFile = try AVAudioFile(forReading: clapURL) let snareURL: URL = Bundle.main.url(forResource: "snare_D1", withExtension: "wav", subdirectory: "Samples")! let snareFile = try AVAudioFile(forReading: snareURL) let hihatURL: URL = Bundle.main.url(forResource: "closed_hi_hat_F#1", withExtension: "wav", subdirectory: "Samples")! let hihatFile = try AVAudioFile(forReading: hihatURL) try drums.loadAudioFiles([ clapFile, snareFile, hihatFile ]) } catch { print("error while finding audio files \(error)") } // sequencer.clearRange(start: Duration(beats: 0), duration: Duration(beats: 100)) // sequencer.debug() // sequencer.setGlobalMIDIOutput(drums.midiIn) // sequencer.enableLooping(Duration(beats: 4)) // sequencer.setTempo(150) // sequencer.tracks[0].add(noteNumber: 60, velocity: 100, position: Duration(beats: 0), duration: Duration(beats: 1)) // sequencer.tracks[0].add(noteNumber: 60, velocity: 100, position: Duration(beats: 1), duration: Duration(beats: 1)) // sequencer.tracks[3].add(noteNumber: 30, velocity: 127, position: Duration(beats: 2.5), duration: Duration(beats: 0.5)) // for i in 0...40 { // sequencer.tracks[0].add(noteNumber: MIDINoteNumber(i), velocity: 100, position: Duration(beats: 0), duration: Duration(beats: 1)) // } } }
解决方案
1. 检查MIDI文件有效性
报错核心提示“Invalid beat range or track is empty”,大概率是4tracks.mid文件本身存在问题:
- 用MIDI编辑工具(如GarageBand、MidiEditor)打开文件,确认至少有一条包含有效节拍范围的轨道,文件本身不是空的。
- 若原文件无效,重新导出示例中的MIDI文件,或创建一个包含4小节空白轨道的测试MIDI文件替换。
2. 安全初始化AppleSequencer
当前代码在属性定义阶段强制解包文件URL,且初始化逻辑早于init()执行,容易引发隐性问题。修改为在init()中安全初始化:
var sequencer: AppleSequencer? init() { engine.output = drums do { // 音频文件加载逻辑保留... // 安全加载MIDI文件 guard let midiURL = Bundle.main.url(forResource: "4tracks", withExtension: "mid") else { print("MIDI文件未找到") return } sequencer = try AppleSequencer(fromURL: midiURL) // 后续操作需添加可选绑定 if let seq = sequencer { seq.setGlobalMIDIOutput(drums.midiIn) seq.enableLooping(Duration(beats: 4)) seq.setTempo(150) // 其他sequencer配置代码 } } catch { print("初始化错误: \(error)") } }
3. 确认文件的Bundle配置
即使路径正确,Xcode可能漏加文件到目标Bundle:
- 选中
4tracks.mid和Samples文件夹下的音频文件,在右侧“File Inspector”中,确认“Target Membership”已勾选项目目标。 - 添加Samples文件夹时,选择“Create folder references”而非“Create groups”,否则
subdirectory: "Samples"无法正确定位文件。
4. 用空序列器验证逻辑
若MIDI文件问题暂时无法解决,可先创建空序列器验证基础逻辑:
sequencer = AppleSequencer() // 添加对应数量的空轨道 sequencer?.newTrack() sequencer?.newTrack() sequencer?.newTrack() sequencer?.newTrack() // 再执行音符添加等操作
若此方式无报错,即可确认问题出在导入的MIDI文件上。
内容的提问来源于stack exchange,提问作者iamluisg
相关产品推荐
相关产品推荐

