From: lilypond-user <[email protected]> On
Behalf Of Paolo Prete
Sent: Friday, November 29, 2019 12:27 AM
To: Lilypond-User Mailing List <[email protected]>
Subject: Generate pitches between pitches
Hello,
given two pitches, for example: c' and c'', is there a way to automatically
generate all the pitches between them? In three different ways:
1) all the "white keys" between them: d' e' f' g' a' b'
2) all the "black keys" between them: des' ees' ges' aes' bes'
3) all the pitches: des' d' ees' e' f' ges' g' aes' a' bes' b'
This feature would be very useful for simulating (piano) glissandos with MIDI.
thanks.
[>]
Like this?
\version "2.19.83"
glisando =
#(define-music-function
(parser location arg1 arg2)
(ly:music? ly:music? )
(letrec
((first-note-fn (lambda (lst)
(cond
((ly:music? lst) lst)
((null? lst) '())
((not (pair? lst)) '())
(else (car lst)))))
(last-note-fn (lambda (lst)
(cond
((ly:music? lst) lst)
((null? lst) '())
((not (pair? lst)) '())
((null? (cdr lst)) (car lst))
(else (last-note-fn (cdr lst)))))))
(let*
((lst1 (ly:music-property arg1 'elements))
(lst2 (ly:music-property arg2 'elements))
(pp-pitch '((0 . (0 . 0))
(1 . (1 . -1/2 ))
(2 . (1 . 0))
(3 . (2 . -1/2 ))
(4 . (2 . 0))
(5 . (3 . 0))
(6 . (4 . -1/2 ))
(7 . (4 . 0))
(8 . (5 . -1/2 ))
(9 . (5 . 0))
(10 . (6 . -1/2 ))
(11 . (6 . 0))))
(make-pitch (lambda (p)
(let* ((note (assoc-get (modulo p 12) pp-pitch))
(octave (quotient p 12)))
(ly:make-pitch octave (car note) (cdr note)))))
(first-note (last-note-fn lst1))
(last-note (first-note-fn lst2))
(first-pitch (ly:music-property first-note 'pitch))
(last-pitch (ly:music-property last-note 'pitch))
(first-duration (ly:duration-log (ly:music-property first-note
'duration)))
(first-type (ly:music-property first-note 'name))
(last-type (ly:music-property last-note 'name)))
(cond ((null? first-note) (throw 'glisando-err
"arg1 must be a music expression with notes"))
((null? last-note) (throw 'glisando-err
"arg2 must be a music expression with notes"))
((not (equal? first-type 'NoteEvent))(throw 'glisando-err
"arg1 must end with a note"))
((not (equal? last-type 'NoteEvent))(throw 'glisando-err
"arg2 must begin with a note"))
(else
(let* ((ps-first (ly:pitch-semitones first-pitch))
(ps-last ( - (ly:pitch-semitones last-pitch) 1))
(dir (if (> ps-first ps-last) 1+ 1- ))
(glis '()))
(do ((p ps-last (dir p)))((equal? p ps-first))
(set! glis (cons
(make-music
'NoteEvent
'pitch
(make-pitch p)
'duration
(ly:make-duration first-duration)
) glis)))
(make-music 'SequentialMusic 'elements (append (list arg1) glis
(list arg2) ))))
))))
\glisando { e'2 d' c'32 } { c''4 b' a'}