-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patharduino-drum-machine.ino
175 lines (149 loc) · 5.21 KB
/
arduino-drum-machine.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
168
169
170
171
172
173
174
175
#include <MozziGuts.h>
#include <Sample.h>
#include <samples/bamboo/bamboo_00_2048_int8.h> // wavetable data
#include <samples/bamboo/bamboo_01_2048_int8.h> // wavetable data
#include <samples/bamboo/bamboo_02_2048_int8.h> // wavetable data
#include "sfx/chirp.h" // wavetable data
#include "sfx/clap.h" // wavetable data
#include "sfx/cowbell.h" // wavetable data
#include "sfx/hihat.h" // wavetable data
#include "sfx/kick.h" // wavetable data
#include "sfx/snare.h" // wavetable data
#include <EventDelay.h>
#include <mozzi_rand.h>
#define CONTROL_RATE 128
#define CELLS_PER_SAMPLE 2048
// Bank of sample
// use: Sample <table_size, update_rate> SampleName (wavetable)
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aBamboo0(BAMBOO_00_2048_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aBamboo1(BAMBOO_01_2048_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aBamboo2(BAMBOO_02_2048_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aChirp(CHIRP_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aClap(CLAP_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aCowbell(COWBELL_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aKick(KICK_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aHiHat(HIHAT_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE>aSnare(SNARE_DATA);
Sample <CELLS_PER_SAMPLE, AUDIO_RATE> *sample1 = &aKick;
Sample <CELLS_PER_SAMPLE, AUDIO_RATE> *sample2 = &aSnare;
Sample <CELLS_PER_SAMPLE, AUDIO_RATE> *sample3 = &aHiHat;
// for scheduling audio gain changes
EventDelay kTriggerDelay;
unsigned int tempoMs = 111;
const byte MAX_STEP_COUNT = 16;
byte cursor1 = 0;
byte cursor2 = 0;
byte cursor3 = 0;
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, OUTPUT);
startMozzi();
aBamboo0.setFreq((float) BAMBOO_00_2048_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded at
aBamboo1.setFreq((float) BAMBOO_01_2048_SAMPLERATE / (float) CELLS_PER_SAMPLE);
aBamboo2.setFreq((float) BAMBOO_02_2048_SAMPLERATE / (float) CELLS_PER_SAMPLE);
aChirp.setFreq((float) CHIRP_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
aClap.setFreq((float) CLAP_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
aCowbell.setFreq((float) COWBELL_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
aHiHat.setFreq((float) HIHAT_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
aKick.setFreq((float) KICK_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
aSnare.setFreq((float) SNARE_SAMPLERATE / (float) CELLS_PER_SAMPLE); // play at the speed it was recorded
kTriggerDelay.set(10); // countdown ms, within resolution of CONTROL_RATE
}
bool shouldPlay(byte steps, byte beats, byte i) {
float divisor = ((float)beats / (float)steps);
bool shouldPlay;
if (i == 0) {
shouldPlay = (beats != 0);
} else {
byte score = i * divisor;
byte prevScore = (i - 1) * divisor;
shouldPlay = (score > prevScore);
}
return shouldPlay;
}
void updateControl(){
// if the sequencer is not running, take no action...
if (digitalRead(2) == LOW) {
return;
}
// select the right samples for each voice
if (digitalRead(7) == LOW) {
sample1 = &aChirp;
} else if (digitalRead(8) == LOW) {
sample1 = &aKick;
} else {
sample1 = &aBamboo0;
}
if (digitalRead(5) == LOW) {
sample2 = &aBamboo1;
} else if (digitalRead(6) == LOW) {
sample2 = &aSnare;
} else {
sample2 = &aClap;
}
if (digitalRead(3) == LOW) {
sample3 = &aBamboo2;
} else if (digitalRead(4) == LOW) {
sample3 = &aCowbell;
} else {
sample3 = &aHiHat;
}
// read the step lengths and beat densities
byte steps1 = (byte) map(mozziAnalogRead(5), 0, 1023, 1, MAX_STEP_COUNT);
byte beats1 = (byte) map(mozziAnalogRead(1), 0, 1023, 0, steps1);
byte steps2 = (byte) map(mozziAnalogRead(6), 0, 1023, 1, MAX_STEP_COUNT);
byte beats2 = (byte) map(mozziAnalogRead(2), 0, 1023, 0, steps2);
byte steps3 = (byte) map(mozziAnalogRead(7), 0, 1023, 1, MAX_STEP_COUNT);
byte beats3 = (byte) map(mozziAnalogRead(3), 0, 1023, 0, steps3);
if(kTriggerDelay.ready()){
if (cursor1 >= steps1) {
cursor1 = 0;
}
if (cursor2 >= steps2) {
cursor2 = 0;
}
if (cursor3 >= steps3) {
cursor3 = 0;
}
if(shouldPlay(steps1, beats1, cursor1)) {
(*sample1).start();
}
if(shouldPlay(steps2, beats2, cursor2)) {
(*sample2).start();
}
if(shouldPlay(steps3, beats3, cursor3)) {
(*sample3).start();
}
cursor1++;
cursor2++;
cursor3++;
// tempo read
kTriggerDelay.start(map(mozziAnalogRead(4), 0, 1023, 300, 50));
}
}
int updateAudio(){
// sum together the playing samples
int asig= (int)
((long) (*sample1).next()*255 +
(*sample2).next()*255 +
(*sample3).next()*255)>>4;
//clip to keep audio loud but still in range
if (asig > 243) {
asig = 243;
}
else if (asig < -244) {
asig = -244;
}
return asig;
}
// the loop function runs over and over again forever
void loop() {
audioHook();
}