Reputation: 1391
I've been working to migrate an older Core MIDI sending implementation to send MIDI 1.0 messages using Apple's newer UMP-aware MIDI Event List API methods.
I've figured out code that runs and should output MIDI clock messages, but when I send it with MIDISendEventList(...)
I see nothing being output from my MIDI interface; there's also no error returned from that method to indicate what the problem is.
Here is the code I'm using:
const ByteCount clockMessageSize = 1;
const UInt32 clockMessage[clockMessageSize] = { (UInt32)0xF8 }; // MIDI clock tick
const MIDITimeStamp timeStamp = mach_absolute_time();
MIDIEventList clockMessageEventList = {};
MIDIEventPacket* clockMessageEventListEndPacket = nullptr;
clockMessageEventListEndPacket = MIDIEventListInit(&clockMessageEventList, kMIDIProtocol_1_0);
clockMessageEventListEndPacket = MIDIEventListAdd(&clockMessageEventList, sizeof(MIDIEventList::packet), clockMessageEventListEndPacket, timeStamp, clockMessageSize, clockMessage);
for (NSUInteger endpointRefIndex = 0; endpointRefIndex < endPointRefsCount; ++endpointRefIndex) {
MIDIObjectRef destinationEndpoint = endPointRefs[endpointRefIndex];
OSStatus midiSendError = MIDISendEventList(outputPortRef, destinationEndpoint, &clockMessageEventList);
if (midiSendError != noErr) {
printf("MIDISendEventList error: %i", (int)midiSendError);
}
}
Inspecting clockMessageEventList.packet
after it has been configured but before it is sent shows:
(248, 0, 0, [... all zeros to index 63])
Does anyone know where I'm going wrong?
Upvotes: 4
Views: 713
Reputation: 70
I don't have enough reputation to reply to the reply asking why the 0x10 fix is necessary, but the reason you need 0x10 is because the event list uses a "universal MIDI packet" format instead of the standard MIDI format.
This format needs a "message type" in the first two bytes - 0x10 is classified as "MIDI 1.0 - System Real Time and System Common Messages". MIDI 1.0 also supports 0x20 (channel voice messages, such as a note on) and 0x30 (data messages for SYSEX).
CoreMIDI also provides functions to generate these 32-bit values, e.g. MIDI1UPSystemCommon would take care of the 0x10 for you, avoiding the need to manually shift bits.
Upvotes: 3
Reputation: 1391
With a bit of additional direction provided by https://stackoverflow.com/a/74248460/8653957 I managed to crack this.
For some reason, the word created for the MIDI clock message needs to be formatted slightly differently, with the first byte being 0x10
, and the second byte being the MIDI clock message:
const ByteCount clockMessageSize = 1;
const UInt32 clockMessage[clockMessageSize] = { 0x10000000 | ((UInt32)message << 16) };
const MIDITimeStamp timeStamp = mach_absolute_time();
MIDIEventList clockMessageEventList = {};
MIDIEventPacket* clockMessageEventListEndPacket = nullptr;
clockMessageEventListEndPacket = MIDIEventListInit(&clockMessageEventList, kMIDIProtocol_1_0);
clockMessageEventListEndPacket = MIDIEventListAdd(&clockMessageEventList, sizeof(MIDIEventList::packet), clockMessageEventListEndPacket, timeStamp, clockMessageSize, clockMessage);
If anyone know why this is, please post it! But here you go, MIDI clock via MIDIEventList.
Upvotes: 2