我无法在CoreMIDI for iOS上找到太多信息.甚至可以通过向设备本身发送消息来播放MIDI声音.iPhone或iPad是否安装了MIDI设备,或者您是否必须将设备连接到接口?
这已经太晚了几年,但它可能会帮助那些帮助我的人.这个网站帮助我从外部MIDI键盘读取MIDI数据.连接是最棘手的部分,但本教程将引导您完成它.
这是我创建的课程.
MIDIController.h
#import <Foundation/Foundation.h>
@interface MIDIController : NSObject
@property NSMutableArray *notes;
@end
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
midiInputCallback函数
midiInputCallback是通过MIDI设备(键盘)发生MIDI事件时调用的功能handleMIDIStatus函数
handleMIDIStatus获取MIDI数据包(其中包含有关播放内容的信息和MIDIController的实例
注意:您需要对MIDIController的引用,以便您可以填充类的属性...在我的情况下,我存储所有播放的音符,按MIDI编号,在一个数组中供以后使用
当statusis 0x90,表示已经触发了一个音符,如果它的速度为0,则认为它没有被播放...我需要添加这个if语句,因为它没有正常运行
注意:我只处理key on和key off事件,所以你会增加switch语句来处理更多的MIDI事件
updateKeyboardButtonAfterKeyPressed方法
我希望这有帮助.
你应该看看pete goodliffe的博客,他慷慨地提供了一个示例项目.它对我开始编程CoreMIDI有很大帮助.
现在关于你的问题,在iOS上,主要使用CoreMIDI网络会话.同一"网络会话"的参与者向彼此发送消息.
例如,您在Mac上配置网络会话(使用音频MIDI设置工具),您可以将iOS设备连接到它.这样,您就可以将消息从iOS发送到OSX主机,反之亦然.
CoreMIDI网络会话依赖于RTP协议来传输MIDI消息,而Bonjour依赖于发现主机.
除此之外,CoreMIDI还可以处理连接到系统的MIDI接口,但默认情况下iOS设备没有物理MIDI接口.如果要将iPhone直接连接到合成器,则必须购买外部硬件.但是,iPad可以通过相机套件连接到兼容USB类的Midi接口.
另外,在独立的iOS设备上,您可以发送使用本地CoreMIDI会话从/向另一个CoreMIDI兼容应用程序发送或接收消息.
| 归档时间: |
|
| 查看次数: |
12113 次 |
| 最近记录: |