7

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?

  • 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 Dec 19 '15 at 8:37
  • Thank you, @OldJohn, I have now posted the same question here: stackoverflow.com/questions/34374593/…. Let's see what happens. – scaramouche Dec 19 '15 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 Dec 20 '15 at 16:00
3

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, privacy policy and cookie policy

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