1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
%% DO NOT EDIT this file manually; it is automatically
%% generated from LSR http://lsr.di.unimi.it
%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
%% and then run scripts/auxiliar/makelsr.py
%%
%% This file is in the public domain.
\version "2.18.0"
\header {
= "automatic-notation, really-cool, scheme-language"
= "
A lilypond score internally is just a Scheme expression, generated by
the lilypond parser. Using scheme, one can also automatically generate
a score without an input file. If you have the music expression in
scheme, a score can be generated by simply calling (scorify-music music
parser) on your music. This will generate a score object, for which you
can then set a custom layout block with (let* ((layout
(ly:output-def-clone $defaultlayout)))
; modify the layout here, then assign it:
(ly:score-add-output-def! score layout)
)
Finally, all you have to do it to pass this score to lilypond for
typesetting. This snippet defines functions @code{(add-score parser
score)}, @code{(add-text parser text)} and @code{(add-music parser
music)} to pass a complete score, some markup or some music to lilypond
for typesetting.
This snippet also works for typesetting scores inside a @code{\\book
@{...@}} block, as well as top-level scores. To achieve this, each
score schedulled for typesetting is appended to the list of toplevel
scores and the toplevel-book-handler (which is a scheme function called
to process a book once a @code{\\book@{..@}} block is closed) is
modified to inser all collected scores so far to the book.
"
= "Generating whole scores (also book parts) in scheme without using the parser"
} % begin verbatim
#(define-public (add-score parser score)
(ly:parser-define! parser 'toplevel-scores
(cons score (ly:parser-lookup parser 'toplevel-scores))))
#(define-public (add-text parser text)
(add-score parser (list text)))
#(define-public (add-music parser music)
(collect-music-aux (lambda (score)
(add-score parser score))
parser
music))
#(define-public (toplevel-book-handler parser book)
(map (lambda (score)
(ly:book-add-score! book score))
(reverse! (ly:parser-lookup parser 'toplevel-scores)))
(ly:parser-define! parser 'toplevel-scores (list))
(print-book-with-defaults parser book))
#(define-public (book-score-handler book score)
(add-score parser score))
#(define-public (book-text-handler book text)
(add-text parser text))
#(define-public (book-music-handler parser book music)
(add-music parser music))
%%%
%% Just some example score to show how to use these functions:
#(define add-one-note-score #f)
#(let ((pitch 0))
(set! add-one-note-score
(lambda (parser)
(let* ((music (make-music 'EventChord
'elements (list (make-music 'NoteEvent
'duration (ly:make-duration 2 0 1/1)
'pitch (ly:make-pitch 0 pitch 0)))))
(score (scorify-music music parser))
(layout (ly:output-def-clone $defaultlayout))
(note-name (case pitch
((0) "do")
((1) "ré")
((2) "mi")
((3) "fa")
((4) "sol")
((5) "la")
((6) "si")
(else "huh")))
(title (markup #:large #:line ("Score with a" note-name))))
(ly:score-add-output-def! score layout)
(add-text parser title)
(add-score parser score))
(set! pitch (modulo (1+ pitch) 7)))))
oneNoteScore =
#(define-music-function (parser location) ()
(add-one-note-score parser)
(make-music 'Music 'void #t))
%%%
\book {
\oneNoteScore
}
\book {
\oneNoteScore
\oneNoteScore
}
% Top-level scores are also handled correctly
\oneNoteScore
\oneNoteScore
|