Mats Bengtsson <[EMAIL PROTECTED]> writes: > Quoting Graham Percival <[EMAIL PROTECTED]>: > >> Even music expressions can be passed in. Note that since we >> want an articulation attached to the second variable, we >> must #####. >> >> pattern = #(define-music-function (parser location x y) (ly:music? ly:music?) >> #{ >> $x e8-. a-. b-. $y-.-> b-. a-. e-. >> #}) >> >> \relative c''{ >> \pattern c8 c8 >> \pattern d8 ais8 >> \pattern cis8 des8 >> }
> One ugly solution is to attach the articulation to a spacer note > in parallel to the music in the second variable. > > pattern = #(define-music-function (parser location x y) (ly:music? ly:music?) > #{ > $x e8-. a-. b-. << $y s1*0-.-> >> b8-. a-. e-. > #}) > > \relative c''{ > \pattern c8 c8 > \pattern d8 ais8 > \pattern cis8 des8 > } > > Otherwise, I guess that you have to use Scheme constructs. Yes. To Graham: A $variable inside the #{ #} notation is like using a regular \variable in classical LilyPond notation. The following: { \music -. -> } is not legal LilyPond. When you have to manually build music expression using scheme, things become a bit more difficult. Here is the methodology: 1) write in classic LilyPond notation the expression you want to generate, for instance: c-^ 2) Use the \displayMusic music function to see how such an expression is internal represented in scheme: \displayMusic c-^ ==> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)) (make-music 'ArticulationEvent 'articulation-type "marcato"))) \displayMusic c ==> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)))) You see that a note (c) is represented as an EventChord expression, with a NoteEvent expression in its elements list. To add a marcato articulation, an ArticulationEvent expression has to be added to the elements property of the EventChord expression. You have to know some bits of scheme to do that. I'll write the function as a whole, then explain the different parts. 3) write a function that builds the expression. (define (add-marcato event-chord) "Add a marcato ArticulationEvent to the elements of `event-chord', which is supposed to be an EventChord expression." (let ((result-event-chord (ly:music-deep-copy event-chord))) (set! (ly:music-property result-event-chord 'elements) (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements))) result-event-chord)) (define (add-marcato event-chord) is the way to define a function in scheme: add-marcato is the function name, and event-chord is the name of the argument. Thus this function takes one argument, which should be, as its name implies, an EventChord expression. In scheme, what kind the arguments should be is often told by the name hey are given. "Add a MarcatoEvent to the elements of `event-chord', which is supposed to be an EventChord expression." The following lines is a description of what does the function. It is not mandatory to add a documentation string to a function, but it helps. the following lines are the body of the function: (let ((result-event-chord (ly:music-deep-copy event-chord))) `let' is used to declare local variables. Here we use one local variable, named `result-event-chord', to which we give the value (ly:music-deep-copy event-chord) `ly:music-deep-copy' is a function specific to LilyPond, like all functions prefixed by "ly:". It is use to make a copy of a music expression. Here, we copy the parameter of the function, `event-chord'. Remember: the purpose is to add a marcato to a EventChord expression. It's better to not modify the EventChord which is given as an argument, because it may be used elsewhere. Thus we now have a result-event-chord, which is a NoteEventChord expression, copy of event-chord. In the following expression, we actually add the marcato to its elements list property. the syntax is (set! place new-value) Here, what we want to set (the "place") is the "elements" property of result-event-chord expression: (ly:music-property result-event-chord 'elements) ly:music-property is the function used to access music properties (the 'elements, 'duration, 'pitch, etc, you see in the \displayMusic output above). the new value is the former elemnts property, with an extra thing: the MarcatoEvent expression, that we copy-paste from the \displayMusic output: (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements)) `cons' is used to add an element to a list. This is what we want: the same list as before + the new ArticulationEvent expression. The order inside the elements property is not important here. And finally, once we have added the MarcatoEvent to its elements property, we can return the result-event-chord, hence the last line of the function. 4) make it a music function and test it It's easier to test a function that builds music expression with a music function. Thus, we transform the add-marcato function into a music function. addMarcato = #(define-music-function (parser location event-chord) (ly:music?) "Add a marcato ArticulationEvent to the elements of `event-chord', which is supposed to be an EventChord expression." (let ((result-event-chord (ly:music-deep-copy event-chord))) (set! (ly:music-property result-event-chord 'elements) (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements))) result-event-chord)) First, we see the name that is given to the music function: addMarcato (a LilyPond variable). It is given a value: the music function defined using `define-music-function', which as the following form: (define-music-function (<parser> <location> <arg1> <arg2> ...) (<arg1-type-predicate> <arg2-type-predicate> ...) ...function body...) The `parser' and `location' argument are mandatory, and used in some more advanced situations. the parser argument is used for instance to access to the value of another LilyPond variable. The location argument is used to set the "origin" of the music expression that is built by the music function, so that, in case of syntax error, the lilypond compiler should tell the user an appropriate place to look in the input file. After those two mandatory arguments, we recognize the `event-chord' argument of our former `add-marcato' function. Following is a list of type predicate for each parameter of the function (except parser and location). A type predicate is function telling if its argument is of the given type or not. A type predicate often used in music function is `ly:music?', which tells whether something is a music expression. Some other type predicate are: markup?, number?, string?, list?, which check if an object is a markup, a number, a string, or a list, respectively. It is a convention in scheme to name a type predicate with the name of the type, followed by a question mark. Here, we have only one type predicate in the list, ly:music?, because the function as only one argument besides parser and location: event-chord, which should be an EventChord, that is more generally speaking a music expression. Following is the body of the add-marcato function we have written above. We can now check whether this function does the job we hope: \displayMusic \addMarcato c ==> (make-music 'EventChord 'elements (list (make-music 'ArticulationEvent 'articulation-type "marcato") (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)))) except the order of the ArticulationEvent and NoteEvent elements (not important in that case), this is the same expression tht we obtained by doing: \displayMusic c-^ ==> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)) (make-music 'ArticulationEvent 'articulation-type "marcato"))) [it's late, short story for the rest] #(define (add-articulation articulation event-chord) "Add the given articulation type ArticulationEvent to the elements of `event-chord', which is supposed to be an EventChord expression." (let ((result-event-chord (ly:music-deep-copy event-chord))) (set! (ly:music-property result-event-chord 'elements) (cons (make-music 'ArticulationEvent 'articulation-type articulation) (ly:music-property result-event-chord 'elements))) result-event-chord)) pattern = #(define-music-function (parser location x y) (ly:music? ly:music?) (let ((x-staccato (add-articulation "staccato" x)) (y-staccato-accent (add-articulation "marcato" (add-articulation "accent" y)))) #{ $x-staccato e8-. a-. b-. $y-staccato-accent b-. a-. e-. #})) \relative c''{ \pattern c8 c8 \pattern d8 ais8 \pattern cis8 des8 } nicolas _______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel