AUSampler stuck notes

Hi,

I'm developing an AUSampler based application for iOS12.4x.
It manages incoming MIDI messages through the MIDIReadProc handler. Initially I sent notifications from this handler to have it respond faster and allow uncoupling with the AU rendering thread.
However I noticed stuck notes (as if some note off messages werent't handled) when playing many note repeatedly at the same time.
I then called MusicDeviceMIDIEvent directly from MIDIReadProc handler, however it didn't fix the problem.
It seems the AU Sampler cannot manage such load ?

Is there a new AUv3 sampler unit available that could help ?
I'm on High Sierra so I can't develop for iOS 13+.

I both manage noteoff (0x8) and 0 velocity note on (0x9) messages to stop playing (calling MusicDeviceMIDIEvent with 0 velocity value).

Accepted Reply

After looking into audioKit source code and finding articles about managing MIDIPacket indeed they contain a tuple data. We have to check its total size and then iterating over the pointer to get messages (status byte followed by one or two value bytes). It now works

Replies

Using new AVAudioUnitSampler (and AVAudioEngine/AVAudioSession instead AUGraph) didn't helped.
Using AudioKit 4.8 and Wrapper (AKMidiSampler/AKAppleSampler) for Apple's AVAudioUnitSampler fixed the problem, so the problem may come from the way I manage midi messages (however it is similar as how AudioKit does).
The code I'm using :

Code Block
err = MIDIInputPortCreateWithBlock(client, portName, &port, onMIDIMessageReceived)


And handler defined as :

Code Block
func onMIDIMessageReceived(message: UnsafePointer<MIDIPacketList>, srcConnRefCon: UnsafeMutableRawPointer?) {
let packetList: MIDIPacketList = message.pointee
let n = packetList.numPackets
var packet = packetList.packet
for _ in 0 ..< n {
let mes: UInt8 = packet.data.0 & 0xF0
let ch: UInt8 = packet.data.0 & 0x0F
if mes == 0x90 && packet.data.2 != 0 {
let noteNo = packet.data.1
let velocity = packet.data.2
DispatchQueue.main.async {
self.delegate?.noteOn(ch: ch, note: noteNo, vel: velocity)
}
} else if (mes == 0x80 || mes == 0x90) {
let noteNo = packet.data.1
let velocity = packet.data.2
DispatchQueue.main.async {
self.delegate?.noteOff(ch: ch, note: noteNo, vel: velocity)
}
}
let packetPtr = MIDIPacketNext(&packet)
packet = packetPtr.pointee
}
}

I also tested without DispatchQueue.main.async (using it instead in the delegate when calling the sampler methods), same problem.

After looking into audioKit source code and finding articles about managing MIDIPacket indeed they contain a tuple data. We have to check its total size and then iterating over the pointer to get messages (status byte followed by one or two value bytes). It now works