A new musical project - the 'fret and forget' system

Following on from my piano key scale finder project, I’ve been working on something to help me remember my bass frets.

This project uses a string of addressable LEDs, and can be configured to zig-zag up and down the strings or across the fretboard.

The string tuning can be specified, along with:

  • scale mode (colour root and scale notes separarely)
  • interval mode (colour/bright root note and intervals from it differently)
  • note mode (colour notes in scale to a pre-defined colour language - I use the colour of the fretboard stickers I have been using)

There is a huge range of scales available.

This was put together with a lot of assistance from Claude Code. Any optimisations welcome, as would be an adaptation to guitar if it interests anyone.

/*
  ============================================================
   LED FRETBOARD SCALE HIGHLIGHTER  -  Pixelblaze
   Bass fretboard. A position lights only when its note is in
   the chosen scale. THREE display modes choose how lit notes
   are coloured.
  ============================================================

  Note numbers (E-based: open low string E = 0):
  0 1 2  3  4  5 6  7 8 9  10 11
  E F F# G  G# A A# B C C# D  D#

  HOW IT WORKS:
    decode(index)  -> physical LED index to (string, fret)
    isInScale()    -> single gate; every mode respects it
    setScale(id)   -> activates the chosen scale/chord
    mode           -> picks colouring for lit notes

  CHANGING SCALE OR CHORD:
    Set scaleId to the ID next to the name in the library below.
    That is all.

  ADDING A SCALE OR CHORD:
    1. Find the setScale() function below.
    2. Copy any existing line as a template.
    3. Change the id number to the next available (currently 84),
       list your intervals using mark(), and add a name comment.
    4. Add the same ID and name to the comment table above setScale().
    Example -- adding Augmented triad as ID 68:
      else if (id == 68) { mark(0);mark(4);mark(8); }           // Augmented triad
*/

// ---- PHYSICAL BOARD -------------------------------------------------
// 4 strings x 22 fret-positions (0..21, position 0 = open/nut). 4*22 = 88.
var NUM_STRINGS = 4;
var NUM_FRETS   = 22;
var NUM_USED    = NUM_STRINGS * NUM_FRETS;   // 88 used of 100 LEDs

// ---- WIRING LAYOUT --------------------------------------------------
//   wiringMode 0 = per-string serpentine   1 = per-fret serpentine
//   reverseChain = 1 if physical LED 0 is at the far end
export var wiringMode   = 0;
export var reverseChain = 1;

// ---- TUNING: open-string note per string, in WIRING string order ----
// E-based note assignment:
// 0 1 2  3  4  5 6  7 8 9  10 11
// E F F# G  G# A A# B C C# D  D#
// Standard 4-string bass low->high E A D G = 0 5 10 3.
// If string 0 is the HIGH string, reverse this: [3, 10, 5, 0].
var openNotes = [0, 5, 10, 3];

// ====================================================================
//   MODE
//     0 = SCALE     root vs other colours (rootColorHue / otherColorHue)
//     1 = INTERVAL  colour per interval-above-root; root/other ignored
//     2 = NOTES     colour per absolute note (E-based); root/other ignored
// ====================================================================
export var mode = 2;

