Skip to content

Instantly share code, notes, and snippets.

@uliska
Created November 21, 2016 15:13
Show Gist options
  • Save uliska/32823fcad2d16d348d9f5e06a368b6fc to your computer and use it in GitHub Desktop.
Save uliska/32823fcad2d16d348d9f5e06a368b6fc to your computer and use it in GitHub Desktop.
Display simple pitches in Just Intonation, optionally specifying fundamental with the note encoding
\version "2.19.50"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Basic Notation Example for "Just Intonation with LilyPond" paper
%
% This file is self-contained to be compiled with recent versions
% of LilyPond's 2.19 development version or later. It will not work
% with LilyPond 2.18.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Underlying mathematics
% Convert a ratio to a floating point step representation.
% The integer part is the number of semitones above the fundamental,
% the fractional part is the fraction of a semitone
#(define (ratio->step ratio)
(* 12 (/ (log ratio) (log 2))))
% Convert a ratio and return a pair with
% - the pitch in semitones
% - the cent deviation above or below (rounded)
% Rounds to the nearest semitone and gives the deviation
% in cents -50 < cent < 49.
#(define (ratio->step/cent ratio)
(let*
((step-cent (ratio->step ratio))
;; truncate the floating point number to the nearest integer (scale step)
(step (inexact->exact (round step-cent)))
;; determine the cent deviation by stripping off
;; the floating point part of step-ratio
(cent (* 100 (- step-cent step))))
;; construct and return the pair
(cons step cent)))
% Maintain a current duration to be used when no duration is given,
% initialize to quarter notes (like with regular pitches without duration)
#(define ji-duration (ly:make-duration 2))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Configuration
% Maintain the fundamental, initialize to a default middle c
#(define ji-fundamental (ly:make-pitch 0 0 0))
% Maintain a current duration to be used when no duration is given,
% initialize to quarter notes (like with regular pitches without duration)
#(define ji-duration (ly:make-duration 2))
% Map the semitone returned by ratio->step/cent
% to a LilyPond pitch definition.
% This is based on the middle c and has to be transposed later
#(define (semitones->pitch semitone)
(let
;; two lists defining the 12 steps within the octave
;; c cis d dis e f fis g as a bes b
((steps '(0 0 1 1 2 3 3 4 4 5 6 6))
(semis '(0 1/2 0 1/2 0 0 1/2 0 1/2 0 -1/2 0))
;; strip semitons of octave
(index (modulo semitone 12)))
(ly:make-pitch
(floor (/ semitone 12))
(list-ref steps index)
(list-ref semis index))))
% Local predicate which is necessary to process two optional arguments
% Accepts the first optional argument when it's either a pitch or a duration
#(define (pitch-or-dur? obj)
(or (ly:pitch? obj)
(ly:duration? obj)))
% Produce a note in Just Intonation.
% If fund(amental) is given change the fundamental to calculate pitches from
% if dur(ation) is given change the duration.
jiNote =
#(define-music-function (fund dur ratio)
((pitch-or-dur?) (ly:duration?) fraction?)
(if fund
;; at least one optional argument has been given,
;; but it may be *either* the fundamental pitch *or* the duration
(if (ly:pitch? fund)
;; set new fundamental pitch
(set! ji-fundamental fund)
;; "first" (i.e. only) optional argument is a duration:
;; set the new duration
(set! ji-duration fund)))
(if dur
;; second optional argument is present (implies that the
;; first one is there too: set duration
(set! ji-duration dur))
(let*
;; note as pair of semitone-interval and cent deviation
((step/cent (ratio->step/cent (/ (car ratio) (cdr ratio))))
;; LilyPond pitch as defined by the ratio
(pitch-from-ratio (semitones->pitch (car step/cent)))
;; LilyPond pitch relative to the current fundamental
(pitch-effective
(ly:pitch-transpose
pitch-from-ratio
ji-fundamental))
;; cent deviation as integer
(cent (cdr step/cent)))
;; finally create the note with generated pitch and markup addition
(make-music
'NoteEvent
'articulations
(list (make-music
'TextScriptEvent
'text (format "(~@f)" (round cent))))
'pitch pitch-effective
'duration ji-duration)))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Examples
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Style the display of the cent deviation
% (note that this is completely independent from the
% calculation and encoding)
\layout {
\context {
\Voice
\override TextScript.direction = #UP
\override TextScript.font-size = -2.5
\override TextScript.self-alignment-X = -0.25
}
}
\markup "Occasionally change fundamental"
{
\jiNote a, 1 5/1
\jiNote 7/1
\jiNote e, 5/1
\jiNote 7/1
}
\markup "Specify fundamental with each note"
{
\jiNote c, 1 4/1
\jiNote bes,, 5/1
\jiNote a,, 6/1
\jiNote g,, 7/1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment