Arduino Tone Polyphony – Part 5

Ok, I thought I’d done with Arduino Polyphony for the time being, but something else came up today that I wanted to try. My post got a mention on the Hackaday blog and one of the comments has led me to a tweak that helps the tuning a little.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

This is based on my previous posts about Arduino Tone Polyphony, see part 1, part 2, part 3, and part 4 here.

If you are new to Arduino, see the Getting Started pages.

Parts list and Circuit

This builds on part 3 and optionally part 4 of this project.  I used the shield built in part 4 as for its output stages, but I used MIDI rather than the built-in keyboard buttons to experiment with the four octave range once again.

The Code

One of the comments on the Hackaday article compared my project to Top Octave Tone Generators which was something I’d not heard of before.  Apparently they were used quite a bit in early electronic organs and made their way into a number of string synthesizers from the early days.  I’m not going to go into the full theory of operation here, I’ll save that for another day.

But it turns out this was a Hackaday challenge a few years back and there was a great solution that managed to squeeze the required 12 tone generators from an Arduino, provided that you coded it in assembler and upped the clock rate to 20MHz rather than the usual 16MHz. I’m not planning on trying to reproduce that, although it is a great piece of work, but one trick I thought I would try relates to the length of the pulses for the square waves.  It allows for a different value for the high and low timings, which effectively allows you to have pulses that average to a half-integer value – so a 80 uS HIGH pulse and a 81 uS LOW pulse is a bit like having an 80.5 uS pulse.  This allows me to correct for some of the frequencies, so I had to give it a go.

I re-ran my spreadsheet for frequencies seeing what happens if I allowed one of the pulses to be 1 uS more or less than the other. It turns out there were 16 across the four octaves that had a lower frequency error if this was possible, so I thought it worth trying.

In the end, I updated my code to allow for two frequency tables allowing a different counter, if required, for the HIGH and LOW pulses.  I now have two playing[] arrays to manage too to store the HIGH and LOW initialisation values for each playing tone.  They key bit of magic though happens in the interrupt routine.  I already have to know what the current level of a pulse is to toggle it, so it is a very simple matter of moving the counter initialisation to within the IF statement and initialising it with a different value.

for (int i=0; i<NUM_TONES; i++) {
if (playingHigh[i] != 0) {
if (counters[i] == 0) {
if (tonepulse & (1<<i)) {
// Switch to LOW
tonepulse &= ~(1<<i);
counters[i] = playingLow[i];
} else {
// Switch to HIGH
tonepulse |= (1<<i);
counters[i] = playingHigh[i];

You can hear the difference in the video.  First a board with the older part 3 code, then a board with this newer version. It is much better for the lower three octaves, but that last octave still gives me trouble.  G5 is particularly bad, but then in my spreadsheet I have an error of almost 10% no matter what tricks I’m playing here. I guess the only way out is now for less polyphony and a higher TICK rate.  Or maybe switch to assembler…

Find the updated code on GitHub.

Closing Thoughts

Just when I’d thought I was done with Arduino tones, this has sent me down another fascinating rabbit hole. I’m now wanting to investigate the world of binary counters and square wave tone generators, which does take me right back to the original aim – thinking of alternative ways to build the Oskitone Poly555.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s