-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSequence.cpp
118 lines (105 loc) · 2.57 KB
/
Sequence.cpp
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
#include "Sequence.h"
#include <string.h>
#include <Arduino.h>
Sequence::Sequence() : swing(0.0), _currentNoteLength(8), active(false), _currentNoteLengthInterpolation(7)
{
clear();
}
void Sequence::toggleNote(char noteIndex)
{
for (int ind = noteIndex * _currentNoteLength; ind < 128; ind += 16 * _currentNoteLength)
{
setNote(ind);
}
updateMessages();
updateLeds();
}
void Sequence::setNote(int ind)
{
bool free = true;
for (int i = ind; i < ind + _currentNoteLength; i++) // check if there are notes ahead that would overlap
{
if (notes[i] != 0)
{
free = false;
break;
}
}
memset(notes + ind, 0, _currentNoteLength);
if (free)
{
notes[ind] = _currentNoteLength;
// check if there are notes behind that have to be shortened
for (int j = (ind - 1); j > max(0, ind - 8); j--)
{
while (notes[j] > (ind - j))
{
notes[j] >>= 1;
}
}
}
}
void Sequence::clear()
{
//memset(notes, 0, SEQUENCE_ENTRIES);
//memset(messages, 0, SEQUENCE_ENTRIES);
active = false;
updateMessages();
updateLeds();
}
void Sequence::updateMessages()
{
memset(messages, 0, SEQUENCE_ENTRIES);
int lastNoteDuration = 0;
int lastNoteIndex = -1;
for (int i = 0; i < 129; i++)
{
int position = i % 128;
if ((lastNoteIndex >= 0)&&((i - lastNoteIndex) >= lastNoteDuration))
{
messages[position] = NOTE_STOP;
lastNoteIndex = -1;
lastNoteDuration = 0;
}
if (notes[position] != 0)
{
active = true;
if ((messages[position] == -1)||((lastNoteIndex >= 0)&&( lastNoteDuration >= (i - lastNoteIndex)))) // last note was just turned of or still wants to be played
messages[position] = NOTE_REPLAY;
else
messages[position] = NOTE_PLAY;
lastNoteIndex = i;
lastNoteDuration = notes[position];
}
}
}
void Sequence::updateLeds()
{
memset(ledStates, 0, SEQUENCE_LEDS);
for (int i = 0; i < _currentNoteLength*16; i++)
{
if (notes[i] != 0)
ledStates[(int)i / _currentNoteLength] = 1;
}
ledStates[16] = (_currentNoteLength >= 1);
ledStates[17] = (_currentNoteLength >= 2);
ledStates[18] = (_currentNoteLength >= 4);
ledStates[19] = (_currentNoteLength >= 8);
}
unsigned char Sequence::getCurrentNoteLength()
{
return _currentNoteLength;
}
void Sequence::changeCurrentNoteLength(int delta)
{
_currentNoteLengthInterpolation = max(min(_currentNoteLengthInterpolation + delta, 7), 0);
if (_currentNoteLengthInterpolation <= 1)
_currentNoteLength = 1;
else if (_currentNoteLengthInterpolation <= 3)
_currentNoteLength = 2;
else if (_currentNoteLengthInterpolation <= 5)
_currentNoteLength = 4;
else
_currentNoteLength = 8;
updateLeds();
}