Jump to content

Microtonal notation and theory of harmony

From LilyPond wiki

If you use microtonal notation, you can define your own note-names for the additional pitches. You list the set of pitch-changes you want to represent, and what symbol to use for each pitch-change.

You can also modify the pitches of unaltered notes, so that MIDI output and \transposition honor your tuning system.

The example below comes from Helmholtz and Ellis' book "on the Sensations of Tone". The notation indicates the precise pitches of just intonation based on perfect fifths and thirds. The sharp, flat and natural notes represent 'Pythagorean' tuning following the cycle of perfect fifths, which results in a very wide major third. The arrows represent the alteration that changes a Pythagorean major third to a perfect major third.

Notice the different shadings of pitch in the C-sharps, G-sharps and A-naturals, depending on their role in the harmony.

\version "2.24.0"

%% http://lsr.di.unimi.it/LSR/Item?id=786
%% see also http://www.ekmelic-music.org/en/ekmelily.htm

% The pitches for the scale are specified in terms of equal-tempered
  %  whole tones.
  % Transposition, key signatures, transposition, and
  %  MIDI output will use these pitches.
  % A perfect fifth is 701.955 'cents' where a cent is 1/200 of an
  %  equal-tempered whole tone.  LilyPond uses rational numbers for
  %  pitches, so we use 702/200 whole tones for the fifth.
  % Building the scale starting on C,
  %  G is a perfect fifth higher at 702/200, D is another fifth higher
  %  at 1404/200 so the pitch within the first octave is 204/200, etc.
  % (You can write a Scheme code to generate the series if you prefer.)
scalepitches = #`#(0/200 204/200 408/200 498/200 702/200 906/200 1110/200)
#(ly:set-default-scale (ly:make-scale scalepitches))

  % Seven perfect fifths (4914 cents) above C, is a C-sharp.
  % Lowered to the first octave this is 114 cents.
  
%% LSR-editor's remark
%% To avoid bleed over we not re-set/define SHARP, FLAT, DOUBLE-FLAT and 
%% DOUBLE-SHARP but use different identifiers --Harm

#(define MSHARP 114/200)
#(define MFLAT (- MSHARP))
#(define MDOUBLE-SHARP (* MSHARP 2))
#(define MDOUBLE-FLAT (* MFLAT 2))

  % The pitch E built from perfect fifths is 408 cents above C,
  %  but a perfect major third is 386 cents.
  % The notes in perfect thirds use arrows on accidentals
  %  to represent adjustment by this 22-cent difference.
  
ARROW = #22/200

#(define SHARP-RAISE   (+ MSHARP ARROW))
#(define SHARP-LOWER   (- MSHARP ARROW))  % 92/200
#(define NATURAL-RAISE (+ NATURAL ARROW))
#(define NATURAL-LOWER (- NATURAL ARROW))
#(define FLAT-RAISE    (+ MFLAT ARROW))
#(define FLAT-LOWER    (- MFLAT ARROW))

  % Note names can now be defined to represent these pitches in our
  % Lilypond input.  We extend the list of Dutch note names:
  
