Learning to tune by ear with Arduino
|Expert musicians, specially those who play string and keyboard instruments, know how to tune their instruments by ear, rapidly and accurately. Not everyone finds tuning easy to learn, and many amateurs are glad to be able to buy a tuner that detects the note being played and indicates how far out it is. But the gadgetry doesn't contribute much to this aspect of ones musical education.|
Musical scales are in fact quite subtle. The basic difficulty, known to the ancients, is that a scale built of harmonically pure intervals doesn't add up to an octave (see Angels). Keyboard players have no way of adjusting their intonation while they are performing, and so various kludges called temperaments were invented starting in the 16th century; different intervals are made a little sharp or flat so that music written at a particular place and time sounds nicely in tune and interesting. The modern piano has equal semitone intervals (equal temperament), but this is bearable only because of some features of instrument design.
Historians have described how early musicians 'tempered' their instruments, and for all the temperaments that were thought of, the deviations from equal temperament can be found in tables and in the Scala program. Nowadays, you can tune an acoustic instrument to different temperaments with the help of software or with a tuner such as the Korg OT-120. Electronic synthesisers with microtuning can be set up directly using their software (if it's still compatible with your computer!) or with Scala. However, these methods give no feel for the way early musicians chose their temperaments and routinely tuned their instruments; a harpsichord may need tuning every day.
Here and there on the internet, people have asked if there exists a device that enables someone sitting at an electronic keyboard to learn tune as though they were tuning a real instrument. I'm fortunate to have access to a harsichord, but don't want to wear out the tuning pegs, or break strings too often. Also, authentic harpsichords don't display the results of ones efforts. Here is an electronic tuning setup that works on a Roland JV1010 and should be easily adaptable, at least to other JVs and XPs.
I chose the popular Arduino microcontroller because it has MIDI plug-in cards (shields), and an excellent MIDI software library. The Arduino is designed to be used by artists and others, who need to learn only very basic electronics and programming. Although, at least for the moment, I also need a Windows PC for interfacing and readout, it seems too difficult for an amateur to develop this kind of "real-time" software directly on a computer.
The latest version is midiTemperament21.
After downloading it, unzip and put the directory with the .ino file into the one you use for your Arduino sketches. Put the libraries that are in the zip file into your Arduino Libraries directories. Note that the MIDI.h file of the MIDI library has been modified, as indicated by added comments, in accordance with the documentation. In particular, we use Serial1.
How tuning with MIDI works
|We want to vary the pitch a synthesiser gives for each note of a designated range on an electronic MIDI keyboard. Physically, a note is defined by its frequency. Since the perception of pitch increases logarithmically (progressively slower) with increasing frequency, pitch is defined in terms of the cent, which is 1/100th of an equal tempered semitone. midiTemperament works in cents, and re-calculates in the frequency domain in order to calculate and display beat frequencies between notes. The gory mathematical details can be found in books and on the web.|
Applications that use MIDI pitch-bend to set temperaments have been described, but they don't do what we want. This website is a pitch-bend free zone.
I bought a JV1010 more than a decade ago because it has microtuning and also some harpsichord samples on the Super Soundset plug-in card. Synths of this range seem to be quite reliable (unlike the bundled software) and they can still be bought second hand.
I'll assume the reader knows a little bit about MIDI. When you play a note on a keyboard, it sends a MIDI message (usually 3 bytes) containing the note number (0-127) to the synth. Simple synths then generate the equal-tempered frequency corresponding to the note, with a more or less horrible timbre. A new-ish MIDI standard (MIDI Tuning) specifies how the pitch of each of the 128 notes can be set independently, but not many synths follow this standard. At any rate, I can't afford one that does.
The old Roland JV and XP synths have settings in memory for tuning each of the 12 degrees of the scale in 1-cent steps, but for a given MIDI channel you get the same tuning in each octave. That isn't much use, because you need more than one octave to go round the circle of fifths and generally play around with tuning. Fortunately, these synths can produce, simultaneously, one kind of sound for each of the 16 MIDI channels, and there are separate scale tuning settings for each channel. So what we do is program the Arduino microcontroller to send each note played to a different channel for each octave, and use the same sound patch for all the channels.
Existing users of these synths might get a bit confused because this conflicts with the Roland approach to "performance' settings, where up to 16 parts or patches can be assigned to a 'performance' and played simultaneously, one per channel. You will no longer be able do this when each channel has a different tuning. My application is basically a multiple keyboard split, that could also be used give one sound per keyboard octave if you really like that sort of thing.
You invoke the tuning/multi-split mode by setting the Arduino microcontroller to the non-existent channel 17. The range of keyboard octaves affected is set in the software, but you can easily change it, and will need to if (unlike mine) your keyboard has less than 88 notes. I've set it to start at octave 1 (starting at C, 3 octaves below middle C) with a span of 6 octaves. (Note that the octave number isn't a MIDI parameter.) Some notes in the top octave of the keyboard are assigned (mapped) for sending tuning commands. The command keys could be put at the bottom of the keyboard, but then you'd lose those nice resonant bass notes that 17th century French composers exploited so well, much to the chagrin (I suppose) of the historically informed fraternity.
In the Roland system, the "scale tune" parameter for each note ranges from 0 to 127, where the default setting of 64 corresponds to zero cents with respect to equal temperament. That means you can tune up or down by a bit more than half a semitone. The program lets you change the number of cents for the note you want to tune.
The keyboard notes I use to make the adjustments are shown in this table. You can re-map them to any keys you like:
|Stop adjusting but tuning still active
|Reset note to default tuning value
|Down 1 cent each time note is played
|Select a note to be tuned
|Up 1 cent each time note is played
|Leave tuning mode, turn all notes off
How to use midiTemperament
Connect up the Arduino, MIDI-box(es), keyboard and computer as shown in the diagram below. The keyboard can be on any channel.
Download and unzip the latest version of the program ("sketch"). Currently it's 'midiTemper21'. Make sure the file is in a sketch directory with the same name without the suffix. Upload it into the Arduino.
The libraries I use are included in the zip file. These go in the 'Libraries' directory of your Arduino installation. Note that MIDI.h library has been modified with respect to the original (see the comment lines in midiTemperament and MIDI.h).
Open the Arduino terminal and set the baud rate to 115200 (the fastest). If that doesn't work on your computer you'll have to modify the sketch and the terminal setting. Speeds as low as 9600 baud may cause noticeable latency (notes aren't sounded simultaneously).
A menu worthy of a teletypewriter appears on the terminal if you send any character. The available commands are all numeric, and if you get anything wrong, just send 'return' until the main menu reappears.
Set the channel to '17' (via the terminal) ; the Arduino sets itself to (the false) channel 17, whereby each designated octave is assigned to its own MIDI channel. You can also set a 'normal' channel (1-16), and then the Arduino will translate input from the keyboard to that channel.
There are commands to preset (with no apocalyptic warnings) the synth to various temperaments, and to randomise the tuning within a range you can change in the program. You can set up your own temperament by typing the cent values in the source code. Settings apply to whatever channel(s) has been selected.
To tune a note, play top G# (or whatever note you have chosen in the sketch), then the chosen note. When you play a note that sends a command, it sounds twice.
Subsequently, each time you play the note being tuned, it sounds normally, and the terminal provides relevant tuning information.
To tune your note up or down, play top A or G respectively. The note being tuned is then adjusted by 1 cent each time it's played. It doesn't seem possible to slide a note up and down in the manner of a string player, though the synth has a portamento function.
To listen to the note being tuned without adjusting it, play top F. To set it to the equal temperament value use top F#.
If exactly two notes are being sounded, the terminal displays them in order of pitch. Also given are the interval, the number of cents corresponding to the true (frequency ratio) interval, and the degree of mistuning or 'impurity'.
To tune another note, play top G# again.
To leave tuning mode and play the newly-tuned synth, play top A#. This key will also turn all notes off if any 'note off' MIDI messages have gone astray.
To set all octaves on the keyboard to the same channel, use the terminal to send the channel number. You may want to do this if you have tuned a range comprising at least one complete octave (starting at C) to the temperament you want, and would like to hear the effect over the whole keyboard. The channel number to use is indicated on the terminal during tuning.
To start tuning again, set channel '17'.
The preset temperaments are copied from Scala so they must be correct. Note that by default Scala scales use C as the reference note for conventional 12-note scales (the deviation of C is always zero cents). That means that A would usually be shifted by your tuning and therefore out of tune with other instruments tuned to A. In case you want A to stay put, the program subtracts algebraically the cents deviation for A (referred to C) from the value for each note of the scale; it's then A that has zero cents. You can choose in the source code which note is to be kept at zero cents.
If you want different information to appear on the terminal, you can modify the relevant part of the sketch, copying the syntax of the existing code (including the pesky semi-colons!!). It's easy if you try; that's the general idea behind the Arduino concept.
Readout using the Arduino terminal
Since the LCD display is too small for present purposes I've sent nearly all the readouts to the serial terminal provided with Arduino. The rotary encoder and the screen let you change channels and display the last note played. The terminal doesn't allow you to store data except by screen copy (below). Other serial software terminals can be used, but future developments will probably use the Processing application as described in the Arduino documentation. Here's a screen copy of the Arduino terminal taken while note D4 was being tuned by comparison with the G below it:
Setting up the Arduino
|The application was developed by progressively modifying midiTranslator (Warren Gill), which provides a good introduction to using the Arduino MIDI library (see below). MidiTranslator lets you select channels, patches and volume by means of a rotary encoder with a push-button, and there is a liquid crystal text display. You don't need a computer to use it once the program has been uploaded.|
MidiTranslator works with any Arduino. My application needs a Mega 2560, because you need two interrupt-driven serial connections. The Mega could also generate 5 or 6 tunable tones of uncertain timbre in a future incarnation, which would not then need the synth. The quality of the sound would be another matter.
For the moment my application does need a computer to be connected (unless you have a MIDI-merger box), and a computer is useful for sending commands and displaying the results. I've also kept, as an option, the midiTranslator hardware (display and buttons), which can still be used to change channels and reset the Arduino. I had to change the connections to suit the Mega and the MIDI shield. The Arduino has no way of "knowing" whether or not the hardware is connected.
Warren Gill made his own MIDI interface; I bought a MIDI shield from Sparkfun (you could also use the Sparkfun MIDI breakout box or other makes of shield).
You need to solder the long-pin connectors (two with 6 pins, two with 8), which weren't supplied (Grrrr). Snip off the Tx and Rx pins of the shield, and connect Tx and Rx of the shield to Tx1 and Rx1 of the Arduino. Best use proper jumper leads with pins at each end, so they don't jump out. Set the little switch on the shield to RUN, so Arduino's default Serial ports are connected normally via Tx and Rx. You can also solder in the shield's pots and push buttons, though we don't use them here.
If you don't use the rotary encoder or display, the setup would look like this:
Arduino Mega with encoder and display
Here's the schematic of midiTranslator adapted for the Mega :
My LCD display has 4 lines of 16 characters. The MidiTranslator screen was 4x20, and I changed the code accordingly. Finding a version of the Arduino library LCD.h that works with a particular display isn't always easy. The problem is that different makes are stated to be compatible with Hitachi models, though the de facto informal standard isn't really a standard.
If you want a stand-alone Arduino to run midiTemperament without a computer, you'll probably consider a display with more than 4 lines. Change the lines of code starting with Serial.print to lcd.print (or add new lines), and look up how to place the cursor.
Installing the Arduino MIDI library
The popularity of Arduino is largely due to the range of code libraries that hide the most difficult aspects of programming from ordinary users.
You need to copy the MIDI library into the 'libraries' directory of your Arduino installation (A library is a directory containing other directories and files.). It can be downloaded from the playground, but then you would have to edit file MIDI.h as instructed in my sketch. A re-edited copy is in the zip file for downloading. Note that as it isn't too easy to rename the library to indicate that it's been modified, I've included an explanatory text file.
Arduino with two MIDI INsAs explained elsewhere on this page, we need two MIDI INs, one for the synth and one for the keyboard.
At the moment the library can handle only one IN and one OUT, and you can't run two instances. So for now you need either a merger box or software (Midi-OX), unless you can add your own software to the sketch.
This situation is likely to evolve.
Setting up the MIDI network
|A drawing of the network I'm using can be downloaded below. Obviously you'll use any other MIDI hardware that's available. This stuff can be expensive.|
Since I don't have a MIDI merger box, the MIDI-OUT data from the keyboard and the JV1010 synth have to be merged using MidiOX on a Windows PC fitted with a 2-input MIDI-USB interface. Midi-OX is a valuable and unique application that has never has never been ported to other platforms.
A third MIDI-IN was (Nio) useful during development, because it lets Midi-OX display output from the Arduino application (system exclusive messages). You can use any means of interfacing MIDI with any computer; sometimes I use a joystick port adapter for the sound card of an ancient PC.
As explained above, Arduino MIDI shields have only one MIDI IN, whereas you need one for the keyboard and another for the synth. The MIDI library handles only one MIDI in and one OUT, and you can't run two instances, for example with piggy-backed MIDI shields. You could arrange a second MIDI IN by writing extra software, but the library is so simple and reliable to use that it seems preferable to sit and wait for an update to the library that's been discussed.
|Here's a screenshot of MIDI-OX connections with the MidiSport and Nio boxes connected. You can have as many inputs as you want, but only one output. The MIDI-OX event port may or may not appear, depending on your settings.|
Note Off messagesWith MIDI, when you send a Note On message, the note will stay on until a Note Off message is received. If you want to change anything in the Arduino sketch, you will need to make sure that Notes Off are redirected to the correct channel and are not sent before the corresponding Note On. There's a compilation directive to get a readout of the Notes On count.
The MIDI standard allows two kinds of Note Off message: a "genuine" one starting with 8, and a Note On (starting with 9) with velocity zero. The MIDI library handles only the "genuine" version, whereas most MIDI gear sends Note On with velocity zero. I've added a line of Arduino code to handle the velocity zero case, and my application works with both formats. If you want, you can convert one to the other using the data mapping function of MIDI-OX.
|Arduino is an open-source hardware and software project (http://www.arduino.cc/). It runs on Mac OS X, Linux and Windows. You can buy an Arduino Mega 2560 from various sources.|
If you need software MIDI-merge the only free package I know is Midi-OX, which is available only for Windows (all versions).
You need a USB port for the Arduino, and possibly another one one for a MIDI interface having a driver for your system. My Midiman Midisport 2X2 interface works with all versions of Windows except the latest and last service pack for XP (known problem).
The Roland JV1010 was delivered (more than a decade ago) with a third-party OEM software package called SoundDiver, which is not maintained. These synths really need some kind of controlling software, though in theory you can do everything by sending sysex messages. I will need to be able to make my own sounds adapted to make it easier to learn to tune. SoundDiver runs on the obsolete Mac OS 9 and on Windows 95/98. It doesn't crash every time on XP, but fails on V*sta and W7. Has anyone tried W8 which is said to be an improvement legacy-wise?
I'm quite familiar with this kind of compatibility problem, because I've encountered the same difficulties with computer-controlled scientific instruments ever since computer control was introduced. Normally, a musical or scientific instrument should be expected to last at least 15-20 years, during which time a hell of a lot of computing platforms come and go. In my opinion, Roland should not have marketed the JV-XP series using third-party software from a firm that was clearly not in a position to maintain it. On the other side, Microsoft and Apple should have been capable of providing operating systems that allow small-scale software developers to produce software that is secure and has a life-expectancy exceeding a couple of years.
Alternative patch editors are available at various prices, but I don't know if the ones that still work with the latest operating systems can handle all the system settings. Also, I don't want to spend serious money to support fairly old hardware.
Things to be done
- Provide code to reset a temperament to a designated channel (a selection of temperaments is in the sketch, but the software hasn't been written yet). You can do this by hand or using the synth's native software.
- Provide a listing of the results of your tuning settings.
- Find out which sounds are best for practising tuning. Most of the JV ones have vibrato and other effects that make the beats difficult to hear. I'll have to get a patch editor that works on my computer and perhaps make my own sounds. The built-in ones seem to be a mixture of samples and purely synthetic sounds (a sine-wave generator is provided). BEWARE : the tuning of some of the piano sounds is "stretched", presumably without too much regard for the structure of the partials.
- Generate frequencies directly, using Arduino's built-in timers.
- I'll need to develop a user interface, and will probably have to learn Processing.
- Find out if there exists a free microtunable synth to which I could adapt the application. The application cSound seems the most appropriate though everything has to be coded.
- Finally, since this is an Arduino project, there are plenty of other ways of sending commands than by using designated MIDI keyboard keys: foot switches, TV remote controller, joystick, speech recognition...
Note on schematic drawings
Arduino and EagleArduino is popular because it allows people who don't know much about electronics to make electronic and electromechanical devices. However, quite a few users find it difficult to produce accurate schematic drawings suitable for posting. On another page (Arduino and Eagle) I'll show how this can be done, and start by explaining to the uninitiated how the software works.