如何用AudioKit的MIDIPlayer播放MIDI文件?报错-10852求解
解决AudioKit MIDIPlayer播放MIDI文件时的AVAE错误-10852
问题重现
使用AudioKit的MIDIPlayer播放MIDI文件,编写了如下SwiftUI代码:
import SwiftUI import AudioKit struct ContentView: View { @StateObject var midi = MIDIWrapper() var body: some View { Button(action: {midi.play()}, label: {Text("play")}) } } class MIDIWrapper: ObservableObject { let engine = AudioEngine() var instrument = AppleSampler() let player: MIDIPlayer init() { engine.output = instrument try? engine.start() player = MIDIPlayer(audioEngine: engine.avEngine, filename: "cdec.mid") } func play() -> () { player.play() } }
在iPhone 13上运行时出现以下错误:
AVAEInternal.h:109 [AVAudioSequencer.mm:121:-[AVAudioSequencer(AVAudioSequencer_Player) startAndReturnError:]: (impl->Start()): error -10852 MIDIPlayer.swift:play():121:Could not start the sequencer (MIDIPlayer.swift:play():121)
解决方法
1. 配置正确的音频会话
iOS要求音频应用必须提前配置AVAudioSession,获取音频权限并设置合适的播放类别。在MIDIWrapper初始化中添加会话配置:
import SwiftUI import AudioKit import AVFoundation // 需导入AVFoundation class MIDIWrapper: ObservableObject { let engine = AudioEngine() var instrument = AppleSampler() let player: MIDIPlayer init() { // 配置音频会话 do { let session = AVAudioSession.sharedInstance() try session.setCategory(.playback, mode: .default) try session.activate() } catch { print("音频会话配置失败: \(error)") } engine.output = instrument // 捕获AudioEngine启动错误 do { try engine.start() } catch { print("AudioEngine启动失败: \(error)") } player = MIDIPlayer(audioEngine: engine.avEngine, filename: "cdec.mid") } func play() { player.play() } }
2. 验证MIDI文件的项目配置
- 确认
cdec.mid已添加到Xcode项目的目标中:选中文件,查看右侧检查器的Target Membership,确保勾选当前应用目标。 - 检查文件名拼写完全一致:iOS区分文件名大小写,代码中的
"cdec.mid"必须和实际文件名完全匹配。
3. 确保MIDIPlayer加载完成后再调用播放
MIDI文件加载需要时间,可通过异步加载或状态检查避免未初始化完成就调用play:
class MIDIWrapper: ObservableObject { let engine = AudioEngine() var instrument = AppleSampler() var player: MIDIPlayer? init() { // 配置音频会话... engine.output = instrument do { try engine.start() // 异步加载MIDI文件 DispatchQueue.global().async { [weak self] in guard let self = self else { return } self.player = MIDIPlayer(audioEngine: self.engine.avEngine, filename: "cdec.mid") self.player?.load() // 显式触发加载 } } catch { print("AudioEngine启动失败: \(error)") } } func play() { guard let player = player else { print("MIDIPlayer未完成初始化") return } player.play() } }
4. 替换静默错误捕获为显式异常处理
原代码中try? engine.start()会忽略错误,改为do-catch可以获取具体失败原因,帮助排查问题:
do { try engine.start() } catch { print("AudioEngine启动失败详情: \(error.localizedDescription)") }
内容的提问来源于stack exchange,提问作者Jesse
相关产品推荐
相关产品推荐

