\paper { tagline = ##f } %% Contributed by vv on -user-fr: %% https://lists.gnu.org/archive/html/lilypond-user-fr/2020-04/msg00112.html rhythms = { %% Strictly speaking, these are not only rhythms, %% as the first pitch will actually be used. %% Also note that explicitly-pitched notes are %% still required in chords and when ties end. a2~\( \repeat unfold 16 c8 4 8\) r r8 8\( 8 8 \tuplet 5/4 {8 8 8 8 8} 8. 16 \tuplet 3/2 {8 8 8} 4\) r %% Chords (sort of) work. r2 4.\( 8 1\) c2. r8 %% Polyphony (sort of) works. %% These may look like spurious polyphonic constructs, %% but the goal is actually here to make the %% semitones pattern as readable as possible. << 8->\( \\ 2*1/4 >> << {8 8 8 8} \\ {} >> << 2.\) \\ { r4 (-. q-.)} >> } semitones = #'( 3 5 2 2 -4 7 7 2 -4 7 7 2 -5 3 -2 -1 -1 0 1 -1 -1 1 3 -2 -4 0 -1 3 -2 -1 0 -2 -5 ;; Entering the chord from the bottom up. -17 5 8 7 ;; The following note is in two voices. -10 0 2 4 4 -1 -2 ;; These are the last two-note chords, ;; again in a secondary voice. -9 4 -4 4) %% We could keep all of the following input mixed in with %% rhythms input above. However, it seems more interesting %% to separate not only semitones from rhythms, but also %% structural information. structure = { \key g \minor \clef bass <>\f s1-\markup \italic "pesante" \clef treble s1*2 s8 s1*23/8\p s1\arpeggio \bar "||" \break \tempo Moderato \time 6/4 } %%%%%%%%%% %% The semitones pattern will be looped if %% shorter than the given rhythms. #(define (loop-list-ref ls x) (let ((z (length ls))) (list-ref ls (remainder x z)))) #(define semi->pitch (make-semitone->pitch (music-pitches #{ c cis d es e f fis g gis a bes b #}))) %% See LSR #266. This is not merely cosmetic here, %% as the transposition mechanism may lead %% to quite extreme results. #(define (naturalize-pitch p) (let* ((o (ly:pitch-octave p)) (a (* 4 (ly:pitch-alteration p))) (n (ly:pitch-notename p)) (result '())) (cond ((and (> a 1) (or (eq? n 6) (eq? n 2))) (set! a (- a 2)) (set! n (+ n 1))) ((and (< a -1) (or (eq? n 0) (eq? n 3))) (set! a (+ a 2)) (set! n (- n 1)))) (cond ((> a 2) (set! a (- a 4)) (set! n (+ n 1))) ((< a -2) (set! a (+ a 4)) (set! n (- n 1)))) (if (< n 0) (begin (set! o (- o 1)) (set! n (+ n 7)))) (if (> n 6) (begin (set! o (+ o 1)) (set! n (- n 7)))) (ly:make-pitch o n (/ a 4)))) applyDeltas = #(define-music-function (music numbers) (ly:music? list?) " Apply a list of semitones (entered as positive or negative integers) to a given musical pattern. Only the first pitch of this pattern will be used as a starting point; all subsequent pitches will be discarded. " (let ((tied? #f) (prev-pitch '()) (delta-pitch '()) (i -1)) (music-filter (lambda (m) ;; We could go into detail into music event types ;; and their possible elements, but it's simpler ;; to just test for anything that has a pitch. (let ((p (ly:music-property m 'pitch))) (if (not (null? p)) (begin (if tied? ;; If the previous note was tied, just copy its pitch ;; and don't move forward in the semitones list. (ly:music-set-property! m 'pitch prev-pitch) (begin (ly:music-set-property! m 'pitch (if (null? prev-pitch) p ;; calculate the new pitch by adding the number ;; of semitones (i.e. delta) to the previous ;; note's pitch. (naturalize-pitch (ly:pitch-transpose (semi->pitch (loop-list-ref numbers i)) prev-pitch)))) (set! i (1+ i)))) (set! tied? #f) ;; testing for tied event. Since we're only working ;; with notes here, ties attached to a whole chord ;; chord won't work. (But one can tie its notes ;; individually.) (map (lambda (j) (if (music-is-of-type? j 'tie-event) (set! tied? #t))) (ly:music-property m 'articulations)) (set! prev-pitch (ly:music-property m 'pitch)))) m)) ;; We want all notes to be affected, so we need ;; to unfold and expand any input shortcut. (unfold-repeats-fully (expand-repeat-notes! (expand-repeat-chords! (list 'rhythmic-event) music)))))) %%%%%%%%%% %% The score given here as an example happens to look much %% nicer when computed in A minor, then transposed. A similar %% process should probably be advisable for most tonal scores. \new Voice << \structure \transpose a c \applyDeltas \rhythms \semitones >> \layout { ragged-last = ##t }