Created
November 21, 2016 15:13
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\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