Re: how to repeat a scheme function that creates a Score
On 4/6/2022 12:35 AM, Jean Abou Samra wrote: The attached MWE file has lots of my failed attempts commented out (I'm at a teachable moment if someone has a moment to teach). Or just point me to the right manual page(s). Here is a piece of code that works: $@(map (lambda (i) (scr)) (iota 10)) Now let's go through your attempt to see why they are failing. This is an amazing user group! Thank you times three to Aaron, Valentin and Jean for your immediate and expert responses! And special thanks to you, Jean, for giving me a full course explaining why all my previous attempts had failed. That was a very valuable learning experience! The code I'm using now is: % scors generates a specified number of scores % e.g. invoke $@(scors 10) from lilypond to generate ten scores #(define (scors num) (map (lambda (i) (scr)) (iota num))) This works nicely as I can make a series of invocations in different bookparts (simulating separate chapters) while preserving the overall sequence of piece numbers. I'd like you to check my learning on "$@" ... Per the ER section 1.2.1, "There are also ‘list splicing’ operators |$@| and |#@| that insert all elements of a list in the surrounding context." So it's not part of scheme but part of lilypond, as a bridge between scheme and lilypond. And that it tells lilypond to preserve all the elements of scheme list value as a sequence of expressions/values to be parsed/interpreted by lilypond, as opposed to getting just the value of the last element of the list. And so it is analogous (at least mnemonically) to the meaning of "$%" in bash (if I remember correctly), which preserves a sequence of command line arguments as separate values rather than combining them as one argument. But may I ask, why are "$@" and "#@" called 'list splicing' operators? The same terminology is used in Perl for what appears to me to be very different behaviors (list editing, insertion and removal), so I'd appreciate learning why 'splicing' is considered descriptive in lilypond. Jeff
Re: how to repeat a scheme function that creates a Score
On 4/5/2022 11:58 PM, Aaron Hill wrote: On 2022-04-05 10:40 pm, Jeff Olson wrote: Question (b): My secondary question is very simple. How do you set the seed for scheme's "random" function (used in my gen-music.ily). I'd like to get the repeatability of a pseudo-random number generator. (set! *random-state* (seed->random-state 42)) Review the Guile documentation [1]: [1]: https://www.gnu.org/software/guile/docs/docs-1.8/guile-ref/Random.html#Random -- Aaron Hill Thanks, Aaron, for answering the ultimate question [2]. [2] https://en.wikipedia.org/wiki/42_(number) Jeff
Re: just two questions
Hi Dario, Le 06/04/2022 à 22:46, Dario Marrini a écrit : hi people, I tried to search for these into docs, but I found everything but not what I needed, so, please, can you explain to me what's the meaning of these notation kinds? : * _\p_ or _ \p _ ( I don't remember well), where 'p' is a dynamic mark * [ a b c d ] (notes written between square brackets thank you cheers dario If you do not remember what a command or piece of syntax does, your best bet is to look into the function index from the notation manual. https://lilypond.org/doc/v2.23/Documentation/notation/lilypond-command-index The entries for \p and [ will redirect to pages explaining that the underscore _\p means to place the dynamic mark below the note (whereas ^\p places it above), and note[ ... note] is an explicit beaming (note the grouping, it's not "[note ... note]" but "note[ ... note]"). Best regards, Jean
just two questions
hi people, I tried to search for these into docs, but I found everything but not what I needed, so, please, can you explain to me what's the meaning of these notation kinds? : - _\p_ or _ \p _ ( I don't remember well), where 'p' is a dynamic mark - [ a b c d ] (notes written between square brackets thank you cheers dario
Re: bug in magnetic snapping lyrics engraver
Le 06/04/2022 à 20:17, Jean Abou Samra a écrit : Did I miss something? Whoops, big problem at line breaks ... \version "2.23.7" #(define (Left_hyphen_pointer_engraver context) (let ((hyphen #f) (text #f)) (make-engraver (acknowledgers ((lyric-syllable-interface engraver grob source-engraver) (set! text grob))) (end-acknowledgers ((lyric-hyphen-interface engraver grob source-engraver) (when (not (grob::has-interface grob 'lyric-space-interface)) (set! hyphen grob ((stop-translation-timestep engraver) (when (and text hyphen) (ly:grob-set-object! text 'left-hyphen hyphen)) (set! text #f) (set! hyphen #f) #(define (lyric-text::apply-magnetic-offset! grob) (let ((hyphen (ly:grob-object grob 'left-hyphen #f))) (when hyphen (let ((left-text (ly:spanner-bound hyphen LEFT))) (when (grob::has-interface left-text 'lyric-syllable-interface) (let* ((common (ly:grob-common-refpoint grob left-text X)) (my-x-ext (ly:grob-extent grob common X)) (left-x-ext (begin ;; Trigger magnetism for left-text (ly:grob-property left-text 'after-line-breaking) (ly:grob-extent left-text common X))) (delta (- (interval-start my-x-ext) (interval-end left-x-ext))) (details (ly:grob-property grob 'details)) (threshold (assoc-get 'squash-threshold details 0.2))) (when (< delta threshold) (ly:grob-translate-axis! grob (- delta) X #(define (lyric-hyphen::displace-bounds-first grob) ;; Make very sure this callback isn't triggered too early. (let ((left (ly:spanner-bound grob LEFT)) (right (ly:spanner-bound grob RIGHT))) (ly:grob-property left 'after-line-breaking) (ly:grob-property right 'after-line-breaking) (ly:lyric-hyphen::print grob))) \layout { \context { \Lyrics \consists #Left_hyphen_pointer_engraver \override LyricText.after-line-breaking = #lyric-text::apply-magnetic-offset! \override LyricHyphen.stencil = #lyric-hyphen::displace-bounds-first \override LyricText.details.squash-threshold = 10 \override LyricHyphen.minimum-distance = 0 \override LyricHyphen.minimum-length = 0.2 \override LyricSpace.minimum-distance = 1 } }
Re: bug in magnetic snapping lyrics engraver
Hi Jean, > To be honest, I don't know why the snippet is so complicated. Perhaps a corollary to Clarke's Law? “Every sufficiently primitive technology is indistinguishable from garbage.” ;) [No offence to the wonderful coders who wrote the existing snippet! Just a funny observation re: Clarke.] > I'd just have done: I was the main squeaky wheel for whom this grease was originally created. I'll test out your version and see if it solves all the use-cases I had/have. Cheers, Kieren.
Re: bug in magnetic snapping lyrics engraver
Le 06/04/2022 à 14:33, Werner LEMBERG a écrit : Is someone taking care of bugs in the magnetic snapping lyrics engraver? Here is an example where it fails to position lyrics correctly (see last system in the image). Werner PS: I've attached a version of `magnetic-lyrics.ily` that actually works with the current development version (using an updated `add-grob-definition` routine). To be honest, I don't know why the snippet is so complicated. I'd just have done: \version "2.23.7" #(define (Left_hyphen_pointer_engraver context) (let ((hyphen #f) (text #f)) (make-engraver (acknowledgers ((lyric-syllable-interface engraver grob source-engraver) (set! text grob))) (end-acknowledgers ((lyric-hyphen-interface engraver grob source-engraver) (when (not (grob::has-interface grob 'lyric-space-interface)) (set! hyphen grob ((stop-translation-timestep engraver) (when (and text hyphen) (ly:grob-set-object! text 'left-hyphen hyphen)) (set! text #f) (set! hyphen #f) #(define (lyric-text::apply-magnetic-offset! grob) (let ((hyphen (ly:grob-object grob 'left-hyphen #f))) (when hyphen (let* ((left-text (ly:spanner-bound hyphen LEFT)) (common (ly:grob-common-refpoint grob left-text X)) (my-x-ext (ly:grob-extent grob common X)) (left-x-ext (begin ;; Trigger magnetism for left-text (ly:grob-property left-text 'after-line-breaking) (ly:grob-extent left-text common X))) (delta (- (interval-start my-x-ext) (interval-end left-x-ext))) (details (ly:grob-property grob 'details)) (threshold (assoc-get 'squash-threshold details 0.2))) (when (< delta threshold) (ly:grob-translate-axis! grob (- delta) X)) #(define (lyric-hyphen::displace-bounds-first grob) ;; Make very sure this callback isn't triggered too early. (let ((left (ly:spanner-bound grob LEFT)) (right (ly:spanner-bound grob RIGHT))) (ly:grob-property left 'after-line-breaking) (ly:grob-property right 'after-line-breaking) (ly:lyric-hyphen::print grob))) \layout { \context { \Lyrics \consists #Left_hyphen_pointer_engraver \override LyricText.after-line-breaking = #lyric-text::apply-magnetic-offset! \override LyricHyphen.stencil = #lyric-hyphen::displace-bounds-first \override LyricText.details.squash-threshold = 0.7 \override LyricHyphen.minimum-distance = 0 \override LyricHyphen.minimum-length = 0 \override LyricSpace.minimum-distance = 1 } } << \new Voice = "foo" \relative c' { \repeat unfold 16 { a8 b a2 a8 b } } \new Lyrics \lyricsto "foo" { \repeat unfold 10 { foo } \repeat unfold 10 { foo -- \markup \caps bar } \repeat unfold 10 { \markup \bold syl -- la -- ble } a \markup \with-color #red ran -- \markup \box dom string of mo -- no -- syl -- la -- bic and mul -- ti -- \markup \fontsize #5 syl -- la -- bic \markup \bold \underline ver -- \markup \italic bi -- age \markup { \stencil #(make-circle-stencil 0.5 0 #f) } } Which seems to work, and doesn't have your first bug. Did I miss something? The second bug is super hard to fix: when you tell LilyPond about spacing constraints between lyrics, before line breaking, you need to assume a lyric syllable won't be moved to the left by 'magnetism', because if you do, the spacer might think it can space its right neighbor more to the left due to the space left by moving the syllable to the left, and if the compression cannot actually be done, it will collide. But when the compression does get done, and the room is left empty, horizontal spacing has already been done and it is too late to tell the right neighbor that it would have room on its left. Am I making sense? Jean
Re: Grace note between arpeggio mark and chord
On Wed, Apr 6, 2022 at 10:15 AM Jean Abou Samra wrote: ... > It's much simpler to put the arpeggio on the grace note and tweak its > positions. > > \version "2.22.2" > > \relative { >4 >\grace { > g'8\tweak positions #'(-4 . -1.5) \tweak extra-spacing-width > #'(-1.0 . 0) \arpeggio >} >4 | > } An arpeggio on the grace note works beautifully, thank you.
Re: Grace note between arpeggio mark and chord
Le 06/04/2022 à 17:44, Knute Snortum a écrit : Hi everyone. I have another engraving question. Without intervention, LilyPond puts a grace note to the left of an arpeggio mark. I want it to the right, between the arpeggio mark and the chord notes. Here is a snippet of the default behavior: %%% \version "2.22.2" \relative { 4 \grace { g'8 } 4\arpeggio | } %%% (I put in the other chords to show the horizontal spacing.) How I want it to look is like the attached picture. (I don't need the "a" cross-staff.) Just to show what I've tried, here is an example of one of my (horrible) attempts at solving the problem: %%% \relative { 4 4*1/4 \hideNotes -\tweak X-offset 3 \arpeggio \unHideNotes \once \override NoteColumn.X-offset = 2 \magnifyMusic #2/3 { g'8 } 4 | } %%% The horizontal spacing is way off and can never be tweaked to get it right. Any assistance would be greatly appreciated. It's much simpler to put the arpeggio on the grace note and tweak its positions. \version "2.22.2" \relative { 4 \grace { g'8\tweak positions #'(-4 . -1.5) \tweak extra-spacing-width #'(-1.0 . 0) \arpeggio } 4 | } Best, Jean
Grace note between arpeggio mark and chord
Hi everyone. I have another engraving question. Without intervention, LilyPond puts a grace note to the left of an arpeggio mark. I want it to the right, between the arpeggio mark and the chord notes. Here is a snippet of the default behavior: %%% \version "2.22.2" \relative { 4 \grace { g'8 } 4\arpeggio | } %%% (I put in the other chords to show the horizontal spacing.) How I want it to look is like the attached picture. (I don't need the "a" cross-staff.) Just to show what I've tried, here is an example of one of my (horrible) attempts at solving the problem: %%% \relative { 4 4*1/4 \hideNotes -\tweak X-offset 3 \arpeggio \unHideNotes \once \override NoteColumn.X-offset = 2 \magnifyMusic #2/3 { g'8 } 4 | } %%% The horizontal spacing is way off and can never be tweaked to get it right. Any assistance would be greatly appreciated. -- Knute Snortum
Re: bug in magnetic snapping lyrics engraver
> Here is an example where it fails to position lyrics correctly (see > last system in the image). And while we are at it: Here is another bug, already reported in https://lists.gnu.org/archive/html/lilypond-user/2020-03/msg00289.html I've slightly sharpened the test to exclude the possibility of kerning being the cause of the (buggy) result. Werner \version "2.20.0" \include "magnetic-lyrics.ily" \new Lyrics \lyricmode { "|foobar|" "|foobar|" \break foo -- "|bar|" "|foobar|" } \layout { \context { \Lyrics \override LyricWord.after-line-breaking = #(lyric-word-compressor 0.5) } \context { \Score \remove "Bar_number_engraver" } } \paper { indent = 0 ragged-right = ##t system-system-spacing.basic-distance = 0 system-system-spacing.minimum-distance = 0 system-system-spacing.padding = 0 }
Re: problem with extending 'magnetic snapping lyrics' engraver
>> but how about just >> changing >> >> (let* ((hyphen-sten (ly:lyric-hyphen::print hyphen)) >> >> to >> >> (let* ((hyphen-sten (ly:grob-property hyphen 'stencil)) >> >> >> ? Then you can do \override LyricHyphen.stencil = #what-you-want to >> get the result. > > D'oh, so simple, thanks again! Well, it doesn't work :-) The magnetic snapping engraver sets the stencil of all affected `hyphen` grobs to `empty-stencil`. On the other hand, the solution with a separate property for the formatter to be accessed with `ly:grob-property-data` seems to work just fine. Werner
bug in magnetic snapping lyrics engraver
Is someone taking care of bugs in the magnetic snapping lyrics engraver? Here is an example where it fails to position lyrics correctly (see last system in the image). Werner PS: I've attached a version of `magnetic-lyrics.ily` that actually works with the current development version (using an updated `add-grob-definition` routine). \version "2.23.7" \include "magnetic-lyrics.ily" << \new Voice = "foo" \relative c'' { d1 ~ | d1 | e16 f e2.. ~ | e1 | f1 | d1 | d1 ~ | d1 | e16 f e2.. ~ | e1 | f1 | d1 | d1 ~ | d1 | e16 f e2.. ~ | e1 | f1 | d1 | d1 ~ | d1 | e16 f e2.. ~ | e1 | f1 | d1 | d1 ~ | d1 | e16 f e2.. ~ | e1 | f1 | d1 | } \new Lyrics \lyricsto "foo" { Foo -- bar -- foo -- bar -- foo -- bar. Foo -- bar -- foo -- bar -- foo -- bar. Foo -- bar -- foo -- bar -- foo -- bar. Foo -- bar -- foo -- bar -- foo -- bar. Foo -- bar -- foo -- bar -- foo -- bar. } >> \paper { indent = 0 ragged-right = ##f line-width = 90\mm } \layout { \context { \Lyrics \override LyricWord.after-line-breaking = #(lyric-word-compressor 0.5) \override LyricHyphen.minimum-distance = #0 \override LyricSpace.minimum-distance = #1 } } \version "2.23.7" %% CHANGELOG %% %% 2022-04-21 Werner Lemberg %% %% * Update `add-grob-definition` to make it work with current development %% version (2.23.7). %% %% 2019-05-28 Thomas Morley %% %% * s/map/for-each/. %% * Fix comment typo. %% * New function `remove-line-starting-hyphens` to exclude line-starting %% `LyricHyphen`. %% %% 2014-03-19 %% %% * Initial version. \header { snippet-title = "Magnetic snapping lyric syllables" snippet-author = "David Nalesnik, Mike Solomon, Thomas Morley, Werner Lemberg" % snippet-source = "http://lists.gnu.org/archive/html/lilypond-user/2014-03/msg00489.html; % snippet-source = "https://lists.gnu.org/archive/html/lilypond-user/2019-05/msg00388.html; snippet-source = "https://lists.gnu.org/archive/html/lilypond-user/2022-04/msg00062.html; % https://lists.gnu.org/archive/html/lilypond-user/2022-04/msg00062.html snippet-description = \markup { This snippet handles lyric syllables that belong to one word together and ensures that there are no irritating gaps between them (solves issue 2458). } % add comma-separated tags to make searching more effective: tags = "lyrics, syllable, gap, hyphen" % is this snippet ready? See meta/status-values.md status = "undecided" } %% % here goes the snippet: % %% % ADD NEW GROB INTERFACE %% #(ly:add-interface 'lyric-word-interface "A word of lyrics. Includes syllables and hyphens." '(text-items)) %%% % CREATE NEW GROB PROPERTY #(define (define-grob-property symbol type? description) (if (not (equal? (object-property symbol 'backend-doc) #f)) (ly:error (_ "symbol ~S redefined") symbol)) (set-object-property! symbol 'backend-type? type?) (set-object-property! symbol 'backend-doc description) symbol) #(for-each (lambda (x) (apply define-grob-property x)) `( (text-items ,list? "Syllables and hyphens of a word of lyrics"))) %%% ADD DEFINITION OF GROB %%% #(define (add-grob-definition grob-name grob-entry) (let* ((meta-entry (assoc-get 'meta grob-entry)) (class(assoc-get 'class meta-entry #f)) (ifaces-entry (assoc-get 'interfaces meta-entry))) (set-object-property! grob-name 'translation-type? ly:grob-properties?) (set-object-property! grob-name 'is-grob? #t) (set! ifaces-entry (uniq-list (sort ifaces-entry symbol (interval-length hyphen-ex) threshold) '() ; no compression--DO NOTHING! (let* ((syl-a-text (ly:grob-property syl-a 'text)) (syl-a-text (if (markup? syl-a-text) syl-a-text (markup syl-a-text))) (syl-b-text (ly:grob-property syl-b 'text)) (syl-b-text (if (markup? syl-b-text) syl-b-text (markup syl-b-text))) (full-text (make-concat-markup (list syl-a-text syl-b-text (set! (ly:grob-property syl-a 'text) full-text) (set! (ly:grob-property syl-b 'text) empty-markup) (set! (ly:grob-property syl-a 'stencil) lyric-text::print) (set! (ly:grob-property syl-b 'stencil) lyric-text::print) (set! (ly:grob-property hyphen 'stencil) empty-stencil) #(define (lyric-word-compressor threshold) (lambda (grob) ; LyricWord (let* ((items (ly:grob-object grob 'text-items)) (item-list (ly:grob-array->list items))) (if (> (length item-list) 1) ; do nothing to monosyllabic words
Re: problem with extending 'magnetic snapping lyrics' engraver
> It's uncomfortable to have grob properties of procedure type, since > they are automatically resolved as callbacks. You set > LyricWord.hyphen-formatter to ly:lyric-hyphen::print. Then, when > you do > > (ly:grob-property grob 'hyphen-formatter) > > this not only looks up ly:lyric-hyphen::print in the property, but > executes it on the LyricWord and returns the result. Since > ly:lyric-hyphen::print is written to work on a LyricHyphen and not a > LyricWord, it gives up and returns '(). Then you try to apply the > "formatter" '() to the hyphen, which goes wrong. You could use > ly:grob-property-data, which skips callbacks, [...] Thanks a lot for the explanation! > but how about just > changing > > (let* ((hyphen-sten (ly:lyric-hyphen::print hyphen)) > > to > > (let* ((hyphen-sten (ly:grob-property hyphen 'stencil)) > > > ? Then you can do \override LyricHyphen.stencil = #what-you-want to > get the result. D'oh, so simple, thanks again! Werner
Re: problem with extending 'magnetic snapping lyrics' engraver
Le 06/04/2022 à 09:49, Werner LEMBERG a écrit : I'm trying to generalize the 'magnetic snapping lyrics' engraver (the most recent version posted as https://lists.gnu.org/archive/html/lilypond-user/2019-05/msg00389.html) by providing a new property `hyphen-formatter`, to be used instead of the hard-coded `ly:lyric-hyphen::print`. Attached you can see the final file together with a diff to the original version (ignoring whitespace), and an example. Unfortunately, it doesn't work, and I can't find the problem: It aborts with ``` ERROR: Wrong type to apply: () ``` Please advise. It's uncomfortable to have grob properties of procedure type, since they are automatically resolved as callbacks. You set LyricWord.hyphen-formatter to ly:lyric-hyphen::print. Then, when you do (ly:grob-property grob 'hyphen-formatter) this not only looks up ly:lyric-hyphen::print in the property, but executes it on the LyricWord and returns the result. Since ly:lyric-hyphen::print is written to work on a LyricHyphen and not a LyricWord, it gives up and returns '(). Then you try to apply the "formatter" '() to the hyphen, which goes wrong. You could use ly:grob-property-data, which skips callbacks, but how about just changing (let* ((hyphen-sten (ly:lyric-hyphen::print hyphen)) to (let* ((hyphen-sten (ly:grob-property hyphen 'stencil)) ? Then you can do \override LyricHyphen.stencil = #what-you-want to get the result. Jean
problem with extending 'magnetic snapping lyrics' engraver
I'm trying to generalize the 'magnetic snapping lyrics' engraver (the most recent version posted as https://lists.gnu.org/archive/html/lilypond-user/2019-05/msg00389.html) by providing a new property `hyphen-formatter`, to be used instead of the hard-coded `ly:lyric-hyphen::print`. Attached you can see the final file together with a diff to the original version (ignoring whitespace), and an example. Unfortunately, it doesn't work, and I can't find the problem: It aborts with ``` ERROR: Wrong type to apply: () ``` Please advise. Werner \version "2.23.7" %% CHANGE-LOG harm () %% %% line 52: %% map becomes for-each %% %% line 133: %% typo in comment %% %% lines 234 ff, 260: %% exclude line-starting LyricHyphen \header { snippet-title = "Magnetic snapping lyric syllables" snippet-author = "David Nalesnik, Mike Solomon, harm" % snippet-source = "http://lists.gnu.org/archive/html/lilypond-user/2014-03/msg00489.html; snippet-source = "see https://lists.gnu.org/archive/html/lilypond-user/2019-05/msg00388.html; snippet-description = \markup { This snippet handles lyric syllables that belong to one word together and ensures that there are no irritating gaps between them (solves issue 2458). } % add comma-separated tags to make searching more effective: tags = "lyrics, syllable, gap, hyphen" % is this snippet ready? See meta/status-values.md status = "undecided" } %% % here goes the snippet: % %% % ADD NEW GROB INTERFACE %% #(ly:add-interface 'lyric-word-interface "A word of lyrics. Includes syllables and hyphens." '(text-items hyphen-formatter)) %%% % CREATE NEW GROB PROPERTY #(define (define-grob-property symbol type? description) (if (not (equal? (object-property symbol 'backend-doc) #f)) (ly:error (_ "symbol ~S redefined") symbol)) (set-object-property! symbol 'backend-type? type?) (set-object-property! symbol 'backend-doc description) symbol) %% harm: #(for-each (lambda (x) (apply define-grob-property x)) `( (text-items ,list? "Syllables and hyphens of a word of lyrics") (hyphen-formatter ,ly:stencil? "Stencil for formatting hyphens"))) %%% ADD DEFINITION OF GROB %%% #(define (add-grob-definition grob-name grob-entry) (let* ((meta-entry (assoc-get 'meta grob-entry)) (class(assoc-get 'class meta-entry #f)) (ifaces-entry (assoc-get 'interfaces meta-entry))) (set-object-property! grob-name 'translation-type? ly:grob-properties?) (set-object-property! grob-name 'is-grob? #t) (set! ifaces-entry (uniq-list (sort ifaces-entry symbol (interval-length hyphen-ex) threshold) '() ; no compression--DO NOTHING! (let* ((syl-a-text (ly:grob-property syl-a 'text)) (syl-a-text (if (markup? syl-a-text) syl-a-text (markup syl-a-text))) (syl-b-text (ly:grob-property syl-b 'text)) (syl-b-text (if (markup? syl-b-text) syl-b-text (markup syl-b-text))) (full-text (make-concat-markup (list syl-a-text syl-b-text (set! (ly:grob-property syl-a 'text) full-text) (set! (ly:grob-property syl-b 'text) empty-markup) (set! (ly:grob-property syl-a 'stencil) lyric-text::print) (set! (ly:grob-property syl-b 'stencil) lyric-text::print) (set! (ly:grob-property hyphen 'stencil) empty-stencil) #(define (lyric-word-compressor threshold) (lambda (grob) ; LyricWord (let* ((items (ly:grob-object grob 'text-items)) (item-list (ly:grob-array->list items))) (if (> (length item-list) 1) ; do nothing to monosyllabic words (let* ((formatter (ly:grob-property grob 'hyphen-formatter)) (text-grobs (filter (lambda (item) (grob::has-interface item 'lyric-syllable-interface)) item-list)) (hyphen-grobs (filter (lambda (item) (grob::has-interface item 'lyric-hyphen-interface)) item-list))) (define (helper fmt seed tx-list hy-list) (if (and (pair? (cdr tx-list)) (pair? hy-list)) (let ((next-syl (cadr tx-list)) (hyphen (car hy-list))) (compress-pair fmt seed hyphen next-syl threshold) (if (equal? empty-markup (ly:grob-property next-syl 'text)) (helper fmt seed (cdr tx-list) (cdr hy-list)) (helper fmt
Re: how to repeat a scheme function that creates a Score
Le 06/04/2022 à 07:40, Jeff Olson a écrit : Two questions below re: (a) looping and (b) random seed. In order to investigate some other problems I'm having in a large project (pagination, memory usage) I learned enough scheme (barely) to define a function that generates a new score with each invocation: -- \version "2.22.0" \include "gen-music.ily" % each invocation of scr generates a new score of different length pcn = 0 scr = #(define-scheme-function () () (set! pcn (1+ pcn)) #{ \score { \header { piece = \markup{ "Piece " #(number->string pcn) } } { \gen-music \bar "|."} } #} ) -- (The include file, gen-music.ily, is attached, and the above ~MWE is also attached as MWE-do-scr.ly.) Question (a): My main question is how to write a scheme function that will invoke my scr function N times, where N could be a number like 1000. So far the only way I know how to do multiple invocations is by explicitly hard-coding "\scr \scr ..." in blocks and copy/pasting those blocks. Looking for a better way, I realized I don't even know how to get one line of scheme to do 2 invocations (needed for tail recursion approach). I can make them execute, in some cases, but not to produce pdf output (never gets to "Interpreting music..."). Part of this may be #(scr) vs $(scr). The attached MWE file has lots of my failed attempts commented out (I'm at a teachable moment if someone has a moment to teach). Or just point me to the right manual page(s). Here is a piece of code that works: $@(map (lambda (i) (scr)) (iota 10)) Now let's go through your attempt to see why they are failing. #(define scors (lambda (n) (if (= n 1) (scr) ((scr) (scors (- n 1) ) #(scors 2) This one is trying to apply a score (the result of (scr)) as a function. A score is not a function. Also, if n = 1, (src) is generated, which is not a list, so at the end of the day you get an "improper list" (something that looks like a list but doesn't have the empty list at the end of the cdr chain). Rather do #(define scors (lambda (n) (if (= n 0) '() (cons (scr) (scors (- n 1) ) #(scors 2) That doesn't error out (scors is applied successfully), but no output either, as you noticed. The problem is that when LilyPond reads a toplevel expression introduced by #, it refrains from interpreting the result, since that is the main way you can write code that operates via side effects on the toplevel (think #(define ...) and such). You need to be a little more insistent, with $. #(define scors (lambda (n) (if (= n 0) '() (cons (scr) (scors (- n 1) ) $(scors 2) Now that gives the error "bad expression type". Indeed, LilyPond knows how to interpret a score, but not a list of scores. So you need to splice the list into several scores that LilyPond will interpret separately. You can do that with $@. Thus, this works: #(define scors (lambda (n) (if (= n 0) '() (cons (scr) (scors (- n 1) ) $@(scors 2) Now to your second attempt: #(for-each (lambda (ignore) (scr)) '(1 2 3 4 5)) This has the same problem of # vs. $@. Also, it is using for-each, which applies a function for its side effect but does not remember the result. In this case, you want a list of the results, which is what map is for. $@(map (lambda (ignore) (scr)) '(1 2 3 4 5)) Now to #(begin (scr) (scr) (scr)) and $(begin (scr) (scr) (scr)) The first discards the result because of #. The second calls src thrice, and discards the results of the two first invocations -- that's what begin is for. As Valentin pointed out while I was writing this, you could use add-score to let LilyPond know about your score via a side effect rather than by returning them. #(begin (add-score (scr)) (add-score (scr)) (add-score (scr))) For the examples at the end, you need $@mine, which is the only one you didn't try :-) Best, Jean
Re: how to repeat a scheme function that creates a Score
On 2022-04-05 10:40 pm, Jeff Olson wrote: Question (a): My main question is how to write a scheme function that will invoke my scr function N times, where N could be a number like 1000. #(for-each add-score (map (lambda (x) #{ \scr #}) (iota 5))) Replace 5 with whatever. -- Aaron Hill
Re: Temporary div. multiple staffs
On Wed, 6 Apr 2022 at 08:39, Xavier Scheuer wrote: > Hello, > > One way mentioned in the documentation is to use the "Keep_alive_together_engraver" in combination with keepAliveInterfaces and VerticalAxisGroup.remove-layer. > See NR 1.6.2 Modifying single staves > Hiding staves > https://lilypond.org/doc/v2.23/Documentation/notation/writing-parts#hiding-staves Wrong link, correct one: https://lilypond.org/doc/v2.23/Documentation/notation/modifying-single-staves.html#hiding-staves Cheers, Xavier -- Xavier Scheuer
Re: Temporary div. multiple staffs
On Wed, 6 Apr 2022 at 07:21, Evan Driscoll wrote: > > Another question, one I've struggled with before. > > The part splits out temporarily into divisi parts on multiple staffs. I always have trouble getting the correct incantations to get the correct result. > > A naive attempt results in http://lilybin.com/1l8whf/5. This is enough to keep working, but it looks bad -- barlines don't cross between staffs, and there's no grouping a la https://lilypond.org/doc/v2.22/Documentation/69/lily-9c91c2b7.png from the manual. > > I can get a pair of staffs that are correct on their own by creating a StaffGroup with two new staffs -- http://lilybin.com/1l8whf/9 -- but the original staff continues through. Omitting the explicit \new Staff invocations doesn't help -- http://lilybin.com/1l8whf/11. > > What's the right way to do this? Hello, One way mentioned in the documentation is to use the "Keep_alive_together_engraver" in combination with keepAliveInterfaces and VerticalAxisGroup.remove-layer. See NR 1.6.2 Modifying single staves > Hiding staves https://lilypond.org/doc/v2.23/Documentation/notation/writing-parts#hiding-staves Cheers, Xavier -- Xavier Scheuer
Re: Temporary div. multiple staffs
(Please keep the mailing list on all replies.) On 2022-04-05 11:06 pm, Evan Driscoll wrote: On Wed, Apr 6, 2022 at 12:37 AM Aaron Hill wrote: Unsure there is a definitively "right" way... but here's an option: http://lilybin.com/1l8whf/12 Move the StaffGroup declaration outside the music. Also, you can name contexts so you can reference an existing one to avoid creating new ones (explicitly or implicitly). Perfect, thanks! As a final tweak, in case anyone finds this thread in the future, here's how to omit the time signature on the new staff: http://lilybin.com/1l8whf/15 Though a question -- I discovered that adding *just* the \new StaffGroup on the "outside" made things work -- on the simplified example, that'd be something like http://lilybin.com/1l8whf/16. In other words, that works even without explicitly naming the existing Staff context and referring to it with \context. Is there any difference between these, aside from possible readability arguments? In many cases, you can rely on the implicit handling of contexts. Your example #16 above relies on the implicit continuation of the current context as only the divisi staff is explicitly created, so things do work as expected. But note that this new staff appears below the original one. If you wanted it to be above, consider: http://lilybin.com/1l8whf/17 (I added color just to make it easier to see which context is which.) -- Aaron Hill
Re: TextScript vertical alignment in Dynamics context
At 12:21 on 05 Apr 2022, Jean Abou Samra wrote: Le 05/04/2022 à 09:48, Mark Knoop a écrit : Hi, I'm trying to align markups in a Dynamics context to their baseline, but they always align their tops. Can't figure out what property to set to achieve this. Example follows - I'd like the markups on the first line (which are in a Dynamics context) to align DOWN rather than UP, i.e. to match the behaviour of the markups on the second line (which are in a Voice context). Thanks in advance for any help on this. The alignment of text scripts is done via side positioning (side-position-interface). Here they position against nothing, so the alignment code just keeps them aligned on a fictive line at 0. The direction of these text scripts is DOWN, so in effect they align on their tops. If you want them aligned on their bottoms, set them to the other direction. \new Dynamics \with { \override TextScript.direction = #UP } ... Alternatively, use a mechanism that makes more sense for your use case, self alignment (self-alignment-interface). \new Dynamics \with { \override TextScript.Y-offset = #ly:self-alignment-interface::y-aligned-on-self \override TextScript.self-alignment-Y = #DOWN } ... Best, Jean Thanks Jean! -- Mark Knoop
Re: how to repeat a scheme function that creates a Score
Hello Jeff, A scheme-function will only be able to output a single top-level-score like this. You should rather do a void-function that calls (add-score #{ \score {...} #}) directly. Similarly you can use (add-text ...) to add top-level markups. Cheers, Valentin Am Mittwoch, 6. April 2022, 07:40:00 CEST schrieb Jeff Olson: > Two questions below re: (a) looping and (b) random seed. > > > In order to investigate some other problems I'm having in a large > project (pagination, memory usage) I learned enough scheme (barely) to > define a function that generates a new score with each invocation: > > -- > > \version "2.22.0" > > \include "gen-music.ily" > > % each invocation of scr generates a new score of different length > pcn = 0 > scr = #(define-scheme-function () () > (set! pcn (1+ pcn)) > #{ > \score { > \header { piece = \markup{ "Piece " #(number->string pcn) } } > { \gen-music \bar "|."} } > #} ) > > -- > > (The include file, gen-music.ily, is attached, and the above ~MWE is > also attached as MWE-do-scr.ly.) > > Question (a): > > My main question is how to write a scheme function that will invoke my > scr function N times, where N could be a number like 1000. > > So far the only way I know how to do multiple invocations is by > explicitly hard-coding "\scr \scr ..." in blocks and copy/pasting those > blocks. > > Looking for a better way, I realized I don't even know how to get one > line of scheme to do 2 invocations (needed for tail recursion > approach). I can make them execute, in some cases, but not to produce > pdf output (never gets to "Interpreting music..."). Part of this may be > #(scr) vs $(scr). The attached MWE file has lots of my failed attempts > commented out (I'm at a teachable moment if someone has a moment to > teach). Or just point me to the right manual page(s). > > Question (b): > > My secondary question is very simple. How do you set the seed for > scheme's "random" function (used in my gen-music.ily). I'd like to get > the repeatability of a pseudo-random number generator. > > TIA, > Jeff > > P.S. May you smile when you see the generated music. signature.asc Description: This is a digitally signed message part.