Hello Tom, you accidently forwarded me the digest. Unless there is a reason not to when replying to a message please change the Subject to match the discussion, make sure to include the list to the recipients and optimally adjust the quoted body to not include the whole digest.
If you’ve got any questions about what is happening here feel free to ask. We are using here that we can "register" scores to the current book(part) from scheme using the function (add-score score) (similarly we can use (add-text markup) to add a stand-alone markup to the book). This allows us to construct scores using scheme, which makes automated handling of thing much easier. So what we want to have is a function that creates a score using standard elements, that is, chords, a voice, and lyrics. At the same time we want to be flexible enough to leave out some of these elements. So we define a void-function (that is a scheme function that returns nothing) that takes: → The title of the score → Optionally the composer of the score → A piece of music for the voice or #f → A piece of music for the chords or #f → A piece of lyrics (which is also music) or a list of such (to allow stanzas) or #f The syntax here is myfunction = #(define-void-function (arg1 arg2 ...) (type-check-arg1 type-check-arg1 ...) function-body) where the type-checks are predicates (functions returning truth values) or (predicate default) for optional arguments with default value. We then use let* which allows us to locally bind some variables (similar to let, but let* lets each binding access the previous bindings). The syntax here is (let* ((var1 value1) (var2 value2) ...) body) So we define CN, FB, VC, LY as shorthands for the ChordNames, FretBoards, Voice and Lyrics. If one of these is set to #f we use empty-music, which is music containing nothing, else we create the contexts with the specified music. As lyrics might be a list of lyrics we have to handle both of these things, which is done by either doing something to the lyrics or by doing to the whole list (which is the (map function list) expression). We also need to handle the presence of the Voice here. If for some reason voice is set to #f we should not align the lyrics to anything and rely on the lyrics themselves being rhythmicised. To make further handling easier we make sure that LY is list even when lyrics isn’t. [WHICH BY THE WAY I FORGOT IF lyrics IS #f, THIS IS FIXED IN THE APPENDED FILE!] So we get a big expression basically just checking: → Is lyrics #f? If so use (in the fixed version a list of) empty music. → Is voice #f? If so do not use \lyricsto "auto" → Is lyrics music or a list? If so we use map to create Lyrics for each member of the list. If not we create a list containing a single Lyrics context. Next we basically want to put all of these contexts in a << ... >> construct. This is known as "simultaneous music" and is internally stored as (make-music 'SimulataneousMusic 'elements A-LIST-OF-MUSIC) where the list of music contains the content of ... . This means we simply have to construct this list and then do the above call with this list. I won’t go into detail what a LISP list is, if you are interested please ask or checkout what I wrote to Simon earlier this thread. But basically if L is a list then `(,a ,b ,c . ,L) will be L with a, b and c prepended. As Jean pointed out this can be done by (cons* a b c L). So we do a (cons* CN FB VC LY) to create a list of all the contexts we created so far (and maybe some empty music, but we do not really have to care about these). Next we create a score with the specified header informations and the previously created simultaneous music. Using #{ ... #} allows us to parse the content between as Lilypond syntax instead of scheme syntax. So we do #{ \score { ... } #} and create the score just like we would in Lilypond syntax. Then the last thing we do is use add-score to add this newly created score to the current book. Cheers, Valentin Am Donnerstag, 24. Februar 2022, 00:05:42 CET schrieben Sie: > Thank you for completely upgrading my lead sheet template. WOW! I haven't > acknowledged because it's so advanced. You've added a bunch of advanced > features I'm trying to understand thoroughly.
% Lead sheet with: % - Guitar fretboard diagrams % - Override a predefined fretboard diagram % - Pickup note with text above it suppressed % - Chord and other text suppressed above the pickup note %%%% Please send critiques to tomcampb...@gmail.com \version "2.22" %%%% STARTING INCLUDABLE TEMPLATE #(define (music-or-false? m) (or (ly:music? m) (not m))) #(define (music-or-list-or-false? m) (or (music-or-false? m) (list? m))) leadsheetScore = #(define-void-function (title composer voice chords lyrics) (markup? (markup? "Trad.") music-or-false? music-or-false? music-or-list-or-false?) (let* ((CN (if chords #{ \new ChordNames $chords #} (empty-music))) (FB (if chords (if voice #{ \new FretBoards $chords #} #{ \new FretBoards \with { \consists Bar_engraver \override BarLine.bar-extent = #'(-6 . 3) } $chords #}) (empty-music))) (VC (if voice #{ \new Staff \new Voice="auto" $voice #} (empty-music))) (LY (if lyrics (if voice (if (ly:music? lyrics) (list #{ \new Lyrics \lyricsto "auto" $lyrics #}) (map (lambda (x) (if (ly:music? x) #{ \new Lyrics \lyricsto "auto" $x #} (if (pair? x) ; If x is a pair of the form (key . music) we create a stanza indication #{ \new Lyrics \lyricsto "auto" { \set stanza = $(if (markup? (car x)) (car x) (format "~a" (car x))) $(cdr x) } #}))) lyrics)) (if (ly:music? lyrics) (list #{ \new Lyrics $lyrics #}) (map (lambda (x) (if (ly:music? x) #{ \new Lyrics $x #} (if (pair? x) ; If x is a pair of the form (key . music) we create a stanza indication #{ \new Lyrics { \set stanza = $(if (markup? (car x)) (car x) (format "~a" (car x))) $(cdr x) } #}))) lyrics))) (list (empty-music)))) (mus (make-music 'SimultaneousMusic 'elements (cons* CN FB VC LY))) (score #{ \score { \header { title = #title composer = #composer } $mus \layout { } \midi { } } #})) (add-score score))) \paper { print-all-headers = ##t } %%%% STARTING CONTENT \include "predefined-guitar-fretboards.ly" % Override predefined fretboard for e minor. % This just adds a G to the first (highest) string. % A little contrived but it's brief. \storePredefinedDiagram #default-fret-table \chordmode { e:m } #guitar-tuning #"o;2-2;2-3;o;o;3-4;" theMelody = \relative c { \clef treble \key e \minor \time 6/8 % Pickup note \partial 8 e'8 % Verse melody (truncated for clarity) g4 a8 b4 e8 d8. e16 fis8 e4 b16 c } theLyrics = \lyricmode { When Daph -- ne from fair Phoe -- bus did fly the __ } theChords = \chordmode { % Replace the N.C. that would appear over % the pickup note \time 6/8 \set noChordSymbol = "" \partial 8 r8 e2.:min b4.:min e4.:min } %%% SAME AS BEFORE \leadsheetScore "Hit and Miss (Daphne)" \theMelody \theChords \theLyrics %%% NO CHORDS \leadsheetScore "Hit and Miss (Daphne)" "theComposer" \theMelody ##f \theLyrics sI = \theLyrics sII = \lyricmode { This is a se -- cond stan -- _ _ za, } %%% MULTIPLE LINES OF LYRICS \leadsheetScore "Hit and Miss (Daphne)" "theComposer" \theMelody ##f #`(,sI ,sII) %% DUE TO NEW VALUES BEING APPENDED WE NEED TO REVERSE THE ORDER alyrics.2 = \sII alyrics.1 = \sI %%% MULTIPLE LINES OF LYRICS WITH STANZA INDICATIONS NOT GIVEN IN THE LYRICS THEMSELVES (BUT BY AN ALIST) \leadsheetScore "Hit and Miss (Daphne)" "theComposer" \theMelody ##f \alyrics %%% NO LYRICS \leadsheetScore "Hit and Miss (Daphne)" "theComposer" \theMelody ##f ##f rhythmicLyrics = \lyricmode { When8 Daph4 -- ne8 from4 fair8 Phoe8. -- bus16 did8 fly4 the8 } %%% NO VOICE \leadsheetScore "Hit and Miss (Daphne)" "theComposer" ##f \theChords \rhythmicLyrics
signature.asc
Description: This is a digitally signed message part.