This demo uses an array of LEDs and two sets of speakers. As there are 12 different steps in an octave, I used 4 LEDs to represent the steps, leaving 4 undefined light combinations.  Different songs can be programmed in to the code.

Sources:
Tech Excercise music Sequencer


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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
</pre>
// MusicSequenceDemo.ino : demonstrate generation of two simultaneous tones at different rates and patterns
 
// The example program generates audio-frequency square waves at different
// pitches and patterns on pins 4 and 5 to demonstrate an event-loop control
// structure allowing parallel execution of multiple timed tasks with pattern
// generation.
 
// Define the pin numbers on which the outputs are generated.
const int outputPin1 = 4;
const int outputPin2 = 5;
 
//Define LED outputs
const int outputPin3 = 7;
const int outputPin4 = 8;
const int outputPin5 = 9;
const int outputPin6 = 10;
 
int outputPins[4] = {outputPin3, outputPin4, outputPin5, outputPin6};
/****************************************************************/
// Define the rhythm patterns for the two outputs using a simple pattern language.
 
// Note values:
// G = high pitch
// C = low pitch
// R = rest
 
// Note durations:
// q = quarter note
// e = eighth note
// s = sixteenth note
 
// A note value symbol affects the pitch generated by the successive note duration symbols.
// Any unknown symbol (including spaces) are ignored.
 
const char *rhythm1 = "fs Rs fs Rs Es Rs fs Rs As Rs Es Rs fs Rs fs Rs";
const char *rhythm2 = "Cs Rs Cs Rs Cs Rs Cs Rs Ge Re Ge Re";
const char *rhythm3 = "fq Rq fq Rq Ee Re fe Re Ae Re Ee Re fq Rq fe Rq";
 
// Define the timing constants for the rhythmic elements.
const long quarter_duration = 500000; // 120 bpm
 
/****************************************************************/
// Define the timing constants for the audio output.
//A3 is 1e6/(440)=2273
const long A3_half_period = 2273;
 
bool a_Lights [4] = {false, false, false, true};
//A#3 is 1 step down from A3= 233.08, half period is
const long AS3_half_period = 2145;
 
bool aS_Lights [4] = {false, false, true, false};
//B3 is 2 steps down from A3= 246.94
const long B3_half_period = 2025;
 
bool b_Lights [4] = {false, false, true, true};
// The low pitch is middle-C, the high pitch is the G a fifth above it. Given
// A3 of 220 Hz and equal temperament, middle C4 has a frequency
// 220*pow(2, 3.0/12) = 261.626 Hz.
 
// The half-period in microseconds is 1e6/(2*261.626), rounded to an integer:
const long C4_half_period = 1911;
 
bool c_Lights [4] = {false, true, false, false};
 
const long CS4_half_period = 1804;
 
bool cS_Lights [4] = {false, true, false, true};
 
const long D4_half_period = 1703;
 
bool d_Lights [4] = {false, true, true, false};
 
const long DS4_half_period = 1607;
 
bool dS_Lights [4] = {false, true, true, true};
 
const long E4_half_period = 1517;
 
bool e_Lights [4] = {true, false, false, false};
 
const long F4_half_period = 1432;
 
bool f_Lights [4] = {true, false, false, true};
 
const long FS4_half_period = 1351;
 
bool fS_Lights [4] = {true, false, true, false};
// The just intonation ratio for a musical fifth is 3/2, so
// G4 = 1.5*261.626 = 392.438 Hz, and the half period duration in
// microseconds is 1e6/(2*392.438): G4_half_period
const long G4_half_period = 1274;
 
bool g_Lights [4] = {true, false, true, true};
 
const long GS4_half_period = 1204;
 
bool gS_Lights [4] = {true, true, false, false};
 
&nbsp;
 
void LEDflip(bool lights[4])
{
 
for(int i=0; i<4; i++) {
 
if(lights[i]==true) {
digitalWrite(outputPins[i], HIGH);
}
else{
digitalWrite(outputPins[i], LOW);
}
}
}
/****************************************************************/
// C++ class to generate a rhythmic sound pattern on a single output.
class MelodyGenerator {
 
private:
// number of the pin to use for output
int output_pin;
 
// current output state
int output_value;
 
/// the time elapsed in microseconds since the last waveform update occurred
unsigned long tone_elapsed;
 
/// the time elapsed in microseconds since the last pattern update occurred
unsigned long pattern_elapsed;
 
// interval between output waveform transitions in microseconds
long tone_interval;
 
// flag which indicates that no tone is generated
bool resting;
 
// interval between pattern transitions in microseconds
long pattern_interval;
 
// current pattern string
const char *pattern_string;
 
// current position within the pattern string
int pattern_pos;
 
public:
 
// Constructor to initialize an instance of the class. This does not
// configure the hardware, only the internal state.
MelodyGenerator( int pin, const char *pattern );
 
// Update function to be called as frequently as possible to generate the
// output. It requires the number of microseconds elapsed since the last
// update.
void update(long interval);
};
 
