lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to generate notes in a scale


From: Peter Chubb
Subject: Re: How to generate notes in a scale
Date: Mon, 21 Apr 2008 21:15:20 +1000
User-agent: Wanderlust/2.15.6 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (Gojō) APEL/10.7 MULE XEmacs/21.4 (patch 20) (Double Solitaire) (i486-linux-gnu)

>>>>> "Mats" == Mats Bengtsson <address@hidden> writes:

Mats> Isn't it possible to obtain the same result in a simpler way by
Mats> just transposing a hard coded template in C major into the
Mats> current key? 

You'ld need a different template for each degree of each kind of
scale, I think.  And for flatted and sharpened turns.  The number of
templates multiplies fast.  If you have a general rule for going one
step up, one step down from any note given the current key, then you
can do any turn; you just need to handle the alteration.

Mats> Information on the current key signature is
Mats> available in the keySignature context property (see the internal
Mats> reference documentation for Key-engraver), but perhaps not in a
Mats> very useful way.

Hmmm.  How does one get at that from a music function?
ly:context-property ??

Mats>  Also, don't forget about the instrumentTransposition property
Mats> (which is set by the \transposition command) if you want to
Mats> handle transposing instruments correctly.

That shouldn't matter.



Here's what I have so far, anyway.  It mostly works, and handles
ordinary turns.  I'm not happy about tenuto (a note marked tenuto
should be lengthened slightly and steal time from the next note on),
nor about the handling of grace notes.  And there are lots of
ornaments I haven't handled yet.

The resulting Midi sounds reasonable, but needs more work.  In
particular, it sounds (for clarinet) as if slurred notes are being
tongued (I don't know enough about Midi yet, but suspect that when a
EndNote event and a StartNote event are adjacent, one should omit
the EndNote.)  And there are lots of tempo markings to handle.

I wish that Director Musices were implemented in scheme not common lisp...

---articulate.ly

#(define ac:staccatoFactor '(1 . 8))
#(define ac:tenutoFactor '(1 . 1))
#(define ac:normalFactor '(7 . 8))

% assume start in C major
#(define ac:current-key (make-music
          'KeyChangeEvent
          'tonic
          (ly:make-pitch -1 0 0)
          'pitch-alist
          (list (cons 0 0)
                (cons 1 0)
                (cons 2 0)
                (cons 3 0)
                (cons 4 0)
                (cons 5 0)
                (cons 6 0))))

#(define ac:currentDuration (ly:make-duration 0 0))

