forked from wiffbi/Kimidi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMIDIController.m
155 lines (134 loc) · 4.02 KB
/
MIDIController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// MIDIController.m
// Kimidi
//
// Created by Richard Schreiber on 21.09.11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "MIDIController.h"
@implementation MIDIController
- (id) init
{
virtualInput = [[PYMIDIVirtualSource alloc] initWithName:@"Kimidi Input"];
[virtualInput addSender:self];
virtualOutput = [[PYMIDIVirtualDestination alloc] initWithName:@"Kimidi Output"];
[virtualOutput addReceiver:self];
// create array for MIDIPacketTimed to check for feedback loop
midiMessages = [[NSMutableArray alloc] init];
return self;
}
- (void) send: (int) channel: (int) key: (int) value
{
//NSLog(@"sendMIDI via ");
//NSLog([virtualInput displayName]);
MIDIPacketList packetList;
MIDIPacket *packetPtr = MIDIPacketListInit(&packetList);
unsigned char midiData[3];
midiData[0] = channel;
midiData[1] = key;
midiData[2] = value;
UInt64 timestamp = AudioGetCurrentHostTime();
packetPtr = MIDIPacketListAdd(&packetList, sizeof packetList, packetPtr, timestamp, 3, (const Byte *)&midiData);
//NSLog(@"%llX", timestamp);
// suppress MIDI feedback-loop
/*
add midiData to list with AudioGetCurrentHostTime()
if midiData is received, ignore it, if it is the same
the same is:
channel the same
key the same
value the same of if channel == 144: both values > 0 or both values == 0
during lookup, remove messages that are to old (usually older than 250ms)
*/
//NSArray *timedMIDIPacket;
//timedMIDIPacket = [NSArray arrayWithObjects: midiData, nil];
MIDIPacketTimed *mpt = [[MIDIPacketTimed alloc] init];
[mpt setChannel:channel];
[mpt setKey:key];
[mpt setValue:value];
[mpt setTimestamp:timestamp];
NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[midiMessages count]];
unsigned count = [midiMessages count];
while (count--) {
//for (MIDIPacketTimed *m in midiMessages) {
MIDIPacketTimed *m = [midiMessages objectAtIndex:count];
if (![m olderThan : timestamp]) {
[itemsToKeep addObject:m];
}
else {
[m autorelease];
}
}
[midiMessages setArray:itemsToKeep];
/*
unsigned count = [midiMessages count];
NSLog(@"send-count: %d", count);
while (count--) {
MIDIPacketTimed *m = [midiMessages objectAtIndex:count];
if ([m olderThan : timestamp]) {
[midiMessages removeObjectAtIndex:count];
[m release];
return;
}
}
*/
[midiMessages addObject:mpt];
//NSLog(@"send: %d, %d, %d", channel, key, value);
[virtualInput processMIDIPacketList:&packetList sender:self];
}
- (void)processMIDIPacketList:(MIDIPacketList*)packetList sender:(id)sender
{
// route MIDI in back to out - feedback loop, as Live always sends MIDI in to MIDI out for controllers
//NSLog(@"receiveMIDI via ");
//NSLog([virtualOutput displayName]);
MIDIPacket *packet = &packetList->packet[0];
//NSLog(@"packet: %d", packet->data[0]);
int channel, key, value;
channel = packet->data[0];
key = packet->data[1];
value = packet->data[2];
if (channel == 144 && value > 0)
{
// values over 0 fix at 127
value = 127;
}
//NSLog(@"received: %d, %d, %d", channel, key, value);
MIDIPacketTimed *mpt = [[MIDIPacketTimed alloc] init];
[mpt setChannel:channel];
[mpt setKey:key];
[mpt setValue:value];
[mpt setTimestamp:AudioGetCurrentHostTime()];
bool forwardMIDI = TRUE;
NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[midiMessages count]];
unsigned count = [midiMessages count];
while (count--) {
//for (MIDIPacketTimed *m in midiMessages) {
MIDIPacketTimed *m = [midiMessages objectAtIndex:count];
if (![mpt equals: m]) {
[itemsToKeep addObject:m];
}
else {
[m autorelease];
forwardMIDI = FALSE;
}
}
[midiMessages setArray:itemsToKeep];
/*
unsigned count = [midiMessages count];
NSLog(@"count: %d", count);
while (count--) {
MIDIPacketTimed *m = [midiMessages objectAtIndex:count];
if ([mpt equals:m]) {
NSLog(@"break feedback loop");
[midiMessages removeObjectAtIndex:count];
[m autorelease];
return;
}
}
*/
if (forwardMIDI) {
//NSLog(@"forward MIDI");
[self send: channel : key : value];
}
}
@end