9

I want to define a Lilypond function that will interpolate two notes. The function should take as inputs: the first note, the last note, the step (in semitones), and whether flats or sharps should be used.

For example:

\sequence a g 1 sharp

should create the chromatic scale:

a ais b c cis d dis e f fis g

Similarly,

\sequence f a -2 flat

should create the sequence descending by whole tones:

f ees des b a

Any ideas?

3
  • 2
    I suspect that you might need to get involved in Scheme programming here. There is very little info about using Scheme within Lilypond, but there are a number of questions here on StackOverflow, that might indicate that asking the question there could get some interest.
    – Old John
    Commented Dec 19, 2015 at 8:37
  • Thank you, @OldJohn, I have now posted the same question here: stackoverflow.com/questions/34374593/…. Let's see what happens. Commented Dec 19, 2015 at 19:38
  • You might also consider posting this to the Lilypond mail list. A few kind souls there have created Scheme functions to meet my needs in the past and in general it's a friendly place with several of Lilypond's main developers always present.
    – bfootdav
    Commented Dec 20, 2015 at 16:00

2 Answers 2

4

Here's a small library I wrote to write scales for my students that does somewhat what you are asking.

\version "2.18.2" 


%{ 
    Before: scaleNotes is an AssociationList mapping all integers from 0 to n  
            (where n is a natural number) to legal note names 
    Value:  A function usable in lilypond code that takes two numbers and maps  
            the range between them according to the scaleNotes mapping. Also  
            takes a third number which defines the length value of the note. 
%} 
#(define (numsToNotes scaleNotes step)  
  (define-music-function 
     (parser location start end dur)  
        (number? number? number?)  
        #{  
            $(ly:parser-include-string  
               parser  
               (get-scale start end scaleNotes dur step)) 
        #} 
       ) 
  ) 
#(define (get-note x scale)  
   (cdr (assoc (modulo x (length scale)) scale)) 
   ) 
#(define (get-scale start end scale dur step) 
   (foldr string-append  
          (cons (string-append (get-note start scale)  
                               (number->string dur))  
                (map (lambda (x) (string-append " " (get-note x scale)))  
                     (range ((if (< start end) + -) start step) end step))) 
   ) 
  ) 


%{ Standard utility functions  %} 
#(define (foldr func li) 
   (define (h x li) 
     (if (null? li) 
       x 
       (h (func x (car li)) (cdr li)))) 
   (h (func (car li) (car (cdr li))) (cdr (cdr li)))) 

#(define (range x y st) 
   (define (h li x st cmp)  
     (if (cmp x y)   
       li 
       (h (cons x li) (+ x st) st cmp))) 
   (reverse (h '() x (if (< x y) (abs st) (* -1 (abs st))) (if (< x y) > <)))) 

To use it to write the sequence you're asking for

#(define Chr-sharp-notes
  '((0 . "c") 
    (1 . "cis")
    (2 . "d")
    (3 . "dis")
    (4 . "e") 
    (5 . "f")
    (6 . "fis") 
    (7 . "g")  
    (8 . "gis")
    (9 . "a")
    (10 . "ais")
    (11 . "b")))
#(define Chr-flat-notes
  '((0 . "c") 
    (1 . "des")
    (2 . "d") 
    (3 . "es") 
    (4 . "e") 
    (5 . "f") 
    (6 . "ges")
    (7 . "g") 
    (8 . "as") 
    (9 . "a") 
    (10 . "bes")
    (11 . "b")))

flatChromatic = #(numsToNotes Chr-flat-notes 2)
sharpChromatic = #(numsToNotes Chr-sharp-notes 1)



\score{ 
    \relative c' { 
       \sharpChromatic #9 #19 #4
       \flatChromatic #17 #9 #4
    }
}

Just copy-paste the codeblocks to the same file and compile it to see the notes.

This is less usable than what you asked for and what you're asking for is actually a quite nice idea for a library so hopefully I'll find time to improve this.

0
\version "2.19.65"

myscale.sharp = #(make-semitone->pitch
                  (music-pitches #{ c cis d dis e f fis g gis a ais b #}))
myscale.flat = #(make-semitone->pitch
                 (music-pitches #{ c des d es e f ges g as a bes b #}))

sequence =
#(define-music-function (start end step scale)
  (ly:pitch? ly:pitch? number? symbol?)
  #{ $@(map #{ \myscale.#scale #}
            (iota (1+ (/ (modulo (- (ly:pitch-semitones end)
                                    (ly:pitch-semitones start))
                                 (if (negative? step) -12 12))
                         step))
                  (ly:pitch-semitones start)
                  step))
      #})

\displayLilyMusic \sequence a g 1 sharp
\displayLilyMusic \sequence f a -2 flat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.