-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmidiChase.ino
167 lines (130 loc) · 4.01 KB
/
midiChase.ino
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
#include "TimerOne.h"
#include "FastLED.h"
#include <MIDI.h>
static const int shiftSpeed = 30000; //how many microseconds between light shifts/ticks
static const int NUM_LEDS = 200;
static const int DATA_PIN = 4;
static const float fadeScaler = 1.0; //devide each channel by this number when shift() occurs.
//1.0 is no fading. 1.01 would be a TINY bit of fading
static const int space = 60; //how many keys do we care about at a time? Axiom61 is 60
static const int maxMidi = 128; //the highest number we ever expect to get from midi
static const int onTime = 30; //how many ticks can you hold a key down for?
//create an array that represents our LED strip
CRGB leds[NUM_LEDS]; //how many LEDs in our strip
//This is some magic sauce that determines the profile of colors that are
//being generated by RGB()
//b_max = space means that EVERY key can generate colors on the blue channel
//g_max = (space - (space/3.0)); means that green stops two thirds of the way across
//the midi piano
//this is all about defining areas of the piano where colors should be represented.
int b_max = space;
int g_max = (space - (space/3.0));
int r_max = (space - ((space/3.0)*2));
//global RGB channels. These will get written to the 0 position every time shift() fires
int r = 0;
int g = 0;
int b = 0;
//onTimes remembers what what time various pitches came on at. It can make lights fade just
//like sounds do
int onTimes[128];
//brightness dictates how bright the LEDs should be. It decays as you hold the keys down.
//this is just the global declaration for it, since it is used globally
float brightness = 0;
//initialize the MIDI device. This Serial means connected to the RX/TX pins on arduino
//Serial1 Serial2 etc. would be appropriate for an arduino mega.
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI);
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN, GRB>(leds, NUM_LEDS);
releaseKeys(); //basically initialize the onTimes array with 0s.
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
MIDI.setHandleNoteOff(handleNoteOff);
MIDI.begin();
pinMode(13, OUTPUT);
Timer1.initialize(shiftSpeed);
Timer1.attachInterrupt(shift);
}
void loop() {
MIDI.read();
}
void handleNoteOn(byte channel, byte pitch, byte velocity) {
digitalWrite(13, HIGH);
onTimes[pitch] = onTime;
}
void handleNoteOff(byte channel, byte pitch, byte velocity) {
digitalWrite(13, LOW);
onTimes[pitch] = 0;
}
//getPitch looks at every key that is currently pressed and calculates a weighted average (weighted towards recently pressed keys)
//of all the keys that are currently pressed.
int getPitch() {
brightness = 0;
float total = 0;
float keysPressed = 0;
int pitch = 0;
for (int i=0; i<maxMidi; i++) {
if (onTimes[i] > 0) {
total+= i;
keysPressed++;
brightness+= onTimes[i];
}
}
pitch = total / keysPressed;
if (brightness > 30) {
brightness = 30;
}
return(pitch);
}
void expireKeys() {
for (int i=0; i<maxMidi; i++) {
onTimes[i]--;
}
}
void releaseKeys() {
for (int i=0; i<maxMidi; i++) {
onTimes[i] = 0;
}
}
void rgb(int pitch) {
r = 0;
g = 0;
b = 0;
float scaler = brightness / 30.0;
if (pitch > 60) {
int offset = (pitch % 60);
pitch = 60 - offset;
}
if (pitch > space) {
pitch = pitch - (pitch - space);
}
if (pitch < r_max) {
r = map(pitch,0,r_max,0,255);
}
if ((pitch >= r_max) && (pitch <= g_max)) {
b = map(pitch-r_max,0,r_max,0,255);
r = 255 - b;
}
if (pitch >= g_max) {
r = map(pitch-g_max,0,r_max,0,255);
g = 255 - r;
}
if (pitch == space) {
b = 255;
}
r = r*scaler;
g = g*scaler;
b = b*scaler;
}
void shift() {
expireKeys();
int pitch = getPitch();
rgb(pitch);
for (int i = NUM_LEDS-1; i>=1; i--) {
leds[i].r = leds[i-1].r/fadeScaler;
leds[i].g = leds[i-1].g/fadeScaler;
leds[i].b = leds[i-1].b/fadeScaler;
}
leds[0].r = r;
leds[0].g = g;
leds[0].b = b;
FastLED.show();
}