// ====================================================================
//   SCALE / CHORD LIBRARY
//
//  ID   Name                          Intervals (semitones from root)
//   0   Major (Ionian)                0, 2, 4, 5, 7, 9, 11
//   1   Dorian                        0, 2, 3, 5, 7, 9, 10
//   2   Phrygian                      0, 1, 3, 5, 7, 8, 10
//   3   Lydian                        0, 2, 4, 6, 7, 9, 11
//   4   Mixolydian                    0, 2, 4, 5, 7, 9, 10
//   5   Natural minor (Aeolian)       0, 2, 3, 5, 7, 8, 10
//   6   Locrian                       0, 1, 3, 5, 6, 8, 10
//   7   Harmonic minor                0, 2, 3, 5, 7, 8, 11
//   8   Melodic minor                 0, 2, 3, 5, 7, 9, 11
//   9   Harmonic major                0, 2, 4, 5, 7, 8, 11
//  10   Major pentatonic              0, 2, 4, 7, 9         (= 6/9 chord tones)
//  11   Minor pentatonic              0, 3, 5, 7, 10
//  12   Minor blues                   0, 3, 5, 6, 7, 10
//  13   Major blues                   0, 2, 3, 4, 7, 9
//  14   Bebop dominant                0, 2, 4, 5, 7, 9, 10, 11
//  15   Bebop major                   0, 2, 4, 5, 7, 8, 9, 11
//  16   Bebop minor                   0, 2, 3, 4, 5, 7, 9, 10
//  17   Hungarian minor (Gypsy minor) 0, 2, 3, 6, 7, 8, 11
//  18   Hungarian major               0, 3, 4, 6, 7, 9, 10
//  19   Double harmonic (Byzantine)   0, 1, 4, 5, 7, 8, 11
//  20   Phrygian dominant             0, 1, 4, 5, 7, 8, 10
//  21   Neapolitan minor              0, 1, 3, 5, 7, 8, 11
//  22   Neapolitan major              0, 1, 3, 5, 7, 9, 11
//  23   Lydian dominant               0, 2, 4, 6, 7, 9, 10
//  24   Mixolydian b6                 0, 2, 4, 5, 7, 8, 10
//  25   Locrian natural-2             0, 2, 3, 5, 6, 8, 10
//  26   Altered / Super Locrian       0, 1, 3, 4, 6, 8, 10
//  27   Lydian augmented              0, 2, 4, 6, 8, 9, 11
//  28   Dorian b2                     0, 1, 3, 5, 7, 9, 10
//  29   Ukrainian Dorian              0, 2, 3, 6, 7, 9, 10
//  30   Lydian #2                     0, 3, 4, 6, 7, 9, 11
//  31   Hirajoshi                     0, 2, 3, 7, 8         (Kostka/Payne form; variants exist)
//  32   Iwato                         0, 1, 5, 6, 10
//  33   In Sen                        0, 1, 5, 7, 10
//  34   Yo                            0, 2, 5, 7, 9         (Japanese; ~ gamelan slendro)
//  35   Marwa                         0, 1, 4, 6, 7, 9, 11
//  36   Purvi                         0, 1, 4, 6, 7, 8, 11
//  37   Todi                          0, 1, 3, 6, 7, 8, 11
//  38   Pelog approx                  0, 1, 3, 7, 8         (rough 12-TET stand-in)
//  39   Prometheus (Scriabin)         0, 2, 4, 6, 9, 10
//  40   Enigmatic                     0, 1, 4, 6, 8, 10, 11
//  41   Egyptian (suspended pent.)    0, 2, 5, 7, 10
//  42   Whole tone                    0, 2, 4, 6, 8, 10
//  43   Diminished (whole-half)       0, 2, 3, 5, 6, 8, 9, 11
//  44   Diminished (half-whole)       0, 1, 3, 4, 6, 7, 9, 10
//  45   Augmented scale               0, 3, 4, 7, 8, 11
//  46   Chromatic                     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
//  47   Messiaen 3                    0, 2, 3, 4, 6, 7, 8, 10, 11
//  48   Messiaen 4                    0, 1, 2, 5, 6, 7, 8, 11
//  49   Messiaen 5                    0, 1, 5, 6, 7, 11
//  50   Messiaen 6                    0, 2, 4, 5, 6, 8, 10, 11
//  51   Messiaen 7                    0, 1, 2, 3, 5, 6, 7, 8, 9, 11
//  52   Persian                       0, 1, 4, 5, 6, 8, 11
//  53   Algerian                      0, 2, 3, 5, 6, 7, 8, 11
//  54   Petrushka / tritone           0, 1, 4, 6, 7, 10
//  68   Bebop minor (natural)         0, 2, 3, 5, 7, 8, 10, 11
//  69   Spanish 8-tone                0, 1, 3, 4, 5, 6, 8, 10
//  ---- Chords: set rootNote to the chord root ----
//  55   Major triad                   0, 4, 7
//  56   Minor triad                   0, 3, 7
//  57   Diminished triad              0, 3, 6
//  58   Augmented triad               0, 4, 8
//  59   Sus2                          0, 2, 7
//  60   Sus4                          0, 5, 7
//  61   Major 6                       0, 4, 7, 9
//  62   Minor 6                       0, 3, 7, 9
//  63   Dominant 7                    0, 4, 7, 10
//  64   Major 7                       0, 4, 7, 11
//  65   Minor 7                       0, 3, 7, 10
//  66   Half-dim (m7b5)               0, 3, 6, 10
//  67   Diminished 7                  0, 3, 6, 9
//  70   Power chord (5)               0, 7
//  71   Add9 (add2)                   0, 2, 4, 7
//  72   Minor add9                    0, 2, 3, 7
//  73   Minor-major 7                 0, 3, 7, 11
//  74   Dominant 7b5                  0, 4, 6, 10
//  75   Dominant 7#5 (aug7)           0, 4, 8, 10
//  76   Major 7#11                    0, 4, 6, 7, 11
//  77   Dominant 9                    0, 2, 4, 7, 10       (= dominant/Mixolydian pentatonic)
//  78   Major 9                       0, 2, 4, 7, 11
//  79   Minor 9                       0, 2, 3, 7, 10
//  80   Dominant 7b9                  0, 1, 4, 7, 10
//  81   Dominant 7#9                  0, 3, 4, 7, 10
//  82   Dominant 13                   0, 2, 4, 7, 9, 10
//  83   Quartal (stacked 4ths)        0, 5, 10
// ====================================================================

