-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMidiIo.cpp
More file actions
197 lines (165 loc) · 4.14 KB
/
MidiIo.cpp
File metadata and controls
197 lines (165 loc) · 4.14 KB
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include <MIDI.h>
#include "MidiIo.h"
#define NB_CHANNELS_OUT 2
#define MAX_CHORD_NOTES 4
#define MIDI_CHANNEL_IN 1
BEGIN_MIDI_IO_NAMESPACE
void handleClock();
void handleStart();
void handleStop();
void handleNoteOn(byte channel, byte note, byte velocity);
void handleNoteOff(byte channel, byte note, byte velocity);
void reset();
midi::MidiInterface<HardwareSerial> MIDI((HardwareSerial &)Serial);
boolean _playing = false;
uint8_t _clock = 0;
uint8_t _step = 0;
uint8_t _channelIn = MIDI_CHANNEL_IN;
uint8_t _channelOut[NB_CHANNELS_OUT] = {1};
uint8_t _lastNotes[NB_CHANNELS_OUT][MAX_CHORD_NOTES] = {{0}};
uint8_t _nbKeyPressed = 0;
uint8_t _nbNotesToSend = 0;
uint8_t _chord[MAX_CHORD_NOTES];
boolean _yieldChord = false;
uint8_t _yieldAtMinimum = 0;
void (*_onStep)(uint8_t step, void (*sendNote)(uint8_t channel, uint8_t *notes));
void (*_onChord)(uint8_t *chord, uint8_t nbNotes);
void (*_onStop)(void);
void init(
void (*onStep)(uint8_t step, void (*sendNote)(uint8_t channel, uint8_t *notes)),
void (*onChord)(uint8_t *chord, uint8_t nbNotes),
void (*onStop)(void))
{
_onStep = onStep;
_onChord = onChord;
_onStop = onStop;
for (uint8_t i = 0; i < NB_CHANNELS_OUT; i++)
{
_channelOut[i] = i + 1;
}
reset();
MIDI.begin(_channelIn);
MIDI.turnThruOff();
MIDI.setHandleClock(handleClock);
MIDI.setHandleStart(handleStart);
MIDI.setHandleStop(handleStop);
MIDI.setHandleNoteOn(handleNoteOn);
MIDI.setHandleNoteOff(handleNoteOff);
}
void sendNotes(uint8_t channelIdx, uint8_t *notes)
{
for (uint8_t i = 0; i < MAX_CHORD_NOTES; i++)
{
if (_lastNotes[channelIdx][i] != 0)
{
MIDI.sendNoteOn(_lastNotes[channelIdx][i], 0, _channelOut[channelIdx]);
}
_lastNotes[channelIdx][i] = notes[i];
if (notes[i] != 0)
{
MIDI.sendNoteOn(notes[i], 127, _channelOut[channelIdx]);
}
}
}
void handleClock()
{
_clock = _clock % 6;
if (_playing && _clock++ == 0)
{
_onStep(_step, sendNotes);
_step++; // let it overflow (255 -> 0)
}
}
void handleStart()
{
_playing = true;
}
void handleStop()
{
_onStop();
for (uint8_t channelIdx = 0; channelIdx < NB_CHANNELS_OUT; channelIdx++)
{
for (uint8_t i = 0; i < MAX_CHORD_NOTES; i++)
{
if (_lastNotes[channelIdx][i] != 0)
{
MIDI.sendNoteOn(_lastNotes[channelIdx][i], 0, _channelOut[channelIdx]);
}
}
}
reset();
}
void handleNoteOn(byte channel, byte note, byte velocity)
{
if (_yieldAtMinimum == 0)
return;
if (_nbKeyPressed < MAX_CHORD_NOTES)
{
_chord[_nbKeyPressed++] = note;
_nbNotesToSend = max(_nbNotesToSend, _nbKeyPressed);
if (_nbKeyPressed >= _yieldAtMinimum)
{
_yieldChord = true;
}
}
}
void handleNoteOff(byte channel, byte note, byte velocity)
{
if (_yieldAtMinimum == 0)
return;
if (!--_nbKeyPressed && _yieldChord)
{
_yieldChord = false;
_onChord(_chord, _nbNotesToSend);
_nbNotesToSend = 0;
}
}
void loop()
{
MIDI.read();
}
void setChordYieldMinimum(uint8_t yieldSize)
{
_yieldAtMinimum = min(yieldSize, MAX_CHORD_NOTES);
}
void setMidiChannelIn(uint8_t channel)
{
_channelIn = channel;
MIDI.setInputChannel(_channelIn);
}
void setMidiChannelOut(uint8_t channelIdx, uint8_t channel)
{
for (uint8_t i = 0; i < MAX_CHORD_NOTES; i++)
{
if (_lastNotes[channelIdx][i] != 0)
{
MIDI.sendNoteOn(_lastNotes[channelIdx][i], 0, _channelOut[channelIdx]);
}
}
_channelOut[channelIdx] = channel;
}
uint8_t getMidiChannelIn()
{
return _channelIn;
}
uint8_t getMidiChannelOut(uint8_t channelIdx)
{
return _channelOut[channelIdx];
}
void reset()
{
_playing = false;
_clock = 0;
_step = 0;
_nbKeyPressed = 0;
_yieldChord = false;
for (uint8_t i = 0; i < MAX_CHORD_NOTES; i++)
{
for (uint8_t channel = 0; channel < NB_CHANNELS_OUT; channel++)
{
_lastNotes[channel][i] = 0;
}
_chord[i] = 0;
}
}
END_MIDI_IO_NAMESPACE