Pete Repeater is our novel physical interface for audio loops. Our device and its Arduino code control an audio looper by sending MIDI “Note On” messages over a MIDI cable to a computer running the Ableton software looper. Ableton MIDI mapping is used to translate the incoming MIDI from Arduino into Ableton actions (e.g. pressing the stop button on
the software looper).
From the beginning of the coding, we wanted to keep the code as simple as possible. We sought to use existing Arduino libraries, as well as techniques taken directly from class. This led us into some interesting directions, including the creation of two new Arduino libraries (“SuperSensor” and “Transport”).
MIDI was the first hurdle. There are two commonly-used approaches to use MIDI on Arduino. One way is to use the Arduino MIDI library, and the other is to write MIDI directly to the serial port. Tom advocates the latter approach, and that’s the way that Louise and Natasha hooked up ColorPlay to MIDI. I wanted to try the Arduino MIDI library because I hope that this project eventually can do a lot more MIDI than our prototype does. For example, if our project could take MIDI input it could have access to the MIDI clock of another device, allowing the looper to work in sync with the tempo and meter of another device (e.g. a drum machine).
Tom suggested that we start with the simpler (non-library) method and move to using the MIDI library if/when we came to need the additional MIDI functionality. He also advised us that the non-library method allows easy use of a SoftwareSerial device, freeing up the hardware serial port for debugging (e.g. Serial.println commands). We switched back to the DIY MIDI, but didn’t use the SoftwareSerial port (due to lack of time, mostly). One MIDI related problem popped up in our circuit, we which got resolved after talking to Louise and Natasha. The Fritzing diagram of the MIDI wiring in the ITP MIDI tutorial has two problems. First, the power and ground connections are wrong–pin 2 should go to ground, not power. Second, the pins are not numbered or labeled on the diagram, so it’s not clear which pin is 4 and which is 5. Louise and Natasha had figured out the correct wiring so we took a look at their circuit and got ours working.
With the MIDI output working, the next step was getting the analog sensors to deliver reliable info about the state of PeteRepeater. The first thought was to do some averaging of the values coming out of the Arduino analogRead command. But we planned to have multiple sensors, so that means we needed to keep track of the averages for several sensors simultaneously. Since Arduino is basically a C/C++ coding environment, I assumed I could use a C struct to keep all this data in one variable per sensor. This proved challenging in Arduino, because structs have to be used in a very specific way within the IDE. After trying various strategies, I abandoned the use of the C struct and dove into the creation of my first Arduino library, which I named “SuperSensor.” The library defines a new type (SuperSensor, which is an object) that wraps analogRead and provides a moving average method. Each sensor will have its own SuperSensor object, so the code for averaging only has to be written once. The Arduino library tutorial was the main resource I used to get the library code working.
After the sensor value averaging was figured out, the next challenge was the creation of an audio transport. Our Arduino code could now tell whether the piece was in the bank, but we only want to send MIDI commands when the state changes: when the piece goes in, we want to send a MIDI command, and then not send another MIDI command until the piece is removed. In essence, we need to track the current desired state (e.g. recording) and also we need to know if the desired state is different from the current state. This led to the creation of a second Arduino library called “Transport.” The library defines a new type (Transport, an object) thats methods for the audio operations we implement in our project. The object keeps good track of when state transitions occur, and provides a way to find out when they do. The code is definitely not sophisticated in how it tracks state transitions and will be augmented soon to make it more robust. The next feature will be the addition of user-definable callback functions that will be called whenever state transitions occur. For example, a user of the library should be able to write some code and attach it to the record state, so that anytime the transport goes into the record state, the user code is called.
From a cursory review of how other Arduino libraries implement callbacks, this does not look terribly difficult.
I learned C++ in a college class back in the day, but I have not ever written anything of significance in C++. I did not expect to be writing C++ code in this class, or really ever again, but the Arduino library tutorial and the open source libraries distributed with Arduino make the creation of a simple Arduino library about as easy as it could be. Though the code for SuperSensor and Transport are on GitHub already, I plan to refine the libraries a bit before announcing their release.
The use of existing and new Arduino libraries has enabled us to keep our Arduino code simple and readable. C++ is back, it is in your basement, the code is coming from INSIDE THE HOUSE!