2012-05-13 4 views
18

ここには、MIDIデータを送信する非常に簡単なCoreMIDI OS Xアプリケーションがあります。問題は、それが動作しないということです。それはうまくコンパイルされ、実行されます。それはエラーを報告せず、クラッシュしません。作成されたソースがMIDIモニターで表示されます。ただし、MIDIデータが出ていませんなぜこの単純なCoreMIDIプログラムはMIDI出力を生成しませんか?

誰かが私がここで間違っていることを教えてもらえますか?

#include <CoreMIDI/CoreMIDI.h> 

int main(int argc, char *args[]) 
{ 
    MIDIClientRef theMidiClient; 
    MIDIEndpointRef midiOut; 
    MIDIPortRef  outPort; 
    char pktBuffer[1024]; 
    MIDIPacketList* pktList = (MIDIPacketList*) pktBuffer; 
    MIDIPacket  *pkt; 
    Byte   midiDataToSend[] = {0x91, 0x3c, 0x40}; 
    int    i; 

    MIDIClientCreate(CFSTR("Magical MIDI"), NULL, NULL, 
        &theMidiClient); 
    MIDISourceCreate(theMidiClient, CFSTR("Magical MIDI Source"), 
        &midiOut); 
    MIDIOutputPortCreate(theMidiClient, CFSTR("Magical MIDI Out Port"), 
         &outPort); 

    pkt = MIDIPacketListInit(pktList); 
    pkt = MIDIPacketListAdd(pktList, 1024, pkt, 0, 3, midiDataToSend); 

    for (i = 0; i < 100; i++) { 
     if (pkt == NULL || MIDISend(outPort, midiOut, pktList)) { 
      printf("failed to send the midi.\n"); 
     } else { 
      printf("sent!\n"); 
     } 
     sleep(1); 
    } 

return 0; 
} 

答えて

25

仮想MIDIソースを作成するには、MIDISourceCreateを呼び出してください。

これは、あなたのソースが他のアプリケーションのMIDI設定UIに表示され、それらのアプリがあなたのソースを聴くかどうかを選択できることを意味します。あなたのMIDIは物理的なMIDIポートに送られることはありません。また、あなたのアプリはそれが送信しているMIDIのどこに行くかという選択肢がありません。私はそれがあなたが望んでいると仮定しています。

The documentation for MIDISourceCreateは言う:

仮想ソースを作成した後、仮想ソースに接続されているすべてのクライアントに仮想ソースからのMIDIメッセージを送信するためにMIDIReceivedを使用しています。

  • が出力ポートを作成するコードを削除します。

