Pi Day MIDI Sequencer

If you write your dates month first, then 14th March is recognised as Pi day i.e. 3.14.(2022) in this case.  I’ve long had the idea of doing something MIDI or sequencer related to number sequences.  I’d like to do something with the Online Encyclopedia of Integer Sequences (OEIS) at some point, but as it is Pi day, I thought I’d start with that.

Now using the digits of Pi as the trigger for playing note values is a well trodden path, and calculating Pi to a number of decimal places is a well known and well researched task but to really get going you need quite a bit of computing power.  But what if the increasing time to calculate a digit is inherently part of the “music”?  That was my idea, so I set about looking for an algorithm to calculate the digits of Pi that would run on an 8-bit microcontroller, like my Arduino.

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

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

Parts list

  • Arduino Uno
  • Optional: 8 ohm speaker or old headphone speaker with 220Ω resistor.
  • Optional: Ready-Made MIDI Module.
  • Optional: I2C 7-segment display module based on a HT16K33.
  • Optional: 10x LEDS and associated resistors
  • Breadboard and jumper wires

The Circuit

PiDayMIDISequencer_bb

The most basic requirement for this circuit is some means of making a sound.  There are two options for that here:

  • Connect up a loudspeaker (and resistor) to an output pin (I’m using A0 here).
  • Connect up a MIDI interface and plug it into a synthesizer (I’m using one of my Ready-Made MIDI Modules here).

You can pick one or both of these methods.  But whilst satisfies the main aim – of having some music generated from the digits of Pi, it isn’t very interesting to look at!

So this also supports two optional display outputs, both of which are optional:

  • 10 LEDs (and associated resistors) on D2 to D11.
  • I2C 4-digit 7-segment display based on the HT16K33 controller.

In my video, I’ve enabled both types of display, although I’m using one of my “led bars” that has been tweaked for use with the Arduino’s weird pin-spacing, and MIDI output to my MT-32 playing the “Bellsinger” voice.

IMG_5929

The Code

The main mechanics are those I’ve used many times before – playing notes, driving LEDs and displays and so on.  To make the options easy to manage, I’ve split all the sound and display handling out into the following functions:

  • displayInit()
  • displayClear()
  • displayNoteOn(digit)
  • displayNoteOff(digit)
  • soundInit()
  • soundNoteOn(digit)
  • soundNoteOff(digit)

Then I’ve used conditional compilation to include the appropriate code in the appropriate place.  Once again I’ve used the HT16K33 library from Rob Tillaart (details here: https://github.com/RobTillaart/HT16K33).

But of course, the real “star” of this show is code to calculate the digits of Pi. Many methods to calculate Pi will store all previous digits and keep calculating to make the value more accurate over time.  This means that you have to keep checking digits and calculating until they stop changing at which point you can assume you know what that particular digit has to be.

That isn’t very practical if I just want to find a single (next) digit.  Most musical applications of Pi will probably store Pi to some number of digits in memory, but I found a discussion on how to calculate the nth digit of Pi. It started with a formula discovered by David Bailey, Peter Borwein, and Simon Plouffe in 1995, which is described in full here.  The downside of this is that it allows you to calculate digits in base 16 (hex), which isn’t really what I’m after.

However, maths doesn’t stand still and there are now forumlas that will calculate the nth digit in base 10 (i.e. decimal).  Here are some resources that talk about this:

In the end I took the code posted to the stackoverflow discussion which has the following opening comment:

/*
 * Computation of the n'th decimal digit of \pi with very little memory.
 * Written by Fabrice Bellard on January 8, 1997.
 * 
 * We use a slightly modified version of the method described by Simon
 * Plouffe in "On the Computation of the n'th decimal digit of various
 * transcendental numbers" (November 1996). We have modified the algorithm
 * to get a running time of O(n^2) instead of O(n^3log(n)^3).
 * 
 * This program uses mostly integer arithmetic. It may be slow on some
 * hardwares where integer multiplications and divisons must be done
 * by software. We have supposed that 'int' has a size of 32 bits. If
 * your compiler supports 'long long' integers of 64 bits, you may use
 * the integer version of 'mul_mod' (see HAS_LONG_LONG).
 */

It only requires a few minor tweaks to run on the Arduino, mostly removing any mentions of the C main and its arguments, and any printf statements.  Thankfully the Arduino has the AVR implementation of math.h available, so that bit can remain unchanged.

I turned the code’s main function into a calcPi() function as follows:

int calcPi(int digit)
{
   /* rest of function */

   return (int)(sum*10.0);
}

The provided function prints out 9 digits of Pi starting with the requested digit.  It does this by finally multiplying the ‘sum’ by 1e9 (i.e. 1000000000).  To return just a single digit I multiply the sum by 10 and return the integer result, which is just one digit – the digit of Pi for the requested location.

I’ve checked the digits produced against a list of the first 100 digits of Pi and it appears to work fine!  There are apparently more efficient routines, but actually as I’m relying on the timing of the calculation for timing in the music, a less efficient routine is fine.

Find it on GitHub here.

Closing Thoughts

I really like the idea of generative music from mathematical sequences, so I plan to do some more playing in this space at some point.

But I’m really pleased with the idea of using the increasing complexity of the calculation to vary the timing.  I’ve left this running for a few minutes and it reaches the point where changes are noticeably slower relatively quickly. In the 3 minutes and 14 seconds of video, I think it has calculated 78 digits of Pi.

I’m now intrigued to know how often it changes note after an hour.  Or even a day 🙂

Update – later that day…

I left it running for 12 hours, and it seemed to work fine at least up until digit 554, where it had calculated 27705 after 10 hours, and was changing digits approximately every 2.5 minutes.  I was quite keen to see if it would make it up to the Feynman point, which occurs at digit 762.  At this rate, I worked out it would probably take another 9 hours or so, and that was assuming the calculation didn’t get any slower!

But when I checked in again after the full 12 hours, it was reading 74345 which Pi Search tells me occurs position 64405!  So either my Arduino had a major speed injection or something had gone wrong!

I suspect at some point there was an overflow in the calculation that messed things up.  Or course there was a slim possibility that I’d been searching for the first instances of the sequences I was finding but it was actually a second or third occurrence but a bit of quite back-tracking and checking soon ruled that out.  And anyway, a rough calculation backwards of 550 digits in ten hours gives an average calculation time of just over 1 minute which seems much more plausible a rate given where things ended up.

Oh well. I can say I’m good for around 10 hours of “music” this way. It was fun while it lasted 🙂

Kevin

Leave a comment