How to abbreviate 'note with the same note an octave higher, parenthesized' in Lilypond?

非 Y 不嫁゛ 提交于 2019-12-05 08:17:15

Ok, so here is a function I created for you, which will allow you to repeat single pitches. The only catch is that it won't use the \relative notation. This is because, in relative notation, the following sequence of notes c' c' c' will obviously be one octave higher than the preceding one. Unfortunately I still could not find a way to have a function such as \function #3 c' that would output c' c c. That said, here is my function and some examples:

\version "2.17.28"

times = #(define-music-function
     (parser location N note)
     (integer? ly:music?)
     (cond 
       ((>= N 2)
         #{ \repeat unfold $N { \absolute $note } #}
       )
       ((= N 1) 
         #{ \absolute $note #}
       )
     )
)

{
 a4 \times #3 b4
 R1
 \times #4 { c'8 d' }
 R1
 \times #1 { c''1 }
}

So the syntax is simply \times #"number of repetition" { ...music... }. If only one note is to be repeated, you can omit both { and }: \times #"number of repetition" "single note".

You can use this function in the middle of a \relative passage, but then you should enter the pitches for the function as absolute pitches. Have a look:

\version "2.17.28"

times = #(define-music-function
     (parser location N note)
     (integer? ly:music?)
     (cond 
       ((>= N 2)
         #{ \repeat unfold $N { \absolute $note } #}
       )
       ((= N 1) 
         #{ \absolute $note #}
       )
     )
)

\relative c'' {
  c4 d \times #4 e'' f g
}

Note that all notes above are in the same octave. The octave position the note f is also NOT influenced by this function, it is influenced by the note preceding the function, i.e., the d.

For sure there is a way to write a better code for this, but I wasn't able to do the trick with neither any \relative nor \transpose commands.


And here is some attempt to help you with your parenthesized octave (same function above but with some small alterations):

\version "2.17.28"

timesP = #(define-music-function
     (parser location N note)
     (integer? ly:music?)
     (cond 
       ((>= N 2)
         #{ 
           << 
             \repeat unfold $N { \absolute $note } 
             \transpose c c' \repeat unfold $N { \absolute \parenthesize $note } 
           >>
         #}
       )
       ((= N 1) 
         #{ 
           << 
             \absolute $note 
             { \transpose c c' \parenthesize $note }
           >>
         #}
       )
     )
)

{
 a4 \timesP #3 b4
 \timesP #8 c'16
 \timesP #2 g4
 \timesP #4 { c'8 d' } % no parenthesis here because there are two notes as arguments...
 \timesP #1 { c''1 } % no parenthesis here because of the { }
}

\relative c'' {
  c4 d \timesP #4 e'' f g
}

There are still some catches here: this function will only parenthesize when the argument is a single note written without { }. This is well commented on the code above.


I hope this will help you somehow. If I come across the solution for the octave transposition problem here, I will update this answer.

I just got this answer from David Kastrup, one of the developers of LilyPond:


The "octave transposition" happens because basically \transpose c c is the same as \absolute (as LilyPond does not apply \relative to transposed music).

\absolute is not necessary in connection with \repeat unfold: \repeat unfold knows how to deal with relative music.

Version 2.14.2 is awfully old. At any rate, there is currently issue http://code.google.com/p/lilypond/issues/detail?id=3673 in the LilyPond tracker, and the respective code can be found at https://codereview.appspot.com/30890043/diff/40001/scm/music-functions.scm

And there we get indeed into Scheme programming. The respective defmacro-public would likely work even in 2.14 though #{ #} might not work properly.

With that definition, your double definition would become:

double = #(define-music-function (parser location note) (ly:music?) (make-relative (note) note #{ $note $note #}))

and would then work in both absolute and relative mode. If the 2.14 #{ #} does not jibe with make-relative, writing (make-sequential-music (list (ly:music-deep-copy note) (ly:music-deep-copy note))) should serve as a Scheme replacement.

The original problem becomes easier to understand once you realize that it's just a simple code replacement, so \relative { \double c' } becomes \relative { c' c' } using different octaves. The make-relative macro will to the \relative operation only on a single note, and then paste the results into the music expression.

Based on the code in your question and the answer from David Kastrup quoted in another reply, I built the following code to turn notes into chords with the same note one octave higher, not parenthesized:

#(define (octavate-pitch pitch octaves)
   (ly:make-pitch
    (+ (ly:pitch-octave pitch) octaves)
    (ly:pitch-notename pitch)
    (ly:pitch-alteration pitch)))

#(define (articulation-is-of-type? art type)
   (string=? (ly:music-property art 'articulation-type) type))

#(define (copy-articulation? art)
   (cond ((music-is-of-type? art 'tie-event)
          #t)
         ((and (music-is-of-type? art 'articulation-event)
               (articulation-is-of-type? art "fermata"))
          #f)
         ; TODO add more cases
         (else
          #f)))

#(define (octNote note)
   (if (null? (ly:music-property note 'pitch))
       note
       (make-relative (note) note
                      (let ((note2 (ly:music-deep-copy note))
                            (pitch (ly:music-property note 'pitch)))
                        (set! (ly:music-property note2 'pitch)
                              (octavate-pitch pitch 1))
                        (set! (ly:music-property note2 'articulations)
                              (filter copy-articulation? (ly:music-property note2 'articulations)))
                        (make-event-chord (list note note2))))))

oct = #(define-music-function
           (parser location music)
           (ly:music?)
         (music-map octNote music))

It can be applied to an individual note or a full music expression:

\relative c' \oct {
  c d e f |
  g2 g |
}

It also works in the opposite order, \oct \relative c' { … }.

To parenthesize the added note, replace the last reference to note2 in octNote with (parenthesize note2) – I just prefer the non-parenthesized version for my own use. (You should probably rename the functions to octPNote and octP in that case, to avoid confusion. I briefly tried to write octPNote as a function that calls octNote and post-processes the result to parenthesize the second note, but wasn’t successful.)

You will also almost certainly need to expand the copy-articulation? predicate – ties and fermate are just the two kinds of articulation I encountered. (It defaults to not copying unknown articulations, so if the predicate is incomplete you’ll see it as missing articulations on the copied note.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!