¿Alguien me puede mostrar cómo usar CoreMIDI en iOS?

No he podido encontrar mucha información sobre CoreMIDI para iOS. ¿Es posible reproducir un sonido MIDI enviando un post al dispositivo mismo? ¿El iPhone o iPad tiene un dispositivo MIDI instalado o tiene que tener un dispositivo conectado a la interfaz?

Debe echar un vistazo al blog de Pete Goodliffe y generosamente proporciona un proyecto de ejemplo. Me ayudó mucho comenzar a progtwigr CoreMIDI.

Ahora sobre sus preguntas, en iOS, en su mayoría se utilizan las sesiones de la networking CoreMIDI. Los participantes en una misma "Sesión de networking" envían posts a los demás.

Por ejemplo, configura una session de networking en su Mac (usando la herramienta Audio MIDI Setup) y puede conectar sus dispositivos iOS a ella. De esta forma, puede enviar posts desde iOS a su host de OSX y viceversa.

Las sesiones de la networking CoreMIDI se basan en el protocolo RTP para transportar posts MIDI y Bonjour para descubrir hosts.

Además de eso, CoreMIDI también puede manejar la interfaz MIDI conectada al sistema, pero los dispositivos iOS no tienen una interfaz MIDI física de forma pnetworkingeterminada. Tienes que comprar hardware externo si quieres conectar directamente tu iPhone a un sintetizador. Sin embargo, el iPad se puede conectar a una interfaz Midi compatible con la class USB a través del kit de la camera.

Otra cosa, en un dispositivo iOS independiente, puede enviar el uso de la session CoreMIDI local para enviar o recibir posts desde / hacia otra aplicación compatible con CoreMIDI.

Esto es un par de años demasiado tarde, pero puede ayudar a alguien más como me ayudó. Este website fue fundamental para ayudarme a leer datos MIDI desde un keyboard MIDI externo. Las conexiones son las partes más difíciles, pero este tutorial lo guiará a través de él.

Aquí está la class que he creado.

MIDIController.h

#import <Foundation/Foundation.h> @interface MIDIController : NSObject @property NSMutableArray *notes; @end 

MIDIController.m

 #import "MIDIController.h" #include <CoreFoundation/CoreFoundation.h> #import <CoreMIDI/CoreMIDI.h> #define SYSEX_LENGTH 1024 #define KEY_ON 1 #define KEY_OFF 0 @implementation MIDIController - (id)init { if (self = [super init]) { _notes = [[NSMutableArray alloc] init]; [self setupMidi]; } return self; } - (void) setupMidi { MIDIClientRef midiClient; checkError(MIDIClientCreate(CFSTR("MIDI client"), NULL, NULL, &midiClient), "MIDI client creation error"); MIDIPortRef inputPort; checkError(MIDIInputPortCreate(midiClient, CFSTR("Input"), midiInputCallback, (__bridge_retained void *)self, &inputPort), "MIDI input port error"); checkError(connectMIDIInputSource(inputPort), "connect MIDI Input Source error"); } OSStatus connectMIDIInputSource(MIDIPortRef inputPort) { unsigned long sourceCount = MIDIGetNumberOfSources(); for (int i = 0; i < sourceCount; ++i) { MIDIEndpointRef endPoint = MIDIGetSource(i); CFStringRef endpointName = NULL; checkError(MIDIObjectGetStringProperty(endPoint, kMIDIPropertyName, &endpointName), "String property not found"); checkError(MIDIPortConnectSource(inputPort, endPoint, NULL), "MIDI not connected"); } return noErr; } void midiInputCallback(const MIDIPacketList *list, void *procRef, void *srcRef) { MIDIController *midiController = (__bridge MIDIController*)procRef; UInt16 nBytes; const MIDIPacket *packet = &list->packet[0]; //gets first packet in list for(unsigned int i = 0; i < list->numPackets; i++) { nBytes = packet->length; //number of bytes in a packet handleMIDIStatus(packet, midiController); packet = MIDIPacketNext(packet); } } void handleMIDIStatus(const MIDIPacket *packet, MIDIController *midiController) { int status = packet->data[0]; //unsigned char messageChannel = status & 0xF; //16 possible MIDI channels switch (status & 0xF0) { case 0x80: updateKeyboardButtonAfterKeyPressed(midiController, packet->data[1], KEY_OFF); break; case 0x90: //data[2] represents the velocity of a note if (packet->data[2] != 0) { updateKeyboardButtonAfterKeyPressed(midiController, packet->data[1], KEY_ON); }//note off also occurs if velocity is 0 else { updateKeyboardButtonAfterKeyPressed(midiController, packet->data[1], KEY_OFF); } break; default: //NSLog(@"Some other message"); break; } } void updateKeyboardButtonAfterKeyPressed(MIDIController *midiController, int key, bool keyStatus) { NSMutableArray *notes = [midiController notes]; //key is being pressed if(keyStatus) { [notes addObject:[NSNumber numberWithInt:key]]; } else {//key has been released for (int i = 0; i < [notes count]; i++) { if ([[notes objectAtIndex:i] integerValue] == key) { [notes removeObjectAtIndex:i]; } } } } void checkError(OSStatus error, const char* task) { if(error == noErr) return; char errorString[20]; *(UInt32 *)(errorString + 1) = CFSwapInt32BigToHost(error); if(isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4])) { errorString[0] = errorString[5] = '\''; errorString[6] = '\0'; } else sprintf(errorString, "%d", (int)error); fprintf(stderr, "Error: %s (%s)\n", task, errorString); exit(1); } @end 

Notas adicionales

Función MidiInputCallback

  • midiInputCallback es la function que se llama cuando se produce un evento MIDI a través de un dispositivo MIDI (keyboard)
    NOTA: Aquí es donde puede comenzar a manejar información MIDI

handleMIDIStatus function

  • handleMIDIStatus toma el package MIDI (que contiene la información sobre lo que se jugó y una instancia de MIDIController
    NOTA: necesita la reference a MIDIController para que pueda completar las properties de la class … en mi caso almaceno todas las notas reproducidas, por número MIDI, en una matriz para usarlas más adelante

  • cuando el status es 0x90 , lo que significa que se ha disparado una nota, si tiene una velocidad de 0, se considera que no se ha reproducido … Necesitaba agregar esta instrucción si porque no funcionaba correctamente
    NOTA: solo manejo key on events de key off y key off , por lo que boostía la instrucción switch para manejar más events MIDI

método updateKeyboardButtonAfterKeyPressed

  • Este es un método que solía almacenar notas que se reproducen y elimino notas de esta matriz una vez que se ha liberado la key

Espero que esto ayude.

Hay mucha información disponible sobre el uso de CoreMidi en iOS.

En cuanto a sus preguntas, sí iOS puede enviar MIDI a un dispositivo y sí, puede crear una unidad de audio de muestreo MIDI que responderá a los events MIDI. Ver AudioGraph para get un código de demostración. También el video de Apple docs / WWDC para AUSampler .