arrowedPitchNames = #`(
       (ceses . ,(ly:make-pitch -1 0 MDOUBLE-FLAT))
       (ceseh . ,(ly:make-pitch -1 0 FLAT-LOWER))
       (ces   . ,(ly:make-pitch -1 0 MFLAT))
       (cesih . ,(ly:make-pitch -1 0 FLAT-RAISE))
       (ceh   . ,(ly:make-pitch -1 0 NATURAL-LOWER))
       (c     . ,(ly:make-pitch -1 0 NATURAL))
       (cih   . ,(ly:make-pitch -1 0 NATURAL-RAISE))
       (ciseh . ,(ly:make-pitch -1 0 SHARP-LOWER))
       (cis   . ,(ly:make-pitch -1 0 MSHARP))
       (cisih . ,(ly:make-pitch -1 0 SHARP-RAISE))
       (cisis . ,(ly:make-pitch -1 0 MDOUBLE-SHARP))

       (deses . ,(ly:make-pitch -1 1 MDOUBLE-FLAT))
       (deseh . ,(ly:make-pitch -1 1 FLAT-LOWER))
       (des   . ,(ly:make-pitch -1 1 MFLAT))
       (desih . ,(ly:make-pitch -1 1 FLAT-RAISE))
       (deh   . ,(ly:make-pitch -1 1 NATURAL-LOWER))
       (d     . ,(ly:make-pitch -1 1 NATURAL))
       (dih   . ,(ly:make-pitch -1 1 NATURAL-RAISE))
       (diseh . ,(ly:make-pitch -1 1 SHARP-LOWER))
       (dis   . ,(ly:make-pitch -1 1 MSHARP))
       (disih . ,(ly:make-pitch -1 1 SHARP-RAISE))
       (disis . ,(ly:make-pitch -1 1 MDOUBLE-SHARP))

       (eeses . ,(ly:make-pitch -1 2 MDOUBLE-FLAT))
       (eses  . ,(ly:make-pitch -1 2 MDOUBLE-FLAT))
       (eeseh . ,(ly:make-pitch -1 2 FLAT-LOWER))
       (eseh  . ,(ly:make-pitch -1 2 FLAT-LOWER))
       (ees   . ,(ly:make-pitch -1 2 MFLAT))
       (es    . ,(ly:make-pitch -1 2 MFLAT))
       (eesih . ,(ly:make-pitch -1 2 FLAT-RAISE))
       (esih  . ,(ly:make-pitch -1 2 FLAT-RAISE))
       (eeh   . ,(ly:make-pitch -1 2 NATURAL-LOWER))
       (e     . ,(ly:make-pitch -1 2 NATURAL))
       (eih   . ,(ly:make-pitch -1 2 NATURAL-RAISE))
       (eiseh . ,(ly:make-pitch -1 2 SHARP-LOWER))
       (eis   . ,(ly:make-pitch -1 2 MSHARP))
       (eisih . ,(ly:make-pitch -1 2 SHARP-RAISE))
       (eisis . ,(ly:make-pitch -1 2 MDOUBLE-SHARP))

       (feses . ,(ly:make-pitch -1 3 MDOUBLE-FLAT))
       (feseh . ,(ly:make-pitch -1 3 FLAT-LOWER))
       (fes   . ,(ly:make-pitch -1 3 MFLAT))
       (fesih . ,(ly:make-pitch -1 3 FLAT-RAISE))
       (feh   . ,(ly:make-pitch -1 3 NATURAL-LOWER))
       (f     . ,(ly:make-pitch -1 3 NATURAL))
       (fih   . ,(ly:make-pitch -1 3 NATURAL-RAISE))
       (fiseh . ,(ly:make-pitch -1 3 SHARP-LOWER))
       (fis   . ,(ly:make-pitch -1 3 MSHARP))
       (fisih . ,(ly:make-pitch -1 3 SHARP-RAISE))
       (fisis . ,(ly:make-pitch -1 3 MDOUBLE-SHARP))

       (geses . ,(ly:make-pitch -1 4 MDOUBLE-FLAT))
       (geseh . ,(ly:make-pitch -1 4 FLAT-LOWER))
       (ges   . ,(ly:make-pitch -1 4 MFLAT))
       (gesih . ,(ly:make-pitch -1 4 FLAT-RAISE))
       (geh   . ,(ly:make-pitch -1 4 NATURAL-LOWER))
       (g     . ,(ly:make-pitch -1 4 NATURAL))
       (gih   . ,(ly:make-pitch -1 4 NATURAL-RAISE))
       (giseh . ,(ly:make-pitch -1 4 SHARP-LOWER))
       (gis   . ,(ly:make-pitch -1 4 MSHARP))
       (gisih . ,(ly:make-pitch -1 4 SHARP-RAISE))
       (gisis . ,(ly:make-pitch -1 4 MDOUBLE-SHARP))

       (aeses . ,(ly:make-pitch -1 5 MDOUBLE-FLAT))
       (ases  . ,(ly:make-pitch -1 5 MDOUBLE-FLAT))
       (aeseh . ,(ly:make-pitch -1 5 FLAT-LOWER))
       (aseh  . ,(ly:make-pitch -1 5 FLAT-LOWER))
       (aes   . ,(ly:make-pitch -1 5 MFLAT))
       (as    . ,(ly:make-pitch -1 5 MFLAT))
       (aesih . ,(ly:make-pitch -1 5 FLAT-RAISE))
       (asih  . ,(ly:make-pitch -1 5 FLAT-RAISE))
       (aeh   . ,(ly:make-pitch -1 5 NATURAL-LOWER))
       (a     . ,(ly:make-pitch -1 5 NATURAL))
       (aih   . ,(ly:make-pitch -1 5 NATURAL-RAISE))
       (aiseh . ,(ly:make-pitch -1 5 SHARP-LOWER))
       (ais   . ,(ly:make-pitch -1 5 MSHARP))
       (aisih . ,(ly:make-pitch -1 5 SHARP-RAISE))
       (aisis . ,(ly:make-pitch -1 5 MDOUBLE-SHARP))

       (beses . ,(ly:make-pitch -1 6 MDOUBLE-FLAT))
       (beseh . ,(ly:make-pitch -1 6 FLAT-LOWER))
       (bes   . ,(ly:make-pitch -1 6 MFLAT))
       (besih . ,(ly:make-pitch -1 6 FLAT-RAISE))
       (beh   . ,(ly:make-pitch -1 6 NATURAL-LOWER))
       (b     . ,(ly:make-pitch -1 6 NATURAL))
       (bih   . ,(ly:make-pitch -1 6 NATURAL-RAISE))
       (biseh . ,(ly:make-pitch -1 6 SHARP-LOWER))
       (bis   . ,(ly:make-pitch -1 6 MSHARP))
       (bisih . ,(ly:make-pitch -1 6 SHARP-RAISE))
       (bisis . ,(ly:make-pitch -1 6 MDOUBLE-SHARP))
       )
