Last active
December 25, 2015 09:48
-
-
Save coffindragger/6956330 to your computer and use it in GitHub Desktop.
objc midi parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static void handle_midi_input (const MIDIPacketList *list, void *inputUserdata, void *srcUserdata) | |
{ | |
AppDelegate *self = (__bridge AppDelegate *)inputUserdata; | |
const MIDIPacket *packet = list->packet; | |
for (int i = 0; i < list->numPackets; i++) { | |
[self->midiParser feedPacketData:packet->data :packet->length]; | |
packet = MIDIPacketNext(packet); | |
} | |
} | |
- (void)listenToAllMidiEndpoints | |
{ | |
midiParser = [[MidiParser alloc] init]; | |
[midiParser setDelegate:self]; | |
status = MIDIClientCreate(CFSTR("MyMidiControlledDevice"), NULL, NULL, &midiClient); | |
status = MIDIInputPortCreate(midiClient, CFSTR("Input"), handle_midi_input, (__bridge void*)self, &midiInput); | |
int num_midi = MIDIGetNumberOfDevices(); | |
for (int i=0; i < num_midi; i++) { | |
MIDIEndpointRef src = MIDIGetSource(i); | |
CFStringRef srcName; | |
MIDIObjectGetStringProperty(src, kMIDIPropertyName, &srcName); | |
status = MIDIPortConnectSource(midiInput, src, NULL); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#define kReferenceNoteNumber 69 | |
#define kReferenceNoteFrequency 440 | |
#define kNotesPerOctave 12 | |
@interface MidiParser : NSObject | |
{ | |
id delegate; | |
} | |
@property id delegate; | |
- (id) init; | |
- (int) feedPacketData:(UInt8 *)bytes :(int)num_bytes; | |
- (void)systemMessage:(unsigned char)message; | |
- (void)controllerMessage:(UInt8)controller withValue:(UInt8)value onChannel:(UInt8)channel; | |
- (void)noteOn:(UInt8)noteNumber withVelocity:(UInt8)velocity onChannel:(UInt8)channel; | |
- (void)noteOff:(UInt8)noteNumber withVelocity:(UInt8)velocity onChannel:(UInt8)channel; | |
+ (double)frequencyFromNoteNumber:(UInt8)noteNumber; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "MidiParser.h" | |
@implementation MidiParser | |
@synthesize delegate; | |
- (id) init | |
{ | |
if (self) { | |
} | |
return self; | |
} | |
- (int) feedPacketData:(UInt8 *)bytes :(int)num_bytes | |
{ | |
int read; | |
for (read=1; read < num_bytes; read++) { | |
unsigned char b = bytes[0]; | |
if (b & 0x30) { | |
// status message | |
unsigned char high = (b & 0xF0); | |
unsigned char low = (b & 0x0F); | |
switch (high) { | |
case 0x80: { | |
UInt8 noteNumber = bytes[read++]; | |
UInt8 velocity = bytes[read++]; | |
[self noteOff:noteNumber withVelocity:velocity onChannel:low]; | |
break; | |
} | |
case 0x90: { | |
UInt8 noteNumber = bytes[read++]; | |
UInt8 velocity = bytes[read++]; | |
if (velocity == 0) { | |
[self noteOff:noteNumber withVelocity:velocity onChannel:low]; | |
} else { | |
[self noteOn:noteNumber withVelocity:velocity onChannel:low]; | |
} | |
break; | |
} | |
case 0xB0: { | |
UInt8 controller = bytes[read++]; | |
UInt8 value = bytes[read++]; | |
[self controllerMessage:controller withValue:value onChannel:low]; | |
break; | |
} | |
case 0xF0: { | |
if (low == 0) { | |
// skip system exclusive "sysex" messages | |
} | |
else { | |
// 0xF0 .. 0xF7 - system common messages | |
// 0xF8 .. 0xFF - system realtime messages | |
[self systemMessage:b]; | |
} | |
break; | |
} | |
default: { | |
//fall through and skip this message | |
} | |
} | |
} else { | |
//skip data we dont care about | |
} | |
} | |
return read; | |
} | |
- (void)systemMessage:(unsigned char)message | |
{ | |
if ([delegate respondsToSelector:@selector(systemMessage:)]) { | |
[delegate systemMessage:message]; | |
} | |
} | |
- (void)controllerMessage:(UInt8)controller withValue:(UInt8)value onChannel:(UInt8)channel | |
{ | |
if ([delegate respondsToSelector:@selector(controllerMessage:withValue:onChannel:)]) { | |
[delegate controllerMessage:controller withValue:value onChannel:channel]; | |
} | |
} | |
- (void)noteOn:(UInt8)noteNumber withVelocity:(UInt8)velocity onChannel:(UInt8)channel | |
{ | |
if ([delegate respondsToSelector:@selector(noteOn:withVelocity:onChannel:)]) { | |
[delegate noteOn:noteNumber withVelocity:velocity onChannel:channel]; | |
} | |
} | |
- (void)noteOff:(UInt8)noteNumber withVelocity:(UInt8)velocity onChannel:(UInt8)channel | |
{ | |
if ([delegate respondsToSelector:@selector(noteOff:withVelocity:onChannel:)]) { | |
[delegate noteOff:noteNumber withVelocity:velocity onChannel:channel]; | |
} | |
} | |
+ (double)frequencyFromNoteNumber:(UInt8)noteNumber | |
{ | |
double offset = (noteNumber - kReferenceNoteNumber) / (double) kNotesPerOctave; | |
return kReferenceNoteFrequency * pow(2.0, offset); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment