2012-05-13 15 views
18

यहां एक बेहद सरल CoreMIDI ओएस एक्स एप्लिकेशन है जो MIDI डेटा भेजता है। समस्या यह है कि यह काम नहीं करता है। यह ठीक संकलित करता है, और चलता है। यह कोई त्रुटि रिपोर्ट नहीं करता है, और क्रैश नहीं होता है। निर्मित स्रोत 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 कहां भेज रहा है। मुझे लगता है कि आप यही चाहते हैं।

The documentation for MIDISourceCreate का कहना है:

एक आभासी स्रोत बनाने के बाद, आभासी स्रोत से जुड़े किसी भी ग्राहकों के लिए अपने आभासी स्रोत से मिडी संदेश प्रसारित करने MIDIReceived का उपयोग करें।

  • कोड है कि आउटपुट पोर्ट बनाता निकालें:

तो, दो बातें। आपको इसकी आवश्यकता नहीं है

  • MIDISend(outPort, midiOut, pktList) से MIDIReceived(midiOut, pktlist) बदलें।
  • यह आपकी समस्या का समाधान करना चाहिए।

    तो आउटपुट पोर्ट्स के लिए क्या अच्छा है? यदि आप अपने MIDI डेटा को किसी विशिष्ट गंतव्य पर निर्देशित करना चाहते हैं - शायद एक भौतिक MIDI पोर्ट - आप वर्चुअल MIDI स्रोत नहीं बनाएंगे। इसके बजाय:।

    1. कॉल MIDIOutputPortCreate() एक आउटपुट पोर्ट
    2. उपयोग MIDIGetNumberOfDestinations() और MIDIGetDestination() स्थलों की सूची प्राप्त करने करने के लिए और एक में आपकी रुचि है खोजने के लिए
    3. एक गंतव्य के लिए मिडी भेजने के लिए, फोन MIDISend(outputPort, destination, packetList)
    +6

    क्या मैं MIDI को भेजने के लिए MIDIReceived का उपयोग करना चाहूंगा। उत्कृष्ट स्पष्टीकरण के लिए धन्यवाद। – sixohsix

    +5

    यदि आप MIDI डिवाइस ड्राइवर के संदर्भ में MIDI स्रोत के बारे में सोचते हैं तो यह थोड़ा और समझ में आता है: उस स्थिति में, ड्राइवर को कुछ MIDI (तार पर) प्राप्त हुआ, और इसके बारे में CoreMIDI को बता रहा है। वर्चुअल एमआईडीआई स्रोत बाद में जोड़े गए थे। –

    +2

    +1 आप देवता हैं, कर्ट। –

    2

    मैं इसे अपने संदर्भ के लिए यहां छोड़ रहा हूं। यह एक पूर्ण उदाहरण है जो आपके पर 100% आधारित है, लेकिन दूसरी तरफ (प्राप्त करने), मेरा खराब सी कोड और स्वीकृत उत्तर के सुधार (बेशक) सहित।

    #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

    एक छोटी सी विस्तार है कि दूसरों को छोड़ दे रहे: MIDIPacketListAddकी time पैरामीटर कुछ संगीत क्षुधा के लिए महत्वपूर्ण है।

    यहाँ कैसे आप इसे प्राप्त कर सकते हैं का एक उदाहरण है:

    #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

    आप पाते हैं कि वास्तव में ज्ञात जर्मन सॉफ़्टवेयर हाउस द्वारा उत्पादित एक वास्तव में ज्ञात एप्लिकेशन, यदि आप समय पैरामीटर को सही ढंग से सेट करना भूल जाते हैं तो अपने आने वाले MIDI-CC डेटा को आकर्षित करने से इंकार कर देता है। – gog