Dear Madams and Sirs,
dear users of lilypond.

I would like to bring to your attention some perhaps prototypical applications of lilypond, carried out in the last years:

1) http://senzatempo.de/mahler/gmahler_sinf3_satz1.html

is a 120 pages analysis of the first movement of the Third Symphony of Gustav Mahler (in the German language). It is remarkable as a *dynamic document": The text and music paragraphs can be folded in and out in various combinations. This project could certainly not have been realized with a commercial GUI-based note setting program, because the music source texts, with and without analytic remarks (=lilypond sources) must be created *programmatically*, to be manageable.

There is only one coherent integrated source text, which can be reached by the very last link on the page.

We consider this project a significant step in the format of musicology publications, and a thing which only lilypond can support.


2) http://markuslepper.eu/publishscores/lepper-op27+33-20181204.pdf
may perhaps prove the feasibility of longer scores: it is a six-act opera with more than sixhundred pages.

3) http://markuslepper.eu/publishscores/lepper-op37-20160529.pdf
is a string quartett which may be interesting because over a third of its movements had been composed *directly* by writing lilypond sources. On http://markuslepper.eu/someSounds.html you can find a sample player generation, (in-directly) driven by the lilypond midi output.

4) As an attachment you find a collection of functions useful for composing, namely for extracting and combining sub-sections of monodic structures, a job we have not found covered in the standard lilypond tool sets. (One source file and the generated pdf for control; free to use under CC-BY-SA)

Hoping to be useful,
yours sincerly,
  Dr. Lepper

-------------------------------------------------------
Dr.-Ing. M.Lepper
Übersetzerbau und Sprachdesign -- Language Design and Compiler Construction
Komposition und Musiktheorie -- Composition and Theory of Music
Heinrich-Heine-Str. 10 10179 Berlin
+49  176 76 524 521
-------------------------------------------------------

Attachment: temaTransform.pdf
Description: Adobe PDF document

% lilyExp / temaTransform.ly
% CC-BY-SA markuslepper.eu 20181210


\include "deutsch.ly"
\version "2.16.0"

% ---------------------------------------------------------------------

%{
    The lilypond scheme functions defined herein allow to extract segments from and
    insert segments into a music structure. They are very useful when composing fugues etc.
    directly as lilypond input.

    The function signatures are:

    mbExtract music  from to     --> deliver the indicated segment.
    mbRemove  music  from to     --> cut out the indicated segment (= the complement to mbExtract).
    mbInsert  music  at  music   --> insert the second music into the first, shifting the
                                         rest after the point of insertion to the right.
    mbReplace music  at  music   --> insert the second music into the first, overwriting the 
                                         rest after the point of insertion.

    ATTENTION: The time points "from" and "to" must be the start times of notes/pauses in 
    the music structure. Otherwise an automated split of one note in two would be necessary,
    which is NOT implemented here


    ATTENTION: We did NOT find a global constant definition for "Rational Max Value" and
    use inline "99/1" instead.


    ATTENTION: The tests work fine with lilypond 2.16.0 But we get many times
"programming error: music has no duration
continuing, cross fingers"


The code has been inspired by
http://lilypond.org/doc/v2.18/Documentation/extending/doubling-a-note-with-slurs-_0028example_0029

Further infos used were 
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-tutorial
-> http://www.schemers.org/Documents/Standards/R5RS/
-> http://www.schemers.org/Documents/Standards/R5RS/HTML/
-> http://www.gnu.org/software/guile/
%}



% phase zero: no music written out yet
% cases
%     cursor   after
%     |--------|----
%     |from   (|to  |to)
%         |from
%     special case:
%           |to 

#(define (mbCut0 notes from to cursor res)
     (if (null? notes)
         res
         (let*((rest (mbNextEvent (cdr notes)))
               (note (car notes))
               (dura (ly:moment-main (ly:music-duration-length note)))
               (after(+ cursor dura))
               )
               (cond ((= cursor from)
                      (if (< to after)
                          (mbCut00 note (- to from))
                          (mbCut1 rest to after (list (ly:music-deep-copy note)))
                      ))
                     ((< from after)
                      (let*(newnote (ly:music-deep-copy note))
                           (X (set! (ly:music-property newnote 'duration) 
                                    (- (min after to) from)) )
                           (if (< to after)
                               ('newnote)
                               (mbCut1 rest to after (list newnote)))
                      ))
                     (else (mbCut0 rest from to after res))
               )
            )
      )
 )


% phase one: currently writing out
% cases
%     cursor   after
%     |--------|----
%     |to
%         |to
%              |to |to

#(define (mbCut1 notes to cursor res)
     (if (null? notes)
         res
         (let*((rest (mbNextEvent (cdr notes)))
               (note (car notes))
               (dura (ly:moment-main (ly:music-duration-length note)))
               (after(+ cursor dura))
              )
              (cond ((= cursor to) res)
                    ((< to after)  (append res (list(mbCut00 note (- to cursor)))) )
                    (else (mbCut1 rest to after 
                            (append res (list (ly:music-deep-copy note)))))
              ))
     )
 )

