2015-06-02 26 views
0

我上的一个小程序工作以监视来自NI Maschine 2.(MIDI输出想法是程序变化信息添加到NI机和使用的一些部件他们触发VJ-efects和一些其他的东西)CoreMIDI:midiReadProc只接收3个数据包的第一数据包具有相同时间戳

下面的测试情况给出了问题。 NI机器上的测试部分在第一拍时有一个音符和两个节目改变信息,在第16秒后有第二个音符。

我击球的时候开始,捕捉与MIDI监视器工具我看到输出: results from MIDI Monitor

这是正确的。恰恰是Maschine发送的是什么。 - 注意两个控制变更和下一个数据包的注释具有相同的时间戳。

当我做我的简单的虚拟客户端相同(见下面的代码)我得到这个: Results from my Virtual Client

  • ,你可以看到第二个控制变更和注意在分组丢失!

通知第二个第三行(歌曲位置和继续)也具有相同的时间戳,并在两种情况下都收到。

如果你不嫌麻烦,直到读了这一点,你就会明白这个问题。 我知道我的simpel虚拟客户端和MIDI监视器程序之间的巨大差异是使用CoreMidi服务插件来监听MIDI输出。 这仅仅是CoreMidi的限制还是我错过了一些东西?

下面以虚拟客户端代码: 它剥夺了基本需要接收来自NI Mashine东西。 init设置虚拟客户端,目标并设置UniqueID。 如上所示,readproc正在生成缺少数据包的NSLOG消息。

任何建议都非常赞赏

// 
// VirtualClient.m 
// testMidiReadProc 
// 
// Created by Rob Keeris on 02/06/15. 
// Copyright (c) 2015 Connector. All rights reserved. 
// 

#import "VirtualClient.h" 

@implementation VirtualClient 


SInt32   virtualinUniqueId = 1234567893; 
MIDIClientRef client; 
MIDIEndpointRef virtualIn; 

NSString * midiTypeName(Byte midiType){ 
    switch (midiType) { 
     case 0x80: return @"Note Off"; 
     case 0x90: return @"Note On"; 
     case 0xB0: return @"ControlChange"; 
     case 0xC0: return @"ProgramChange"; 
     case 0xF2: return @"SongPosition"; 
     case 0xF8: return @"Clock"; 
     case 0xFA: return @"Start"; 
     case 0xFB: return @"Continue"; 
     case 0xFC: return @"Stop"; 
     case 0x00: return @"InvalidType"; 
     default: return [NSString stringWithFormat:@"Unlisted midiType 0x%02x",midiType]; 
    } 
} 

void midiReadProc (const MIDIPacketList *list, void *procRef, void *srcRef) { 

    const MIDIPacket *packet = &list->packet[0]; // ?defined as const to avoid compiler warnings? 
    for (int i = 0; i < list->numPackets; i++) { 

     if (packet->data[0] != 0xF8){ // filter out Clock messages 

      NSLog(@"%llu packet(%i of %i) %@(0x%02x) 0x%02x 0x%02x", 
        packet->timeStamp,i+1,list->numPackets,midiTypeName(packet->data[0]),packet->data[0],packet->data[1],packet->data[2]); 
     } 

     packet = MIDIPacketNext (packet); 
    } 
} 

- (id)init{ 
    OSStatus result; 

    self = [super init]; 
    if (self) { 
     // Create the client 
     result = MIDIClientCreate(CFSTR("myVirtualClient"), NULL, NULL, &client); 
     if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 
     // create the destination 
     result = MIDIDestinationCreate(client, CFSTR("myVirtualDestination"), midiReadProc,(__bridge void *)(self),&virtualIn); 
     if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 
     // set the UniqueId so i dont have to toggele the output in NI Maschine 
     result = MIDIObjectSetIntegerProperty(virtualIn, kMIDIPropertyUniqueID, virtualinUniqueId); 
     if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 

    } 
    return self; 
} 

@end 

额外的信息 把这个额外的测试响应基因的提示时看到 取出0xF8的过滤器,并使用一个printf代替的NSLog发生了什么();从MIDI监视器

输出: enter image description here

输出形成我的代码:

enter image description here

没有办法解决,但现在一个时钟接收到具有相同的时间戳。

在这个测试中的节奏被设置为50 BPM(因此每50毫秒一个时钟) 我检查是否有时钟脉冲丢失,但事实并非如此。所有时钟都会收到大约预期的时间戳。

+0

您是否找到解决方案?我也遇到了同样的时间戳邮件 –

回答

0

这里点评。 既然你这样做:

const MIDIPacket *packet = &list->packet[0]; // ?defined as const to avoid compiler warnings? 