pitchnames = \arrowedPitchNames
#(ly:parser-set-note-names pitchnames)

  % The symbols for each alteration
  
arrowGlyphs = #`(
        (,MDOUBLE-SHARP . "accidentals.doublesharp")
        (,SHARP-RAISE  . "accidentals.sharp.arrowup")
        (,MSHARP        . "accidentals.sharp")
        (,SHARP-LOWER  . "accidentals.sharp.arrowdown")
        (,NATURAL-RAISE . "accidentals.natural.arrowup")
        (  0            . "accidentals.natural")
        (,NATURAL-LOWER . "accidentals.natural.arrowdown")
        (,FLAT-RAISE   . "accidentals.flat.arrowup")
        (,MFLAT         . "accidentals.flat")
        (,FLAT-LOWER   . "accidentals.flat.arrowdown")
        (,MDOUBLE-FLAT  . "accidentals.flatflat")
)

  % If the major scale is built from the tonic, dominant, and subdominant
  %  major chords, then the major scale involves arrowed accidentals.
  % Defining the pitches in the major mode allows us to use it for
  %  key signatures.
  
justMajor = #`(
    (0 . ,NATURAL)
    (1 . ,NATURAL)
    (2 . ,NATURAL-LOWER)
    (3 . ,NATURAL)
    (4 . ,NATURAL)
    (5 . ,NATURAL-LOWER)
    (6 . ,NATURAL-LOWER)
)
justMinor = #`(
    (0 . ,NATURAL)
    (1 . ,NATURAL)
    (2 . ,FLAT-RAISE)
    (3 . ,NATURAL)
    (4 . ,NATURAL)
    (5 . ,FLAT-RAISE)
    (6 . ,FLAT-RAISE)
)

  % keyAlterationOrder needs to know our pitches to typeset key signatures.
  % Each object that draws accidentals needs to know our glyphs.
  
