Audiokit 定序器停止时AKMIDI采样器崩溃

Audiokit 定序器停止时AKMIDI采样器崩溃,audiokit,audiotoolbox,coremidi,Audiokit,Audiotoolbox,Coremidi,当停止音序器时,我的应用程序中出现间歇性崩溃。我的应用程序使用一个自定义的基于AudioToolbox的MusicSequencer,连接AKMIDISampler作为其MIDI端点。我已经跟踪到了AKMIDISampler的func句柄(事件:AKMIDIEvent)获取一个空事件(即event.internalData.count==0)。因为采样器是“硬连线”的,可以说,作为端点,我真的不确定如何调试它,因为我看不到序列试图发送什么(或者为什么它显然发送一个空事件) 我能够通过破解我自己的

当停止音序器时,我的应用程序中出现间歇性崩溃。我的应用程序使用一个自定义的基于AudioToolbox的MusicSequencer,连接AKMIDISampler作为其MIDI端点。我已经跟踪到了AKMIDISampler的
func句柄(事件:AKMIDIEvent)
获取一个空事件(即
event.internalData.count==0
)。因为采样器是“硬连线”的,可以说,作为端点,我真的不确定如何调试它,因为我看不到序列试图发送什么(或者为什么它显然发送一个空事件)

我能够通过破解我自己的AK构建来运行它,在这个构建中,我检查了
event.internalData.count
。然而,我的项目()中的另一个问题迫使我使用CocoaPods中的AudioKit,这删除了我的修复(或者更确切地说,hack)

我已经记录了所有向序列中添加事件的函数,但没有一个函数发送空数据

我想知道的一个可能的解释;我最近注意到,启用AddressSanitizer表示在创建用户事件时堆栈缓冲区溢出。我承认我完全搞不清楚我们打算如何在Swift中创建可变长度事件。我似乎无法“合法”创建任何具有
event.length>4
的事件,尽管该结构具有
length
属性。例如,这段代码:

let eventDataBytes = ByteBackpacker.pack(event) // convert to [UInt8]
var midiData = MusicEventUserData()
midiData.length = UInt32(MemoryLayout<Event>.size)
withUnsafeMutablePointer(to: &midiData.data, { pointer in
    for i in 0 ..< eventDataBytes.count {
        print("Can write byte \(i)...")
        pointer[i] = eventDataBytes[i]
    }
})

不确定是什么导致了崩溃(虽然我想我以前见过这种情况),但作为一般调试技巧,如果可以的话,避免将采样器“硬连接”到序列器。如果您能够将MIDI端点设置为AKCallbackInstrument而不是采样器,则可以使用回调函数“手动”触发采样器。使用回调函数的诸多好处之一是,您可以添加断点或打印语句进行调试。另外,通过不硬连接采样器,您可以在停止sequencer之前手动停止采样器。好吧,崩溃本身肯定是由一个空事件击中
handleMIDI
(它读取索引而不进行边界检查)引起的。问题只是这个空洞的事件是什么以及它是如何实现的。我会调查一下AKCallback仪器。谢谢你的提示。现在我已经对Akmidispler进行了子类化,添加了边界检查,因此它不再崩溃。据我所知,直接将sequencer连接到采样器没有任何好处。另一方面,对于使用AKCallbackInstrument,调试MIDI消息只是冰山一角。这是值得你花时间的。下面是一些示例代码,让您开始:回调与AKSampler一样,接收良好的旧MIDI音符事件(状态、音符编号、速度)。你会惊讶于你所需要的改变是如此之少。@MarcusKim,一点也不聪明,实际上就是
if event.data.count>2{//play it}
。但我应该补充一点,我现在正在使用@c_booth推荐的AKCallbackInstruments。到目前为止,一切顺利。
* thread #10, stop reason = EXC_BREAKPOINT (code=1, subcode=0x100bc677c)
    frame #0: 0x0000000100bc677c Spliqs`partial apply for closure #1 in     AKMIDISampler.enableMIDI(_:name:) [inlined] generic specialization <Swift.UInt8> of Swift.Array._getElement(Swift.Int, wasNativeTypeChecked: Swift.Bool, matchingSubscriptCheck: Swift._DependenceToken) -> A at AKMIDISampler.swift:0 [opt]
frame #1: 0x0000000100bc677c Spliqs`partial apply for closure #1 in AKMIDISampler.enableMIDI(_:name:) [inlined] generic specialization <Swift.UInt8> of Swift.Array.subscript.getter : (Swift.Int) -> A at AKMIDISampler.swift:0 [opt]
frame #2: 0x0000000100bc677c Spliqs`partial apply for closure #1 in AKMIDISampler.enableMIDI(_:name:) [inlined] AudioKit.AKMIDISampler.(event=AudioKit.AKMIDIEvent @ 0x00007f94f2693800)(event: AudioKit.AKMIDIEvent) throws -> () at AKMIDISampler.swift:60 [opt]
* frame #3: 0x0000000100bc677c Spliqs`partial apply for closure #1 in AKMIDISampler.enableMIDI(_:name:) at AKMIDISampler.swift:48 [opt]
frame #4: 0x0000000100bc677c Spliqs`partial apply for closure #1 in AKMIDISampler.enableMIDI(_:name:) at AKMIDISampler.swift:0 [opt]
frame #5: 0x0000000100bc4bb8 Spliqs`thunk for @escaping @callee_guaranteed (@unowned UnsafePointer<MIDIPacketList>, @unowned UnsafeMutableRawPointer?) -> () at AKMIDISampler.swift:0 [opt]
frame #6: 0x0000000194f6d7ac CoreMIDI`LocalMIDIReceiverList::HandleMIDIIn(unsigned int, unsigned int, void*, MIDIPacketList const*) + 156
frame #7: 0x0000000194f6d608 CoreMIDI`MIDIProcess::RunMIDIInThread() + 124
frame #8: 0x0000000194f81640 CoreMIDI`XThread::RunHelper(void*) + 20
frame #9: 0x0000000194f85698 CoreMIDI`CAPThread::Entry(CAPThread*) + 88
frame #10: 0x0000000184c25220 libsystem_pthread.dylib`_pthread_body + 272
frame #11: 0x0000000184c25110 libsystem_pthread.dylib`_pthread_start + 292
frame #12: 0x0000000184c23b10 libsystem_pthread.dylib`thread_start +