AVAudioSequencer.tempoTrack not sending SetTempo messages

I'm trying to get tempo related messages from the AVAudioSequencer.tempoTrack.


class TempoHandler {
    private var midiEndpoint = MIDIEndpointRef()
    private var midiClient = MIDIClientRef()
    private let sequencer: AVAudioSequencer

    public init(sequencer: AVAudioSequencer) {
        self.sequencer = sequencer
    }

    func setup() {
        var status = MIDIClientCreateWithBlock("TempoHandler.Client" as CFString, &midiClient, nil)
        try checkStatus(status: status, error: SequencerMIDIContextError.createMidiClient)

        status = MIDIDestinationCreateWithBlock(midiClient, "TempoHandler.In" as CFString, &midiEndpoint, midiIO)
        try checkStatus(status: status, error: SequencerMIDIContextError.createMidiDestination)

        sequencer.tempoTrack.destinationMIDIEndpoint = midiEndpoint
    }

    private func midiIO(_ packetList: UnsafePointer<MIDIPacketList>, _ src: UnsafeMutableRawPointer?) {
        let packets = packetList.pointee
        var packet = packets.packet
        for _ in 0 ..< packets.numPackets {
            print("TempoHandler received " + String(format:"%02X", packet.data.0))
            packet = MIDIPacketNext(&packet).pointee
        }
    }
}
  • My sequencer is fully loaded with a MIDI file before I call setup() then sequencer.prepareToPlay() if that matters.

  • The MIDI file contains multiple SetTempo meta messages that are audibly well handled by the sequencer.

  • When instead setting my midiEndpoint as a destination to another track (sequencer.tracks[0]), my handler does output note messages.

But with the tempo track, no MIDI message is received. Is there something I'm missing ?

[post error]

I tried both variations:

  • load my MIDI file in the sequencer with the AVMusicSequenceLoadOptions.smf_ChannelsToTracks option and listen to both the tempoTrack and the last track of the tracks array. I would expect to receive meta messages on either this last track or tempoTrack, because the doc states:

/** @typedef AVMusicSequenceLoadOptions @abstract Determines whether data on different MIDI channels is mapped to multiple tracks, or if the tracks are preserved as-is. @discussion If AVMusicSequenceLoadSMF_ChannelsToTracks is set, the loaded MIDI Sequence will contain a tempo track, one track for each MIDI channel that is found in the SMF, and one track for SysEx and/or MetaEvents (this will be the last track in the sequence).

If AVMusicSequenceLoadSMF_ChannelsToTracks is not set, the loadad MIDI Sequence will contain one track for each track that is found in the SMF, plus a tempo track (if not found in the SMF).

API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0)) */

  • use MIDIDestinationCreateWithProtocol as MIDIDestinationCreateWithBlock is deprecated for iOS 14+

Unfortunately with no success.

[comment error]

AVAudioSequencer.tempoTrack not sending SetTempo messages
 
 
Q