export var scaleId = 46;

var selectedScale = array(12);   // selectedScale[d]=1 if interval d is active

// mark() and setScale() are internal -- you only edit the mark() calls below.
function mark(d) { selectedScale[d] = 1; }

function setScale(id) {
  var d = 0;
  for (d = 0; d < 12; d++) { selectedScale[d] = 0; }

  // ---- Diatonic modes ----
  if      (id ==  0) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(9);mark(11); }       // Major (Ionian)
  else if (id ==  1) { mark(0);mark(2);mark(3);mark(5);mark(7);mark(9);mark(10); }       // Dorian
  else if (id ==  2) { mark(0);mark(1);mark(3);mark(5);mark(7);mark(8);mark(10); }       // Phrygian
  else if (id ==  3) { mark(0);mark(2);mark(4);mark(6);mark(7);mark(9);mark(11); }       // Lydian
  else if (id ==  4) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(9);mark(10); }       // Mixolydian
  else if (id ==  5) { mark(0);mark(2);mark(3);mark(5);mark(7);mark(8);mark(10); }       // Natural minor
  else if (id ==  6) { mark(0);mark(1);mark(3);mark(5);mark(6);mark(8);mark(10); }       // Locrian
  // ---- Other 7-note ----
  else if (id ==  7) { mark(0);mark(2);mark(3);mark(5);mark(7);mark(8);mark(11); }       // Harmonic minor
  else if (id ==  8) { mark(0);mark(2);mark(3);mark(5);mark(7);mark(9);mark(11); }       // Melodic minor
  else if (id ==  9) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(8);mark(11); }       // Harmonic major
  // ---- Pentatonic / blues ----
  else if (id == 10) { mark(0);mark(2);mark(4);mark(7);mark(9); }                        // Major pentatonic
  else if (id == 11) { mark(0);mark(3);mark(5);mark(7);mark(10); }                       // Minor pentatonic
  else if (id == 12) { mark(0);mark(3);mark(5);mark(6);mark(7);mark(10); }               // Minor blues
  else if (id == 13) { mark(0);mark(2);mark(3);mark(4);mark(7);mark(9); }                // Major blues
  // ---- Bebop ----
  else if (id == 14) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(9);mark(10);mark(11); }  // Bebop dominant
  else if (id == 15) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(8);mark(9);mark(11); }   // Bebop major
  else if (id == 16) { mark(0);mark(2);mark(3);mark(4);mark(5);mark(7);mark(9);mark(10); }   // Bebop minor
  // ---- Gypsy / exotic ----
  else if (id == 17) { mark(0);mark(2);mark(3);mark(6);mark(7);mark(8);mark(11); }       // Hungarian minor
  else if (id == 18) { mark(0);mark(3);mark(4);mark(6);mark(7);mark(9);mark(10); }       // Hungarian major
  else if (id == 19) { mark(0);mark(1);mark(4);mark(5);mark(7);mark(8);mark(11); }       // Double harmonic
  else if (id == 20) { mark(0);mark(1);mark(4);mark(5);mark(7);mark(8);mark(10); }       // Phrygian dominant
  else if (id == 21) { mark(0);mark(1);mark(3);mark(5);mark(7);mark(8);mark(11); }       // Neapolitan minor
  else if (id == 22) { mark(0);mark(1);mark(3);mark(5);mark(7);mark(9);mark(11); }       // Neapolitan major
  // ---- Melodic minor modes ----
  else if (id == 23) { mark(0);mark(2);mark(4);mark(6);mark(7);mark(9);mark(10); }       // Lydian dominant
  else if (id == 24) { mark(0);mark(2);mark(4);mark(5);mark(7);mark(8);mark(10); }       // Mixolydian b6
  else if (id == 25) { mark(0);mark(2);mark(3);mark(5);mark(6);mark(8);mark(10); }       // Locrian natural-2
  else if (id == 26) { mark(0);mark(1);mark(3);mark(4);mark(6);mark(8);mark(10); }       // Altered
  else if (id == 27) { mark(0);mark(2);mark(4);mark(6);mark(8);mark(9);mark(11); }       // Lydian augmented
  else if (id == 28) { mark(0);mark(1);mark(3);mark(5);mark(7);mark(9);mark(10); }       // Dorian b2
  // ---- Harmonic minor modes ----
  else if (id == 29) { mark(0);mark(2);mark(3);mark(6);mark(7);mark(9);mark(10); }       // Ukrainian Dorian
  else if (id == 30) { mark(0);mark(3);mark(4);mark(6);mark(7);mark(9);mark(11); }       // Lydian #2
  // ---- Japanese pentatonic ----
  else if (id == 31) { mark(0);mark(2);mark(3);mark(7);mark(8); }                        // Hirajoshi
  else if (id == 32) { mark(0);mark(1);mark(5);mark(6);mark(10); }                       // Iwato
  else if (id == 33) { mark(0);mark(1);mark(5);mark(7);mark(10); }                       // In Sen
  else if (id == 34) { mark(0);mark(2);mark(5);mark(7);mark(9); }                        // Yo
  // ---- Indian thaats / gamelan ----
  else if (id == 35) { mark(0);mark(1);mark(4);mark(6);mark(7);mark(9);mark(11); }       // Marwa
  else if (id == 36) { mark(0);mark(1);mark(4);mark(6);mark(7);mark(8);mark(11); }       // Purvi
  else if (id == 37) { mark(0);mark(1);mark(3);mark(6);mark(7);mark(8);mark(11); }       // Todi
  else if (id == 38) { mark(0);mark(1);mark(3);mark(7);mark(8); }                        // Pelog approx
  // ---- Other exotic ----
  else if (id == 39) { mark(0);mark(2);mark(4);mark(6);mark(9);mark(10); }               // Prometheus
  else if (id == 40) { mark(0);mark(1);mark(4);mark(6);mark(8);mark(10);mark(11); }      // Enigmatic
  else if (id == 41) { mark(0);mark(2);mark(5);mark(7);mark(10); }                       // Egyptian
  // ---- Symmetric ----
  else if (id == 42) { mark(0);mark(2);mark(4);mark(6);mark(8);mark(10); }               // Whole tone
  else if (id == 43) { mark(0);mark(2);mark(3);mark(5);mark(6);mark(8);mark(9);mark(11); }   // Diminished (W-H)
  else if (id == 44) { mark(0);mark(1);mark(3);mark(4);mark(6);mark(7);mark(9);mark(10); }   // Diminished (H-W)
  else if (id == 45) { mark(0);mark(3);mark(4);mark(7);mark(8);mark(11); }               // Augmented scale
  else if (id == 46) { mark(0);mark(1);mark(2);mark(3);mark(4);mark(5);mark(6);mark(7);mark(8);mark(9);mark(10);mark(11); } // Chromatic
  // ---- Messiaen modes of limited transposition ----
  else if (id == 47) { mark(0);mark(2);mark(3);mark(4);mark(6);mark(7);mark(8);mark(10);mark(11); }  // Messiaen 3
  else if (id == 48) { mark(0);mark(1);mark(2);mark(5);mark(6);mark(7);mark(8);mark(11); }           // Messiaen 4
  else if (id == 49) { mark(0);mark(1);mark(5);mark(6);mark(7);mark(11); }               // Messiaen 5
  else if (id == 50) { mark(0);mark(2);mark(4);mark(5);mark(6);mark(8);mark(10);mark(11); }          // Messiaen 6
  else if (id == 51) { mark(0);mark(1);mark(2);mark(3);mark(5);mark(6);mark(7);mark(8);mark(9);mark(11); } // Messiaen 7
  // ---- More named exotics ----
  else if (id == 52) { mark(0);mark(1);mark(4);mark(5);mark(6);mark(8);mark(11); }       // Persian
  else if (id == 53) { mark(0);mark(2);mark(3);mark(5);mark(6);mark(7);mark(8);mark(11); }  // Algerian
  else if (id == 54) { mark(0);mark(1);mark(4);mark(6);mark(7);mark(10); }               // Petrushka / tritone
  // ---- Chords ----
  else if (id == 55) { mark(0);mark(4);mark(7); }                                        // Major triad
  else if (id == 56) { mark(0);mark(3);mark(7); }                                        // Minor triad
  else if (id == 57) { mark(0);mark(3);mark(6); }                                        // Diminished triad
  else if (id == 58) { mark(0);mark(4);mark(8); }                                        // Augmented triad
  else if (id == 59) { mark(0);mark(2);mark(7); }                                        // Sus2
  else if (id == 60) { mark(0);mark(5);mark(7); }                                        // Sus4
  else if (id == 61) { mark(0);mark(4);mark(7);mark(9); }                                // Major 6
  else if (id == 62) { mark(0);mark(3);mark(7);mark(9); }                                // Minor 6
  else if (id == 63) { mark(0);mark(4);mark(7);mark(10); }                               // Dominant 7
  else if (id == 64) { mark(0);mark(4);mark(7);mark(11); }                               // Major 7
  else if (id == 65) { mark(0);mark(3);mark(7);mark(10); }                               // Minor 7
  else if (id == 66) { mark(0);mark(3);mark(6);mark(10); }                               // Half-dim (m7b5)
  else if (id == 67) { mark(0);mark(3);mark(6);mark(9); }                                // Diminished 7
  else if (id == 68) { mark(0);mark(2);mark(3);mark(5);mark(7);mark(8);mark(10);mark(11); }  // Bebop minor (natural)
  else if (id == 69) { mark(0);mark(1);mark(3);mark(4);mark(5);mark(6);mark(8);mark(10); }   // Spanish 8-tone
  else if (id == 70) { mark(0);mark(7); }                                                // Power chord (5)
  else if (id == 71) { mark(0);mark(2);mark(4);mark(7); }                                // Add9 (add2)
  else if (id == 72) { mark(0);mark(2);mark(3);mark(7); }                                // Minor add9
  else if (id == 73) { mark(0);mark(3);mark(7);mark(11); }                               // Minor-major 7
  else if (id == 74) { mark(0);mark(4);mark(6);mark(10); }                               // Dominant 7b5
  else if (id == 75) { mark(0);mark(4);mark(8);mark(10); }                               // Dominant 7#5 (aug7)
  else if (id == 76) { mark(0);mark(4);mark(6);mark(7);mark(11); }                       // Major 7#11
  else if (id == 77) { mark(0);mark(2);mark(4);mark(7);mark(10); }                       // Dominant 9
  else if (id == 78) { mark(0);mark(2);mark(4);mark(7);mark(11); }                       // Major 9
  else if (id == 79) { mark(0);mark(2);mark(3);mark(7);mark(10); }                       // Minor 9
  else if (id == 80) { mark(0);mark(1);mark(4);mark(7);mark(10); }                       // Dominant 7b9
  else if (id == 81) { mark(0);mark(3);mark(4);mark(7);mark(10); }                       // Dominant 7#9
  else if (id == 82) { mark(0);mark(2);mark(4);mark(7);mark(9);mark(10); }               // Dominant 13
  else if (id == 83) { mark(0);mark(5);mark(10); }                                       // Quartal (stacked 4ths)
}