\layout {
  \context {
    \Score
  keyAlterationOrder = #`(
    (6 . ,MFLAT) (2 . ,MFLAT) (5 . ,MFLAT) (1 . ,MFLAT) (4 . ,MFLAT) (0 . ,MFLAT) (3 . ,MFLAT)
    (3 . ,MSHARP) (0 . ,MSHARP) (4 . ,MSHARP) (1 . ,MSHARP) (5 . ,MSHARP) (2 . ,MSHARP) (6 . ,MSHARP)
    (6 . ,FLAT-RAISE) (2 . ,FLAT-RAISE) (5 . ,FLAT-RAISE) (1 . ,FLAT-RAISE) (4 . ,FLAT-RAISE) (0 . ,FLAT-RAISE) (3 . ,FLAT-RAISE)
    (3 . ,SHARP-LOWER) (0 . ,SHARP-LOWER) (4 . ,SHARP-LOWER) (1 . ,SHARP-LOWER) (5 . ,SHARP-LOWER) (2 . ,SHARP-LOWER) (6 . ,SHARP-LOWER) (6 . ,SHARP-RAISE)
    (3 . ,NATURAL-RAISE) (0 . ,NATURAL-RAISE) (4 . ,NATURAL-RAISE) (1 . ,NATURAL-RAISE) (5 . ,NATURAL-RAISE) (2 . ,NATURAL-RAISE) (6 . ,NATURAL-RAISE)
    (6 . ,NATURAL-LOWER) (2 . ,NATURAL-LOWER) (5 . ,NATURAL-LOWER) (1 . ,NATURAL-LOWER) (4 . ,NATURAL-LOWER) (0 . ,NATURAL-LOWER) (3 . ,NATURAL-LOWER)
    )
    \override KeySignature.alteration-glyph-name-alist = \arrowGlyphs
    \override KeySignature.padding-pairs = #'(
    (("accidentals.natural.arrowdown" . "accidentals.natural.arrowdown") . 0.5)
    (("accidentals.natural.arrowdown" . "accidentals.sharp.arrowdown") . 0.2)
    (("accidentals.natural.arrowdown" . "accidentals.flat.arrowdown") . 0.7)
    (("accidentals.natural.arrowup" . "accidentals.natural.arrowup") . 0.5)
    (("accidentals.natural.arrowup" . "accidentals.sharp.arrowup") . 0.2)
    (("accidentals.natural.arrowup" . "accidentals.flat.arrowup") . 0.7)
    (("accidentals.flat.arrowup" . "accidentals.flat.arrowup") . 0.3))
    \override Accidental.alteration-glyph-name-alist = \arrowGlyphs
    \override AccidentalCautionary.alteration-glyph-name-alist = \arrowGlyphs
    \override TrillPitchAccidental.alteration-glyph-name-alist = \arrowGlyphs
    \override AmbitusAccidental.alteration-glyph-name-alist = \arrowGlyphs
  }
}
  % MIDI implements microtones as a pitch bend, with one bend per channel.
  % These lines below assign one channel to each Voice, in case there are
  % multiple voices on a staff, so that each voice can have its correct
  % pitch bend.
  
\midi {
  \context {
    \Staff
    \remove "Staff_performer"
    \remove "Key_performer" % avoid midi bug, issue 748
  }
  \context {
    \Voice
    %midiInstrument = "pad 4 (choir)"
    midiInstrument = "drawbar organ"
    \consists "Staff_performer"
  }
  \tempo 4 = 30
}

\score { <<
  \new Staff \with {
    instrumentName = \markup\center-column {"Sopr." "Alto"}
  } \relative c'' {
    \key b\justMinor
    s1*0^\markup\huge"from St. Matthew Passion, J. S. Bach"
    % Was mein Gott will, das gescheh allzeit
    << {
      \accidentalStyle Score.modern
      \partial 4
      dih4 | ciseh b e dih8 cis | cis2 b
    } \\ {
      fis4 | e8 fis giseh aiseh b4 b | b aiseh fis2
    } >>
  }
  \new Staff \with {
    instrumentName = \markup\center-column {"Tenor" "Bass"}
  } \relative c' {
    \key b\justMinor
    << {
      \clef "treble_8"
       aih8 b | ciseh diseh e4 b8 ciseh%{Ellis has cis%} dih4 | gis, cis diseh2
    } \\ {
      fis,8 giseh | a4 giseh gih fis | eiseh fis b,2
    } >>
  }
  >>
  \layout{}
  \midi{}
}