Friday, 28 April 2017

Displaying MIDI notes as fret positions

To convert scales and patterns into LED combinations we've made quite extensive use of spreadsheets. Boring old boxes of numbers have made displaying patterns of dots much easier.

The guitar fingerboard LEDs have been wired starting at fret 15, low string E, passing through each string of the 15th fret (E, A, G, D, B, E) then continuing with LED number six representing 14th fret low E, LED seven is the 14th fret A string and so on.

So we first drew up our patterns in a spreadsheet, coloured the boxes (to make them easier to identify) then transferred these patterns into byte arrays.


Anyone familiar with guitar scales might see the pentatonic minor box one starting with the A root note on the fifth fret in the image above.

After giving each note of the scale a "colour palette index", we stored each pair of strings in a single byte. So the low E string is the upper nibble of the first byte, the A string the lower nibble of the first byte, the D string is the upper nibble of the second byte and G is the lower nibble. The B string is the third byte upper nibble and lastly the high E string is represented by the lower nibble of the third byte.

So reading the scale chart from the bottom right corner, reading upwards, then from right to left, our fifteenth fret LED colour index values are 7(E), 2(A), 0(D), 0(G), 4(B), 7(e) (zero represents no dot to be displayed). The fourteenth colour index values are 0, 0, 5, 1, 0, 0.


You can see that by splitting each fret/string position into a single half-byte 0-F, when storing the values in hexadecimal, we can actually "see" the dots in the code. The first three byte values, for the six strings on the fifteenth fret are 0x72, 0x00, 0x47. The correlates directly with the dot patterns in the spreadsheet 7(E), 2(A), 0(D), 0(G), 4(B), 7(e)

Using a similar technique, we listed the note values of every fret position for every string.


Then after a quick Google look-up, recorded the MIDI note value for each note at each fret position, for each string. Recording the MIDI values in the same order we've wired the LEDs, our array of values begins 31, 36, 41, 46, 50, 55

These are the midi note values for G2, C3, F3, Bb3, D4, G4 which happen to be the notes on the guitar at the fifteenth fret.


Since the seven LED is at the low E string position on the 14th fret, our array of MID note positions continues 30, 35, 40, 45, 49, 54. We continue recording each note value in our MIDI array, all the way up from fret 15 to fret zero (open strings).

const byte midi_notes[] PROGMEM = {
  31,36,41,46,50,55,
  30,35,40,45,49,54,
  29,34,39,44,48,53,
  28,33,38,43,47,52,
  27,32,37,42,46,51,
  26,31,36,41,45,50,
  25,30,35,40,44,49,
  24,29,34,39,43,48,
  23,28,33,38,42,47,
  22,27,32,37,41,46,
  21,26,31,36,40,45,
  20,25,30,35,39,44,
  19,24,29,34,38,43,
  18,23,28,33,37,42,
  17,22,27,32,36,41,
  16,21,26,31,35,40
};

Now when we receive a MIDI note value, we can loop through this array to work out which LED corresponds to that note and light it up (or, if it's a note off message, turn it off).

void addNoteToFretboard(byte note, int col_index){
  // loop through all the midi note values in the array
  // and wherever there's a match, light up that LED with
  // the appropriate colour index
  byte p;
  CRGB c = RGBColour(col_index);

  for(int i=0; i<96; i++){
    p = pgm_read_byte(&midi_notes[i]);  
    if(p==note){
      led[i] = c;
    }
  }
  FastLED.show();
}

(in the example above, we have a function into which we pass an index number and it returns a CRGB value for a specific colour)

When hooked up to a MIDI source, the result looks something like this:



That's the opening sequence to Metallica's Enter Sandman. If you already know how to play the song, you'll recognise the familiar patterns around the 5th, 6th and 7th frets. For some notes, more than one dot appears. That's because there's more than one place where you can fret the note. Matching colours mean "it's the same note" so you'll see a red dot appear at both the 6th fret low E string and 1st fret A string at the same time. You can choose whether to play the riff on the 6th/7th fret, or on the 1st and second - it's up to you!

At the minute there's no differentiation between channels - you need to turn channels on and off using your MIDI sequencer - so when we wound the song on a bit and played it complete with distorted guitar, bass notes and drums/hi-hat, it looked a little bit crazy!




However, as a performance piece, we think it looks pretty cool too!