// ---- ROOT NOTE ------------------------------------------------------
export var rootNote = 0;          // 0 = E

export function isInScale(note) {
  var diff = (note - rootNote + 12) % 12;
  return selectedScale[diff];
}

// --- Colour reference table ------------------------------------------
// 0.00=red
// 0.08=orange
// 0.13=yellow
// 0.3=green
// 0.42=cyan
// 0.50=sky
// 0.58=blue
// 0.67=indigo
// 0.75=violet
// 0.83=magenta
// 0.92=pink
// 1.00=red

// ---- MODE 0: SCALE colours (root vs other) --------------------------
export var rootColorHue    = 0.0;
export var rootColorSat    = 1.0;
export var rootBrightness  = 0.6;

export var otherColorHue   = 0.06;
export var otherColorSat   = 1.0;
export var otherBrightness = 0.4;

// ---- MODE 1: INTERVAL colour language -------------------------------
// Indexed by interval above root. A constant colour per interval; only
// shows where the scale lights it. Edit to taste.
//   idx: 0=P1/8ve 1=m2 2=M2 3=m3 4=M3 5=P4 6=TT 7=P5 8=m6 9=M6 10=m7 11=M7
// 0.00=red 0.08=orange 0.13=yellow 0.3=green 0.42=cyan 0.50=sky 0.58=blue 0.67=indigo 0.75=violet 0.83=magenta 0.92=pink 1.00=red
var intervalHue    = [0.00, 0.08, 0.13, 0.25, 0.33, 0.45, 0.55, 0.66, 0.75, 0.83, 0.90, 0.96];
var intervalSat    = [1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0];
var intervalBright = [0.70, 0.40, 0.40, 0.50, 0.50, 0.50, 0.40, 0.60, 0.40, 0.50, 0.40, 0.40];

