2015-06-02 25 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之前仔細想一想。這是因爲我找不到正確使用的例子。那麼,不會忘記這一點。 –

相關問題