// Constructor for an instance of the class.
MelodyGenerator::MelodyGenerator(int pin, const char *pattern)
{
// initialize the state variables
output_pin = pin;
output_value = LOW;
 
tone_elapsed = 0;
pattern_elapsed = 0;
 
tone_interval = C4_half_period;
resting = false;
 
pattern_interval = quarter_duration;
 
pattern_string = pattern;
pattern_pos = 0;
}
 
&nbsp;
 
// Update polling function for an instance of the class.
void MelodyGenerator::update(long interval)
{
// Check whether the next transition time has been reached, and if so, update
// the state and hardware output.
tone_elapsed += interval;
 
if (tone_elapsed >= tone_interval) {
 
// Reset the timer according to the desired interval to produce a correct
// average rate even if extra time has passed.
tone_elapsed -= tone_interval;
 
// Update the output pin to generate the audio waveform.
output_value = !output_value;
 
if (!resting) {
digitalWrite( output_pin, output_value);
} else {
digitalWrite( output_pin, LOW);
}
}
 
//-----------------------------------------------
 
// Check whether the pattern interval has expired.
pattern_elapsed += interval;
 
if (pattern_elapsed >= pattern_interval) {
pattern_elapsed -= pattern_interval;
 
// Process one or more symbols from the rhythm pattern. This will process
// any note value symbols until a note duration symbol is reached.
for(;;) {
char next_symbol = pattern_string[pattern_pos];
 
// Advance counter to next pattern string position.
pattern_pos++;
 
// if the next symbol is the end of the string, recycle to the beginning.
if (next_symbol == 0) {
pattern_pos = 0;
continue;
 
} else if (next_symbol == 'G') {
tone_interval = G4_half_period;
LEDflip(g_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'A') {
tone_interval = A3_half_period;
LEDflip(a_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'B') {
tone_interval = B3_half_period;
LEDflip(b_Lights);
resting = false;
continue;
 
&nbsp;
 
} else if (next_symbol == 'C') {
tone_interval = C4_half_period;
LEDflip(c_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'D') {
tone_interval = D4_half_period;
LEDflip(d_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'E') {
tone_interval = E4_half_period;
LEDflip(e_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'F') {
tone_interval = F4_half_period;
LEDflip(f_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'a') {
tone_interval = AS3_half_period;
LEDflip(aS_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'c') {
tone_interval = CS4_half_period;
LEDflip(cS_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'd') {
tone_interval = DS4_half_period;
LEDflip(dS_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'f') {
tone_interval = FS4_half_period;
LEDflip(fS_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'g') {
tone_interval = GS4_half_period;
LEDflip(gS_Lights);
resting = false;
continue;
 
} else if (next_symbol == 'R') {
resting = true;
continue;
 
} else if (next_symbol == 'q') {
pattern_interval = quarter_duration;
break; // leave the symbol-reading loop
 
} else if (next_symbol == 'e') {
pattern_interval = quarter_duration / 2;
break; // leave the symbol-reading loop
 
} else if (next_symbol == 's') {
pattern_interval = quarter_duration / 4;
break; // leave the symbol-reading loop
 
} else {
// all other symbols are ignored
continue;
}
}
}
}
 
/****************************************************************/
// Global variables.
// Declare two instances of the pattern generator.
 
MelodyGenerator generator1( outputPin1, rhythm1 );
MelodyGenerator generator2( outputPin2, rhythm3 );
 
// The timestamp in microseconds for the last polling cycle, used to compute
// the exact interval between output updates.
unsigned long last_update_clock = 0;
 
/****************************************************************/
/****************************************************************/
// This function is called once after reset to initialize the program.
void setup()
{
// Initialize two digital output pins, one for each pattern generator.
pinMode( outputPin1, OUTPUT );
pinMode( outputPin2, OUTPUT );
 
pinMode(outputPin3, OUTPUT);
pinMode(outputPin4, OUTPUT);
pinMode(outputPin5, OUTPUT);
pinMode(outputPin6, OUTPUT);
}
 
/****************************************************************/
// This function is called repeatedly as fast as possible from within the
// built-in library to poll program events.
 
void loop()
{
// The timestamp in microseconds for the last polling cycle, used to compute
// the exact interval between output updates.
static unsigned long last_update_clock = 0;
 
// Read the microsecond clock.
unsigned long now = micros();
 
// Compute the time elapsed since the last poll. This will correctly handle wrapround of
// the 32-bit long time value given the properties of twos-complement arithmetic.
unsigned long interval = now - last_update_clock;
last_update_clock = now;
 
// update the pattern generators
generator1.update(interval);
generator2.update(interval);
}
/****************************************************************/
<pre>