// ---- MODE 2: NOTE colour language -----------------------------------
// Indexed by absolute note (E-based). A constant colour per pitch.
//   idx:         0=E   1=F  2=F#   3=G    4=G#  5=A   6=A#   7=B     8=C   9=C#   10=D  11=D#
// 0.00=red 0.08=orange 0.13=yellow 0.3=green 0.42=cyan 0.50=sky 0.58=blue 0.67=indigo 0.75=violet 0.83=magenta 0.92=pink 1.00=red
var noteHue    = [0.33, 0.75, 0.13, 0.02, 0.79, 0.90, 0.75,    0.7, 0.0,    0.62, 0.5,  0.35];
var noteSat    = [1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0];
var noteBright = [0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50];

// ---- INTERVAL BRIGHTNESS FLAG ---------------------------------------
// When useIntervalBrightness = 1, modes 0 and 2 borrow brightness from
// intervalBright[diff] instead of their own brightness values.
// Colours and saturation still come from the active mode.
export var useIntervalBrightness = 0;

// ---- DECODE: physical LED index -> (gString, gFret) -----------------
var gString = 0;
var gFret   = 0;
function decode(index) {
  var i = reverseChain ? (NUM_USED - 1 - index) : index;
  var pos = 0;
  if (wiringMode == 0) {
    gString = floor(i / NUM_FRETS);
    pos     = i % NUM_FRETS;
    gFret   = (gString % 2 == 0) ? pos : (NUM_FRETS - 1 - pos);
  } else {
    gFret   = floor(i / NUM_STRINGS);
    pos     = i % NUM_STRINGS;
    gString = (gFret % 2 == 0) ? pos : (NUM_STRINGS - 1 - pos);
  }
}