for (int i = 0; i < list->numPackets; i++) { 

应该

for (int i = 0; i < list->numPackets; ++i) { 

但是,这并不解决您的问题。 当您删除过滤“if”(除了获得大量F8s)之后会发生什么? 在黑暗中拍摄:尝试使用printf来查看NSLog是否不合格。

+0

感谢您的回复。我将这个建议的结果添加到了问题中。恐怕它不会带来很多额外的线索。 –

0

我想我找到了问题是wat。 数据包不会丢失,但会放在第一个包的数据[0]中。另一篇文章(正确使用midipacketlistadd-coremidi)让我走上正轨。

enter image description here

此测试我把3个注释和2个中的第一条上控制变更消息和单不第十六和一个烧毛控制改变的弦。

那么,它的清除控制转变将持有2个控制转换和3个NoteOn消息。 NoteOf消息包含3个NoteOf。

这是Coremidi中的错误还是另一方程序员的不良行为?

编辑 这是解决。正如Kurt指出的那样正常,你必须为一个数据包中的多条消息做好准备。所以你必须做下面的事情。

感谢您的所有意见。

#import "VirtualClient.h" 

@implementation VirtualClient 


SInt32   virtualinUniqueId = 1234567893; 
MIDIClientRef client; 
MIDIEndpointRef virtualIn; 
MIDITimeStamp previousTimeStamp; 

struct MIDIMessage 
{ 
    char* description; 
    int messageLength; 
}; 
typedef struct MIDIMessage MIDIMessage; 

// incomplete list of possible messages but suffucient for this test 
const MIDIMessage x00 = {"Error! or Unlisted",0}; 
const MIDIMessage x80 = {"Note Off",3}; 
const MIDIMessage x90 = {"Note On",3}; 
const MIDIMessage xB0 = {"ControlChange",3}; 
const MIDIMessage xC0 = {"ProgramChange",2}; 
const MIDIMessage xF2 = {"SongPosition",3}; 
const MIDIMessage xF8 = {"Clock",1}; 
const MIDIMessage xFA = {"Start",1}; 
const MIDIMessage xFB = {"Continue",1}; 
const MIDIMessage xFC = {"Stop",1}; 

MIDIMessage midiType(Byte midiType){ 

    switch (midiType) { 

     case 0x80: return x80; 
     case 0x90: return x90; 
     case 0xB0: return xB0; 
     case 0xC0: return xC0; 

     case 0xF2: return xF2; 
     case 0xF8: return xF8; 
     case 0xFA: return xFA; 
     case 0xFB: return xFB; 
     case 0xFC: return xFC; 

     default: return x00; 
    } 

} 

void midiReadProc (const MIDIPacketList *list, void *procRef, void *srcRef) { 

int index; 
int messageLength; 
const MIDIPacket *packet = &list->packet[0]; 

// handle packets 
for (int i =0;i< list->numPackets;++i){ 

    // handle messages in each packet 
    index = 0; 
    while (index < packet->length){ 

     messageLength = midiType(packet->data[index]).messageLength; 

     if (messageLength){ 

      printf("%llu packet(%i of %i) %s", packet->timeStamp,i+1,list->numPackets,midiType(packet->data[index]).description); 
      for (int x =1; x< messageLength;x++) 
       printf(" data[%i]:0x%02x",x,packet->data[index+x]); 
      printf("\n"); 
      index+=messageLength; 

     } 
     else{ 

      printf("Unlisted comand! printing rest of bytes"); 
      for (int i =index; i < packet->length;i++) 
       printf("0x%02x ",packet->data[i]); 
      printf("\n"); 
      break; 

     } 

    } 
    packet = MIDIPacketNext (packet); 
    } 
} 

- (id)init{ 
    OSStatus result; 
    self = [super init]; 
    if (self) { 
     // Create the client 
     result = MIDIClientCreate(CFSTR("myVirtualClient"), NULL, NULL, &client); 
     if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 
     // create the destination 
     result = MIDIDestinationCreate(client, CFSTR("myVirtualDestination"), midiReadProc,(__bridge void *)(self),&virtualIn); 
     if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 
     // set the UniqueId so i dont have to toggele the output in NI Maschine 
     result = MIDIObjectSetIntegerProperty(virtualIn, kMIDIPropertyUniqueID, virtualinUniqueId); 
    if (result !=0) NSLog(@"MIDIClientCreate error %i",result); 

    } 
    return self; 
} 

@end 
+0

这不是CoreMIDI中的错误,也不是MIDI数据的发送者。这很正常。 MIDIPacket允许包含一个或多个MIDI消息(或部分sysex消息)。您需要使用长度字段,解析数据的许多字节并解释它们。 –

+0

感谢您指出这一点。下一次我会更加小心,在使用bug之前仔细想一想。这是因为我找不到正确使用的例子。那么,不会忘记这一点。 –

相关问题