# teaching machines

## Arpeggiator, Part III

This post is part of a series of notes and exercises for a summer camp on making musical instruments with Arduino and Pure Data.

The last step of our arpeggiator gives the musician the ability to control the tempo or timing of the notes. We’ll use our last potentiometer for this. Its reading will be used to set the delay between notes. This delay needs to be set in both the Arduino sketch and the Pure Data patch.

### Arduino

The duration of each note is going to be needed in a few places, so let’s declare duration as a global. Make it a short rather than an int.

In note_wait, right after you write the note’s ID, read the value from A2 and assign it to duration. We’ll use this number directly as the number of milliseconds that each note plays.

Recall that the analog pins report a number in the range [0, 1023]. We need two bytes to hold numbers in this range, and shorts are two bytes wide—on Arduino, at least. Adjust your call to delay to use this duration variable.

We must also send the duration out along the serial port so that Pure Data knows when to stop playing the note. But there’s a hitch. The comport object can only receive bytes, and duration is a two-byte quantity. We are going to need to do some bit twiddling.

Consider the number 1023. In binary, it has this form:

0000001111111111

Let’s separate the bytes so they are easier to see:

00000011 11111111

Maybe we could just send the number in pieces like this? Yes, that’s what we’ll do.

The byte on the left is called the high-order byte. It holds the digits of the most magnitude. The byte on the right is called the low-order byte. The Arduino functions highByte and lowByte will separate duration into its two parts. Use them and write the high-order byte to the serial port. Then write the low-order byte.

That takes care of the Arduino side of things. Our message size is now 3 bytes. On to Pure Data!

### Pure Data

The third inlet of makenote expects the duration. To get the duration, we need to gather up the three bytes of each message sent in by the Arduino. The last two bytes must be reconstituted back into a two-byte quantity. There are a couple of operators we can use to achieve this. Suppose the high-order byte is 00000011, and the low-order byte is 11111111.

00000011 <- high
11111111 <- low

We can put these bytes back together with this set of operations: (high << 8) | low. The << is called the left-shift operator. The << 8 tells high to move left 8 bits, shifting it into its correct place and padding the lesser digits with zeroes. That leaves us with this situation:

00000011 00000000 <- high << 8
11111111 <- low

The | is called a bitwise or. It looks at each pair of corresponding bits in the two numbers. If at least one of the bits is 1, the output bit is 1. Given these two numbers, | gives us this result:

00000011 11111111

That’s our two-byte quantity!

Accomplish these operations in Pure Data in the following way:

• Delete the connection between comport and makenote.
• Add a repack 3 object.
• Feed the outlet of comport into repack.
• Add an unpack float float float object.
• Feed the outlet of repack into the inlet of unpack.
• Feed the first outlet of unpack into the first inlet of makenote.
• Add a << 8 object.
• Feed the second outlet of unpack—the high-order byte—into the first inlet of << 8.
• Add a | object.
• Feed the outlet of << 8 into the left inlet of |.
• Feed the third outlet of unpack—the low-order byte—into the second inlet of |.
• Feed the outlet of | into the inlet of the duration’s number box.

There. Now you should be able to set the tempo and hear your arpeggiator speed up and slow down when you crank the third potentiometer!

### Challenges

After you get your arpeggiator working, answer the following questions on a piece of scratch paper.

• When you crank the tempo potentiometer down to zero, the arpeggios play too quickly. How might you prevent this?
• Orchestrate in the Arduino sketch a sequence of arpeggios to play in succession. Perhaps you start on a major arpeggio rooted on C, then you switch to a minor arpeggio rooted on D, then you switch to… You might benefit from writing a helper function to play an given arpeggio for a given root note. Compose something that pleases you.