// ---- BEFORE RENDER --------------------------------------------------
export function beforeRender(delta) {
  setScale(scaleId);
}

// ---- RENDER ---------------------------------------------------------
export function render(index) {
  if (index >= NUM_USED) { hsv(0, 0, 0); return; }

  decode(index);
  var note = (openNotes[gString] + gFret) % 12;

  if (isInScale(note)) {
    var diff = (note - rootNote + 12) % 12;
    var bright = 0;

    if (mode == 1) {
      hsv(intervalHue[diff], intervalSat[diff], intervalBright[diff]);

    } else if (mode == 2) {
      bright = useIntervalBrightness ? intervalBright[diff] : noteBright[note];
      hsv(noteHue[note], noteSat[note], bright);

    } else {
      if (diff == 0) {
        bright = useIntervalBrightness ? intervalBright[0] : rootBrightness;
        hsv(rootColorHue, rootColorSat, bright);
      } else {
        bright = useIntervalBrightness ? intervalBright[diff] : otherBrightness;
        hsv(otherColorHue, otherColorSat, bright);
      }
    }
  } else {
    hsv(0, 0, 0);
  }
}


6 Likes

Looks amazing! Great use of Lego :smiling_face:

Verrry impressive project! All of the skills required to pull this together; inventor, electrician, woodworker, coder and musician, very rarely exist in the same person. And what a perfect application for Pixelblaze.