だから、2つのことを行います。あなたはそれを必要としません。

  • 変更MIDISend(outPort, midiOut, pktList)MIDIReceived(midiOut, pktlist)に変更します。
  • これは問題を解決するはずです。

    出力ポートは何に適していますか? MIDIデータを特定の宛先(おそらく物理的なMIDIポート)に送る場合は、仮想MIDIソースを作成しないでください。代わりに:

    1. 出力ポートを作るために呼び出すMIDIOutputPortCreate()
    2. 使用MIDIGetNumberOfDestinations()MIDIGetDestination()宛先のリストを取得し、あなたが興味のあるものを見つけるために
    3. MIDISend(outputPort, destination, packetList)を呼び出し、1つの宛先にMIDIを送信します。 。
    +6

    決して千年に私はMIDIを送信するためにMIDIReceivedを使用すると思います。優れた説明をありがとう。 – sixohsix

    +5

    MIDIデバイスドライバのコンテキストでMIDIソースを考えると少し意味があります。その場合、ドライバはMIDIを(ワイヤで)受信し、CoreMIDIにそのことを伝えています。仮想MIDIソースは後で追加されました。 –

    +2

    +1あなたは神様です、Kurt。 –

    2

    私は自分自身の参照のためにこれをここに残しています。それはあなたの100%ベースの完全な例ですが、反対側(受信)、私の悪いCコード、受け入れられた回答の修正(もちろん)を含みます。

    #import "AppDelegate.h" 
    
    @implementation AppDelegate 
    
    @synthesize window = _window; 
    
    #define NSLogError(c,str) do{if (c) NSLog(@"Error (%@): %u:%@", str, (unsigned int)c,[NSError errorWithDomain:NSMachErrorDomain code:c userInfo:nil]); }while(false) 
    
    static void spit(Byte* values, int length, BOOL useHex) { 
        NSMutableString *thing = [@"" mutableCopy]; 
        for (int i=0; i<length; i++) { 
         if (useHex) 
          [thing appendFormat:@"0x%X ", values[i]]; 
         else 
          [thing appendFormat:@"%d ", values[i]]; 
        } 
        NSLog(@"Length=%d %@", length, thing); 
    } 
    
    - (void) startSending { 
        MIDIEndpointRef midiOut; 
        char pktBuffer[1024]; 
        MIDIPacketList* pktList = (MIDIPacketList*) pktBuffer; 
        MIDIPacket  *pkt; 
        Byte   midiDataToSend[] = {0x91, 0x3c, 0x40}; 
        int    i; 
    
        MIDISourceCreate(theMidiClient, CFSTR("Magical MIDI Source"), 
            &midiOut); 
        pkt = MIDIPacketListInit(pktList); 
        pkt = MIDIPacketListAdd(pktList, 1024, pkt, 0, 3, midiDataToSend); 
    
        for (i = 0; i < 100; i++) { 
         if (pkt == NULL || MIDIReceived(midiOut, pktList)) { 
          printf("failed to send the midi.\n"); 
         } else { 
          printf("sent!\n"); 
         } 
         sleep(1); 
        } 
    } 
    
    void ReadProc(const MIDIPacketList *packetList, void *readProcRefCon, void *srcConnRefCon) 
    { 
        const MIDIPacket *packet = &packetList->packet[0]; 
    
        for (int i = 0; i < packetList->numPackets; i++) 
        { 
    
         NSData *data = [NSData dataWithBytes:packet->data length:packet->length]; 
         spit((Byte*)data.bytes, data.length, YES); 
    
         packet = MIDIPacketNext(packet); 
        } 
    } 
    
    - (void) setupReceiver { 
        OSStatus s; 
        MIDIEndpointRef virtualInTemp; 
        NSString *inName = [NSString stringWithFormat:@"Magical MIDI Destination"]; 
        s = MIDIDestinationCreate(theMidiClient, (__bridge CFStringRef)inName, ReadProc, (__bridge void *)self, &virtualInTemp); 
        NSLogError(s, @"Create virtual MIDI in"); 
    } 
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
    { 
        MIDIClientCreate(CFSTR("Magical MIDI"), NULL, NULL, 
            &theMidiClient); 
        [self setupReceiver]; 
        [self startSending]; 
    
    } 
    
    @end 
    
    0

    他の人がスキップされていることを少し詳しく:MIDIPacketListAddtimeパラメータがいくつかの音楽のアプリケーションのために重要です。ここで

    は、あなたがそれを取得する方法の例です:

    #import <mach/mach_time.h> 
    MIDITimeStamp midiTime = mach_absolute_time(); 
    

    出典:Apple Documentation

    そして、ここでは他の例に適用されません:

    pktBuffer[1024]; 
    MIDIPacketList *pktList = (MIDIPacketList*)pktBuffer; 
    MIDIPacket *pktPtr = MIDIPacketListInit(pktList); 
    MIDITimeStamp midiTime = mach_absolute_time(); 
    Byte midiDataToSend[] = {0x91, 0x3c, 0x40}; 
    pktPtr = MIDIPacketListAdd(pktList, sizeof(pktList), pktPtr, midiTime, midiDataToSend, sizeof(midiDataToSend)); 
    
    +0

    実際に知られているドイツのソフトウェアハウスによって作成された、実際に知られているアプリケーションが、timeパラメータを正しく設定することを忘れた場合、受信したMIDI-CCデータを描画することを拒否することがあります。 – gog

    関連する問題