20

これは、MIDI データを送信する非常に単純な CoreMIDI OS X アプリケーションです。問題は、それが機能しないことです。正常にコンパイルされ、実行されます。エラーは報告されず、クラッシュもしません。作成されたソースが MIDI モニターに表示されます。しかし、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;
}
4

4 に答える 4

27

MIDISourceCreate仮想 MIDI ソースを作成するために呼び出しています。

これは、ソースが他のアプリの MIDI セットアップ UI に表示され、それらのアプリがソースを聞くかどうかを選択できることを意味します。MIDI は、他のアプリがたまたまそこにチャネルしない限り、どの物理 MIDI ポートにも送信されません。また、送信する MIDI の送信先をアプリが選択できないことも意味します。それがあなたの望みだと思います。

MIDISourceCreate のドキュメントには次のように書かれています。

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

したがって、次の 2 つのことを行います。

  • 出力ポートを作成するコードを削除します。あなたはそれを必要としません。
  • に変更MIDISend(outPort, midiOut, pktList): MIDIReceived(midiOut, pktlist)

それはあなたの問題を解決するはずです。

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

  1. MIDIOutputPortCreate()出力ポートを作成するための呼び出し
  2. と を使用MIDIGetNumberOfDestinations()MIDIGetDestination()て目的地のリストを取得し、興味のある目的地を見つけます。
  3. MIDI を 1 つの宛先に送信するには、 を呼び出しますMIDISend(outputPort, destination, packetList)
于 2012-05-13T17:55:40.840 に答える
3

参考までに、これをここに残しておきます。これは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
于 2012-06-24T16:21:51.820 に答える