在 iOS 应用程序中调试 MIDI

Debugging MIDI in iOS app

我正在尝试在我的 iOS 应用程序中实施 CoreMIDI,但我现在无法尝试调试它。目前我有一个 UILabel,只要调用我的 MIDI 回调就会更新。但是,我的 UILabel 永远不会更新!我不确定为什么会这样,我猜这是我在 MIDI 初始化中定义某些东西的方式或我调用 UILabel 的方式。我仍在尝试解决这个问题,但是否有更好的方法在 iOS 应用程序上调试 MIDI(因为 iOS 设备只有一个端口,并且只能使用该端口连接到计算机或给定时间的 MIDI 控制器)。

我是如何创建 MIDI 客户端的:

Check(MIDIClientCreate(CFSTR("Yun Client"), NULL, NULL , &client));
Check(MIDIOutputPortCreate(client, CFSTR("Yun Output Port"), &outputPort));
Check(MIDIInputPortCreate(client, CFSTR("Yun Input Port"), MIDIInputCallback, 
                         (__bridge void *)self, &inputPort));
unsigned long sourceCount = MIDIGetNumberOfSources();

CFStringRef endpointName;
for (int i = 0; i < sourceCount; ++i) {
    MIDIEndpointRef endPoint = MIDIGetSource(i);
    endpointName = NULL;
    Check(MIDIObjectGetStringProperty(endPoint, kMIDIPropertyName, &endpointName));
    Check(MIDIPortConnectSource(inputPort, endPoint, NULL));
    [param addToMIDIInputsArray:[NSString stringWithFormat:@"%@", endpointName]];
}

我的 MIDI 回调:

// MIDI receiver callback
static void MIDIInputCallback(const MIDIPacketList *pktlist, 
                              void *refCon, void *connRefCon) {
    SynthViewController *vc = (__bridge SynthViewController*)refCon;

    MIDIPacket *packet = (MIDIPacket *)pktlist->packet;

    Byte midiCommand = packet->data[0] >> 4;
    NSInteger command = midiCommand;

    Byte noteByte = packet->data[1] & 0x7F;
    NSInteger note = noteByte;

    Byte velocityByte = packet->data[2] & 0x7F;
    float velocity = [[NSNumber numberWithInt:velocityByte] floatValue];

    // Note On event
    if (command == 9 && velocity > 0) {
        [vc midiKeyDown:(note+4) withVelocity:velocity];
    } 
    // Note off event
    else if ((command == 9 || command == 8) && velocity == 0) {
        [vc midiKeyUp:(note+4)];
    }

    [vc.logLabel addLogLine:[NSString stringWithFormat:@"%lu - %lu - %lu", 
                            (long)command, (long)note, (long)velocityByte]];
}

addLogLine方法:

- (void)addLogLine:(NSString *)line {
    NSString *str = [NSString stringWithFormat:@"%d - %@", _cnt++, line];
    _logLabel.text = str;
}

任何帮助都很棒!谢谢

MIDIInputPortCreate 的 header 文档说:

readProc will be called on a separate high-priority thread owned by CoreMIDI.

您只能在主线程上更新 UIKit。

在解析传入的 MIDI 数据后,使用 dispatch_async 将控制转移到主线程。

static void MIDIInputCallback(const MIDIPacketList *pktlist, 
                          void *refCon, void *connRefCon) {
    SynthViewController *vc = (__bridge SynthViewController*)refCon;
    // ...

    dispatch_async(dispatch_get_main_queue(), ^{
        // Note On event
        if (command == 9 && velocity > 0) {
           [vc midiKeyDown:(note+4) withVelocity:velocity];
        } 
        // Note off event
        else if ((command == 9 || command == 8) && velocity == 0) {
           [vc midiKeyUp:(note+4)];
        }

        [vc.logLabel addLogLine:[NSString stringWithFormat:@"%lu - %lu - %lu", (long)command, (long)note, (long)velocityByte]];
    });
}