#(define (ac:up note)
  (let* ((pitch (ly:music-property note 'pitch))
         (notename (ly:pitch-notename pitch))
         (new-notename (if (eq? notename 6) 0 (+ 1 notename)))
         (alterations (ly:music-property ac:current-key 'pitch-alist))
         (new-alteration (cdr (assq new-notename alterations)))
         (new-octave (if (eq? new-notename 0) (+ 1 (ly:pitch-octave pitch))
                      (ly:pitch-octave pitch)))
       )
   (set! (ly:music-property note 'pitch)(ly:make-pitch new-octave new-notename 
new-alteration))))

#(use-modules (ice-9 debug))

#(define (ac:down note)
  (begin
  (let* ((pitch (ly:music-property note 'pitch))
         (notename (ly:pitch-notename pitch))
         (new-notename (if (eq? notename 0) 6 (- notename 1)))
         (alterations (ly:music-property ac:current-key 'pitch-alist))
         (new-alteration (cdr (assq new-notename alterations)))
         (new-octave (if (eq? new-notename 6) (- (ly:pitch-octave pitch) 1)
                      (ly:pitch-octave pitch)))
       )
   (set! (ly:music-property note 'pitch)(ly:make-pitch new-octave new-notename 
new-alteration))))
)

#(define (ac:articulate-one-note m fraction)
  "Replace m with m*fraction rest*(1-fraction)"
  (if  (eq? 'NoteEvent (ly:music-property m 'name))
   (let*
    ((dur (ly:music-property m 'duration))
     (l (ly:duration-log dur))
     (d (ly:duration-dot-count dur))
     (factor (ly:duration-factor dur))
     (num (car fraction))
     (denom (cdr fraction)))
    (begin
     (set! ac:currentDuration dur)
     (set! (ly:music-property m 'duration)
      (ly:make-duration l d
       (* num (car factor))
       (* denom (cdr factor))))))
   m))

#(define ac:inSlur #f)
#(define ac:inPhrasingSlur #f)

% If there's an articulation, use it.
% If in a slur, use tenutoFactor instead.
% What to do about phrasing slurs?
% Expect an EventChord
% trills, turns., ornaments pralls etc.
% are also treated as Articulations.
% How should they be handled???
#(define (ac:getactions:elements es actions)
  (let* ((factor ac:normalFactor)
         (e (car es))
         (tail (cdr es)))
   (case (ly:music-property e 'name)
    ((SkipEvent)
     (set! factor (cons 1 1)))
    ((RestEvent)
     (set! factor (cons 1 1)))
    ((ArticulationEvent)
     (let ((articname (ly:music-property e 'articulation-type)))
      (cond 
       ((string= articname "staccato")
        (set! factor ac:staccatoFactor))
       ((string= articname "tenuto")
        (set! factor ac:tenutoFactor))
       ((string= articname "mordent")
        (set! actions (list 'mordent)))
       ((string= articname "prall")
        (set! actions (list 'trill)))
       ((string= articname "trill")
        (set! actions (list 'trill)))
       ((string= articname "turn")
        (set! actions (list 'turn)))
     )))
    ((SlurEvent)
     (let ((direction (ly:music-property e 'span-direction)))
      (set! ac:inSlur (eq? direction -1))))
    ((PhrasingSlurEvent) 
     (let ((direction (ly:music-property e 'span-direction)))
      (set! ac:inPhrasingSlur (eq? direction -1)))))
   (if (null? tail)
    (cond 
     ((null? actions)
      (if ac:inSlur (cons 'articulation  '(1 . 1))
       (cons 'articulation  factor)))
      (else actions))
    (ac:getactions:elements tail actions))))

#(define (ac:getactions music)
   (let* ((es (ly:music-property music 'elements)))
    (ac:getactions:elements es '())))

#(define (ac:setduration music duration)
  (if 
   (or (eq? (ly:music-property music 'name) 'NoteEvent)
    (eq? (ly:music-property music 'name) 'RestEvent))
   (set! (ly:music-property music 'duration) duration)))

#(define (ac:articulate-chord music)
  (begin
   (cond 
    ((eq? 'EventChord (ly:music-property music 'name))
     (let ((actions (ac:getactions music)))
      (case (car actions)
       ((articulation)
        (map
         (lambda (x) (ac:articulate-one-note x (cdr actions)))
         (ly:music-property music 'elements))
        (let*
         ((num (car (cdr actions)))
          (denom (cdr (cdr actions)))
          (mult (ly:duration-factor ac:currentDuration))
          (newnum (* (- denom num) (car mult)))
          (newdenom (* (cdr mult) denom))
          (len (ly:duration-log ac:currentDuration))
          (dots (ly:duration-dot-count ac:currentDuration)))
         (if (not (eq? num denom))
          (make-music 'SequentialMusic 'elements 
           (list music 
           (make-music 'EventChord 'elements 
            (list
             (make-music 'RestEvent 'duration (ly:make-duration len dots newnum 
newdenom))))))
          music)))
       ((trill) music)
       ((turn)
        (let*
         ((dur (ly:music-property
                (car (ly:music-property music 'elements)) 'duration))
          (factor (ly:duration-factor dur))
          (newdur (ly:make-duration (+ (ly:duration-log dur) 2)
                   (ly:duration-dot-count dur) (car factor)(cdr factor))))
         (begin
          (map (lambda (y) (ac:setduration y newdur)) 
           (ly:music-property music 'elements))
          (let* ((above (ly:music-deep-copy music))
                 (below (ly:music-deep-copy music))
                 (newmusic (make-music 'SequentialMusic 'elements (list above 
music below music))))
           (begin
            (map (lambda (y) (ac:down y))
             (filter 
              (lambda (z) (eq? 'NoteEvent (ly:music-property z 'name)))
              (ly:music-property below 'elements)))
            (map (lambda (y) (ac:up y))
             (filter 
              (lambda (z) (eq? 'NoteEvent (ly:music-property z 'name)))
              (ly:music-property above 'elements)))
            newmusic)))))
     )))
    ((eq? 'KeyChangeEvent (ly:music-property music 'name))
     (set! ac:current-key music)
     music
   )
    (else  music))
 ))


   
articulate = #(define-music-function (parser location music)
               (ly:music?)
               "Adjust times of note to add tenuto, staccato and 
                normal articulations.
                "
               (music-map ac:articulate-chord music)
               )


----Usage
lots-of-music=\relative c'' { ... }

\include "articulate.ly"

\score {
        \unfoldRepeats \articulate lots-of-music
        \midi{}
}

--
Dr Peter Chubb  http://www.gelato.unsw.edu.au  peterc AT gelato.unsw.edu.au
http://www.ertos.nicta.com.au           ERTOS within National ICT Australia





reply via email to

[Prev in Thread] Current Thread [Next in Thread]