On a side note, as a lifelong music lover I had no idea there were so many scales. I’ve recently been listening to a duo called Angine de Poitrine. The guitarist/bassist has a custom built doubleneck guitar/bass that is double-fretted so he can play their music which is performed in 24tet. The reason I mention this is that several of the reaction videos have mentioned the scales that the songs were written in. And before I went down a rabbithole of Persian, Indian, and strangely, Balkan polka-style with occaisional forays into full on math/shred rock, I had NO idea we had so much scale -age to build music on!

Sorry for rambling, but your scale selection comments and the photo with your Chase Bliss loopers reminded me of my new favorite band.

Awesome work and thanks for posting this! :musical_notes::tada:

1 Like

Some very kind words there, thanks! (though to correct the record, this became a lot more achievable when I found pre-wired LED strings!) I’ve now got it mounted up with a proper frame around it with fret markers, so I think I am ‘done’ for now. Might consider a plastic print case in the future.

RE: A-d-P. Like a lot of prog/math bands, I respect them, and am amazed by them, but actually struggle to really get into the microtonal stuff. If that’s what you’re into, King Gizzard and the Lizard Wizard do a bit of that - they even have an album called Flying Microtonal Banana!

You might also like this lego microtonal guitar: https://www.youtube.com/watch?v=rPCEImSfCwc