#(define (mbCut00 note length)
        (let*((newnote (ly:music-deep-copy note))
              (X (set! (ly:music-property newnote 'duration)
                       (ly:make-duration 0 0 length) 
                 ))
             )
             (list newnote))
 )



mbExtract = #(define-music-function (parser location music from to)
                                    (ly:music? number? number?)
   "Extract the notes from music which lie between from and to.
    (Partial inclusion of duration values currently not supported!)"
     (make-music 'SequentialMusic 'elements
      (mbCut0 (mbNextEvent (list music)) from to 0/1 '() )
     )
  )

mbRemove = #(define-music-function (parser location music from to)
                                    (ly:music? number? number?)
   "Remove the notes from music which lie between from and to.
    (Partial inclusion of duration values currently not supported!)"
   (make-music 'SequentialMusic 'elements
      (append
        (mbCut0 (mbNextEvent (list music)) 0/1 from  0/1 '() )
        (mbCut0 (mbNextEvent (list music)) to 99/1   0/1 '() )
      )
   )
)

mbInsert = #(define-music-function (parser location music at musicIN)
                                    (ly:music? number? ly:music?)
   "Insert the second music into the first at the given position.
    (Partial inclusion of duration values currently not supported!)"
   (make-music 'SequentialMusic 'elements
      (append
        (mbCut0 (mbNextEvent (list music))  0/1 at  0/1 '() )
        (list musicIN)
        (mbCut0 (mbNextEvent (list music)) at 99/1  0/1 '() )
      )
   )
)

mbReplace = #(define-music-function (parser location music at musicIN)
                                    (ly:music? number? ly:music?)
   "Insert the second music into the first at the given position,
    replacing the notes.
    (Partial inclusion of duration values currently not supported!)"
   (let*((insDura  (mbAddDurations (list musicIN)) )
         (XX (display insDura))
        )
        (make-music 'SequentialMusic 'elements
          (append
           (mbCut0 (mbNextEvent (list music)) 0/1 at  0/1 '() )
           (list musicIN)
           (mbCut0 (mbNextEvent (list music)) (+ at insDura) 99/1   0/1 '() )
          ))
   )
)


%  Horizontal iterator steps through deep nestings of 
%  C++ objects of some "music container classes" 
%  and delivers "events" and "chord-events".
%  Argument must be a list of C++ music objects. As long as such a container is
%  at first position, it is replaced by its contents.

#(define (mbNextEvent iter)
         (if (null? iter) 
             iter
             (let* ((first (car iter))
                    (rest (cdr iter))
                    (types (ly:music-property first 'types)))
                   (cond ((memq 'music-wrapper-music types)
                          (mbNextEvent (append(list(ly:music-property first 'element))
                                               rest)))
                         ((or (memq 'music-sequential-music types)
                              (memq 'sequential-music types))
                          (mbNextEvent (append(ly:music-property first 'elements) rest)))
	                 (else iter)
                    )))
 )

#(define (mbAddDurations iter)
         (mbAddDurations0 (mbNextEvent iter) 0/1)
 )

#(define (mbAddDurations0 iter res)
         (if (null? iter) 
             res
             (let*( (dura (ly:moment-main(ly:music-duration-length(car iter))) ) )
                  (mbAddDurations0 (mbNextEvent (cdr iter)) (+ res dura))
             ))
 )

#(define (test iter)
         (let*((XX0 (display "=========== INCOMING VALUE : ============= \n\n"))
               (XX1  (display iter))
               (XX2 (display "\n-----------\n"))
               (XX3 (display "\n-----------\n"))
               (iter2 (mbNextEvent iter))
               (XX3 (display "\n-----------  AFTER SPLICE  : \n"))
               (XX31 (if (null? iter2) #t (display  iter2)))
               (XX4 (display "\n-----------\n"))
              )
              (if (null? iter2) #t (test (cdr iter2)) )
          )
)

% ----------------------------------------------------------------
% TEST SECTION
%  call  lilypond temaTransform
% ----------------------------------------------------------------


tema = \relative d' {d2 a'  | f d | cis d4 e | f2~ f8 g f e} 

\score {
  <<
  \new Staff {

%%% #( test (list tema))

    \tema | 
    \mbRemove \tema #3/2 #6/2  | 
  }

  \new Staff {
    R1 | R1 | e'2 \mbExtract \tema #1/2 #99
    \mbReplace \tema #2/2 {fis'2 }
  }

  \new Staff {
    \mbInsert \tema #3/2 {g8 a h c'}
  }
  >>
}


%eof

%eof
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to