Alguém me pode mostrar como usar o CoreMIDI no iOS?

não consegui encontrar muita informação sobre o CoreMIDI para os iOS. É mesmo possível tocar um som MIDI enviando uma mensagem para o próprio dispositivo. O iPhone ou iPad tem um dispositivo MIDI instalado ou você tem que ter um dispositivo conectado à interface com?

Author: bobjamin, 2012-12-19

2 answers

Você deve dar uma olhada no blog do pete goodliffe e ele generosamente fornece um projeto de exemplo. Ajudou-me muito começar a programar o CoreMIDI.

Agora sobre as suas perguntas, sobre os iOS, a maioria das sessões de rede CoreMIDI são usadas. Os participantes de uma mesma "sessão de rede" enviam mensagens uns aos outros.

Por exemplo, configura uma sessão de rede no seu Mac (usando a ferramenta de configuração do MIDI de áudio) e pode ligar os seus dispositivos iOS a ele. Assim, podes enviar mensagens do iOS para a sua máquina OSX e vice-versa.

As sessões da rede CoreMIDI baseiam-se no protocolo RTP para transportar mensagens MIDI e Bonjour para descobrir os servidores.

Ao lado disso, o CoreMIDI também consegue lidar com a interface MIDI ligada ao sistema, mas os dispositivos iOS não têm interface física MIDI por omissão. Você tem que comprar hardware externo se quiser conectar diretamente o seu iPhone a um sintetizador. No entanto, o iPad pode ser conectado a uma interface Midi compatível com a classe USB através do kit de câmara.

Outra coisa, em um dispositivo iOS autônomo, você pode enviar usar a sessão local CoreMIDI para enviar ou receber mensagens de / para outra aplicação compatível CoreMIDI.

 7
Author: FredericK, 2013-01-01 11:57:55
Isto é um par de anos atrasado, mas pode ajudar outra pessoa como me ajudou. Este site foi fundamental para me ajudar a ler os dados MIDI de um teclado MIDI externo. As conexões são as partes mais complicadas, mas este tutorial irá guiá-lo através dele. Eis a classe que criei.

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

Adicional Notas

Função MidiInputCallback

  • midiInputCallback é a função que é chamada quando um evento MIDI ocorre através de um dispositivo MIDI (teclado)
    nota: é aqui que pode começar a lidar com a informação MIDI

Função HandleMIDIStatus

  • handleMIDIStatus pega no Pacote MIDI (que contém a informação sobre o que foi jogado e uma instância do MIDIController
    nota: você precisa da referência a MIDIController para que possa povoar propriedades para o class...in meu caso eu armazeno todas as notas tocadas, pelo número MIDI, em um array para uso mais tarde em

  • Quando o status é 0x90, o que significa que uma nota foi despoletada, se tiver uma velocidade de 0, é considerada não tocada...Precisava de acrescentar isto, porque não estava a funcionar correctamente.
    nota: eu só lido com os Eventos key on e key off, por isso você aumentaria a declaração de mudança para lidar com mais MIDI eventos

UpdateKeyboardButtonAfterKeyPressed Method

  • Este é um método que eu usei para armazenar notas que são tocadas e eu removo notas deste array uma vez que a chave foi lançada
Espero que isto ajude.
 7
Author: 02fentym, 2015-07-17 08:05:04