lydown 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +357 -0
- data/bin/lydown +149 -0
- data/lib/lydown/core_ext.rb +121 -0
- data/lib/lydown/errors.rb +2 -0
- data/lib/lydown/lilypond.rb +41 -0
- data/lib/lydown/parsing/lydown.treetop +160 -0
- data/lib/lydown/parsing/nodes.rb +191 -0
- data/lib/lydown/parsing.rb +33 -0
- data/lib/lydown/rendering/base.rb +24 -0
- data/lib/lydown/rendering/comments.rb +7 -0
- data/lib/lydown/rendering/defaults.yml +185 -0
- data/lib/lydown/rendering/figures.rb +106 -0
- data/lib/lydown/rendering/lyrics.rb +14 -0
- data/lib/lydown/rendering/movement.rb +19 -0
- data/lib/lydown/rendering/music.rb +362 -0
- data/lib/lydown/rendering/settings.rb +107 -0
- data/lib/lydown/rendering/staff.rb +83 -0
- data/lib/lydown/rendering.rb +45 -0
- data/lib/lydown/templates/lilypond_doc.erb +15 -0
- data/lib/lydown/templates/movement.erb +48 -0
- data/lib/lydown/templates/part.erb +55 -0
- data/lib/lydown/templates.rb +22 -0
- data/lib/lydown/version.rb +3 -0
- data/lib/lydown/work.rb +192 -0
- data/lib/lydown.rb +11 -0
- metadata +84 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
grammar Lydown
|
2
|
+
include Lydown::Parsing
|
3
|
+
|
4
|
+
rule lines
|
5
|
+
line ([\n] line)* <Root>
|
6
|
+
end
|
7
|
+
rule stream_switch
|
8
|
+
music_stream / lyrics_stream / lyrics2_stream
|
9
|
+
end
|
10
|
+
rule music_stream
|
11
|
+
'=music' white_space? [\n] music ([\n] !stream_breaker music)*
|
12
|
+
end
|
13
|
+
rule lyrics_stream
|
14
|
+
'=lyrics' white_space? [\n] lyrics_content ([\n] !stream_breaker lyrics_content)*
|
15
|
+
end
|
16
|
+
rule lyrics2_stream
|
17
|
+
'=lyrics2' white_space? [\n] lyrics2_content ([\n] !stream_breaker lyrics2_content)*
|
18
|
+
end
|
19
|
+
rule stream_breaker
|
20
|
+
stream_switch / stream_breaking_setting
|
21
|
+
end
|
22
|
+
rule stream_breaking_setting
|
23
|
+
'-' white_space* ('part:' / 'movement:') setting_value comment?
|
24
|
+
end
|
25
|
+
rule line
|
26
|
+
stream_switch / comment / setting / lyrics / music
|
27
|
+
end
|
28
|
+
rule comment
|
29
|
+
'//' comment_content
|
30
|
+
end
|
31
|
+
rule comment_content
|
32
|
+
[^\n]* <CommentContent>
|
33
|
+
end
|
34
|
+
rule setting
|
35
|
+
white_space? '-' white_space* setting_key ':' setting_value comment? <Setting>
|
36
|
+
end
|
37
|
+
rule setting_key
|
38
|
+
[a-z0-9_]+ <Setting::Key>
|
39
|
+
end
|
40
|
+
rule setting_value
|
41
|
+
(!"\n" !"//" .)* <Setting::Value>
|
42
|
+
end
|
43
|
+
rule music
|
44
|
+
white_space? event* comment?
|
45
|
+
end
|
46
|
+
rule white_space
|
47
|
+
[ \t]+
|
48
|
+
end
|
49
|
+
rule event
|
50
|
+
(barline / duration / note / standalone_figures / rest / silence / phrasing / tie) white_space*
|
51
|
+
end
|
52
|
+
rule barline
|
53
|
+
('?|' / ':|][|:' / '[|:' / ':|]' / [\|\.\:]+) <Barline>
|
54
|
+
# ('|' / '.' / '||' / '.|' / '..' / '|.|' / '|.' /
|
55
|
+
# '.|') <Barline>
|
56
|
+
end
|
57
|
+
rule duration
|
58
|
+
duration_value / duration_macro
|
59
|
+
end
|
60
|
+
rule duration_value
|
61
|
+
number dots* multiplier? <DurationValue>
|
62
|
+
end
|
63
|
+
rule number
|
64
|
+
[0-9]+
|
65
|
+
end
|
66
|
+
rule dots
|
67
|
+
'.'+
|
68
|
+
end
|
69
|
+
rule multiplier
|
70
|
+
'*' number ('/' number)*
|
71
|
+
end
|
72
|
+
rule duration_macro
|
73
|
+
'{' duration_macro__expression '}'
|
74
|
+
end
|
75
|
+
rule duration_macro__expression
|
76
|
+
(macro_name / macro_event*) <DurationMacroExpression>
|
77
|
+
end
|
78
|
+
rule macro_event
|
79
|
+
(duration / note_placeholder / rest / silence / phrasing / tie) white_space*
|
80
|
+
end
|
81
|
+
rule macro_name
|
82
|
+
[a-zA-Z_] [a-zA-Z0-9_]*
|
83
|
+
end
|
84
|
+
rule note_placeholder
|
85
|
+
[_@] expression*
|
86
|
+
end
|
87
|
+
rule note
|
88
|
+
note_head octave* accidental_flag? figures? expression* <Note>
|
89
|
+
end
|
90
|
+
rule expression
|
91
|
+
(expression_shorthand / expression_longhand) <Note::Expression>
|
92
|
+
end
|
93
|
+
|
94
|
+
rule expression_shorthand
|
95
|
+
[\_\.`]
|
96
|
+
end
|
97
|
+
rule expression_longhand
|
98
|
+
'\\' [^\s\n]+
|
99
|
+
end
|
100
|
+
rule figures # bass figures
|
101
|
+
'<' figures_component? (white_space? figures_component)* '>'
|
102
|
+
end
|
103
|
+
rule figures_component
|
104
|
+
('_' / [#bh] / ([1-9] [\+\-\!\\'`]*)) <FiguresComponent>
|
105
|
+
end
|
106
|
+
rule standalone_figures
|
107
|
+
duration_value? figures <StandAloneFigures>
|
108
|
+
end
|
109
|
+
rule rest
|
110
|
+
[rR] multiplier* <Rest>
|
111
|
+
end
|
112
|
+
rule silence
|
113
|
+
[s] multiplier* <Silence>
|
114
|
+
end
|
115
|
+
rule note_head
|
116
|
+
[a-g] accidental* <Note::Head>
|
117
|
+
end
|
118
|
+
rule accidental
|
119
|
+
[\+\-]+
|
120
|
+
end
|
121
|
+
rule octave
|
122
|
+
[\,']+ <Note::Octave>
|
123
|
+
end
|
124
|
+
rule accidental_flag
|
125
|
+
[\!\?] <Note::AccidentalFlag>
|
126
|
+
end
|
127
|
+
rule phrasing
|
128
|
+
beam_open / beam_close / slur_open / slur_close
|
129
|
+
end
|
130
|
+
rule beam_open
|
131
|
+
[\[] white_space* <Phrasing::BeamOpen>
|
132
|
+
end
|
133
|
+
rule beam_close
|
134
|
+
white_space* [\]] white_space* <Phrasing::BeamClose>
|
135
|
+
end
|
136
|
+
rule slur_open
|
137
|
+
[\(] white_space* <Phrasing::SlurOpen>
|
138
|
+
end
|
139
|
+
rule slur_close
|
140
|
+
white_space* [\)] white_space* <Phrasing::SlurClose>
|
141
|
+
end
|
142
|
+
rule tie
|
143
|
+
regular_tie / short_tie
|
144
|
+
end
|
145
|
+
rule regular_tie
|
146
|
+
'~' <Tie>
|
147
|
+
end
|
148
|
+
rule short_tie
|
149
|
+
'&' <ShortTie>
|
150
|
+
end
|
151
|
+
rule lyrics
|
152
|
+
'>' white_space* lyrics_content
|
153
|
+
end
|
154
|
+
rule lyrics_content
|
155
|
+
(!"\n" !"//" .)* <Lyrics>
|
156
|
+
end
|
157
|
+
rule lyrics2_content
|
158
|
+
(!"\n" !"//" .)* <Lyrics2>
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Lydown::Parsing
|
2
|
+
module Root
|
3
|
+
def _to_stream(element, stream)
|
4
|
+
if element.elements
|
5
|
+
element.elements.each do |e|
|
6
|
+
e.respond_to?(:to_stream) ? e.to_stream(stream) : _to_stream(e, stream)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
stream
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_stream(stream = [])
|
13
|
+
_to_stream(self, stream)
|
14
|
+
stream
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module CommentContent
|
19
|
+
def to_stream(stream)
|
20
|
+
stream << {type: :comment, content: text_value.strip}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Setting
|
25
|
+
include Root
|
26
|
+
|
27
|
+
def to_stream(stream)
|
28
|
+
level = (text_value =~ /^([\s]+)/) ? ($1.length / 2) : 0
|
29
|
+
@setting = {type: :setting, level: level}
|
30
|
+
_to_stream(self, stream)
|
31
|
+
end
|
32
|
+
|
33
|
+
def setting
|
34
|
+
@setting
|
35
|
+
end
|
36
|
+
|
37
|
+
def emit_setting(stream)
|
38
|
+
stream << @setting
|
39
|
+
end
|
40
|
+
|
41
|
+
module Key
|
42
|
+
def to_stream(stream)
|
43
|
+
parent.setting[:key] = text_value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module Value
|
48
|
+
def to_stream(stream)
|
49
|
+
parent.setting[:value] = text_value.strip
|
50
|
+
parent.emit_setting(stream)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module DurationValue
|
56
|
+
def to_stream(stream)
|
57
|
+
stream << {type: :duration, value: text_value}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module Note
|
62
|
+
include Root
|
63
|
+
|
64
|
+
def to_stream(stream)
|
65
|
+
note = {type: :note, raw: text_value}
|
66
|
+
_to_stream(self, note)
|
67
|
+
stream << note
|
68
|
+
end
|
69
|
+
|
70
|
+
module Head
|
71
|
+
def to_stream(note)
|
72
|
+
note[:head] = text_value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module Octave
|
77
|
+
def to_stream(note)
|
78
|
+
note[:octave] = text_value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module AccidentalFlag
|
83
|
+
def to_stream(note)
|
84
|
+
note[:accidental_flag] = text_value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module Expression
|
89
|
+
def to_stream(note)
|
90
|
+
note[:expressions] ||= []
|
91
|
+
note[:expressions] << text_value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
module FiguresComponent
|
97
|
+
def to_stream(note)
|
98
|
+
note[:figures] ||= []
|
99
|
+
note[:figures] << text_value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module StandAloneFigures
|
104
|
+
include Root
|
105
|
+
|
106
|
+
def to_stream(stream)
|
107
|
+
note = {type: :stand_alone_figures}
|
108
|
+
_to_stream(self, note)
|
109
|
+
stream << note
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module Phrasing
|
114
|
+
module BeamOpen
|
115
|
+
def to_stream(stream)
|
116
|
+
stream << {type: :beam_open}
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
module BeamClose
|
121
|
+
def to_stream(stream)
|
122
|
+
stream << {type: :beam_close}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
module SlurOpen
|
127
|
+
def to_stream(stream)
|
128
|
+
stream << {type: :slur_open}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module SlurClose
|
133
|
+
def to_stream(stream)
|
134
|
+
stream << {type: :slur_close}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module Tie
|
140
|
+
def to_stream(stream)
|
141
|
+
stream << {type: :tie}
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module ShortTie
|
146
|
+
def to_stream(stream)
|
147
|
+
stream << {type: :short_tie}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
module Rest
|
152
|
+
def to_stream(stream)
|
153
|
+
rest = {type: :rest, raw: text_value, head: text_value[0]}
|
154
|
+
if text_value =~ /^R(\*([0-9]+))?$/
|
155
|
+
rest[:multiplier] = $2 || '1'
|
156
|
+
end
|
157
|
+
|
158
|
+
stream << rest
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
module Silence
|
163
|
+
def to_stream(stream)
|
164
|
+
stream << {type: :silence, raw: text_value, head: text_value[0]}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
module DurationMacroExpression
|
169
|
+
def to_stream(stream)
|
170
|
+
stream << {type: :duration_macro, macro: text_value}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
module Lyrics
|
175
|
+
def to_stream(stream)
|
176
|
+
stream << {type: :lyrics, content: text_value}
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
module Lyrics2
|
181
|
+
def to_stream(stream)
|
182
|
+
stream << {type: :lyrics, stream: :lyrics2, content: text_value}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
module Barline
|
187
|
+
def to_stream(stream)
|
188
|
+
stream << {type: :barline, barline: text_value}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'polyglot'
|
2
|
+
require 'treetop'
|
3
|
+
|
4
|
+
require 'lydown/parsing/nodes'
|
5
|
+
require 'lydown/parsing/lydown.treetop'
|
6
|
+
|
7
|
+
# Treetop.load 'lydown/parsing/lydown'
|
8
|
+
|
9
|
+
class LydownParser
|
10
|
+
def self.parse(source, opts = {})
|
11
|
+
parser = self.new
|
12
|
+
ast = parser.parse(source)
|
13
|
+
unless ast
|
14
|
+
error_msg = format_parser_error(source, parser, opts)
|
15
|
+
STDERR.puts error_msg
|
16
|
+
raise LydownError, error_msg
|
17
|
+
else
|
18
|
+
ast.to_stream
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.format_parser_error(source, parser, opts)
|
23
|
+
msg = opts[:source_filename] ? "#{opts[:source_filename]}: " : ""
|
24
|
+
if opts[:nice_error]
|
25
|
+
msg << "Unexpected character at line #{parser.failure_line} column #{parser.failure_column}:\n"
|
26
|
+
else
|
27
|
+
msg << "#{parser.failure_reason}:\n"
|
28
|
+
end
|
29
|
+
msg << " #{source.lines[parser.failure_line - 1]} #{' ' * parser.failure_column}^"
|
30
|
+
|
31
|
+
msg
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Lydown::Rendering
|
2
|
+
class Base
|
3
|
+
def initialize(event, work, stream, idx)
|
4
|
+
@event = event
|
5
|
+
@work = work
|
6
|
+
@stream = stream
|
7
|
+
@idx = idx
|
8
|
+
end
|
9
|
+
|
10
|
+
def translate
|
11
|
+
# do nothing by default
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_event
|
15
|
+
idx = @idx + 1
|
16
|
+
while idx < @stream.size
|
17
|
+
e = @stream[idx]
|
18
|
+
return e if e && e[:type] != :comment
|
19
|
+
idx += 1
|
20
|
+
end
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
ly_dir: ./_ly
|
2
|
+
pdf_dir: ./_pdf
|
3
|
+
midi_dir: ./_midi
|
4
|
+
lilypond_cmd: lilypond
|
5
|
+
parts:
|
6
|
+
soprano:
|
7
|
+
clef: treble
|
8
|
+
beaming: manual
|
9
|
+
midi_instrument: voice oohs
|
10
|
+
soprano1:
|
11
|
+
clef: treble
|
12
|
+
beaming: manual
|
13
|
+
midi_instrument: voice oohs
|
14
|
+
soprano2:
|
15
|
+
clef: treble
|
16
|
+
beaming: manual
|
17
|
+
midi_instrument: voice oohs
|
18
|
+
alto:
|
19
|
+
clef: treble
|
20
|
+
beaming: manual
|
21
|
+
midi_instrument: voice oohs
|
22
|
+
alto1:
|
23
|
+
clef: treble
|
24
|
+
beaming: manual
|
25
|
+
midi_instrument: voice oohs
|
26
|
+
alto2:
|
27
|
+
clef: treble
|
28
|
+
beaming: manual
|
29
|
+
midi_instrument: voice oohs
|
30
|
+
tenor:
|
31
|
+
clef: treble_8
|
32
|
+
beaming: manual
|
33
|
+
midi_instrument: voice oohs
|
34
|
+
tenor1:
|
35
|
+
clef: treble_8
|
36
|
+
beaming: manual
|
37
|
+
midi_instrument: voice oohs
|
38
|
+
tenor2:
|
39
|
+
clef: treble_8
|
40
|
+
beaming: manual
|
41
|
+
midi_instrument: voice oohs
|
42
|
+
tenore:
|
43
|
+
clef: treble_8
|
44
|
+
beaming: manual
|
45
|
+
midi_instrument: voice oohs
|
46
|
+
tenore1:
|
47
|
+
clef: treble_8
|
48
|
+
beaming: manual
|
49
|
+
midi_instrument: voice oohs
|
50
|
+
tenore2:
|
51
|
+
clef: treble_8
|
52
|
+
beaming: manual
|
53
|
+
midi_instrument: voice oohs
|
54
|
+
bass:
|
55
|
+
clef: bass
|
56
|
+
beaming: manual
|
57
|
+
midi_instrument: voice oohs
|
58
|
+
bass1:
|
59
|
+
clef: bass
|
60
|
+
beaming: manual
|
61
|
+
midi_instrument: voice oohs
|
62
|
+
bass2:
|
63
|
+
clef: bass
|
64
|
+
beaming: manual
|
65
|
+
midi_instrument: voice oohs
|
66
|
+
basso:
|
67
|
+
clef: bass
|
68
|
+
beaming: manual
|
69
|
+
midi_instrument: voice oohs
|
70
|
+
basso1:
|
71
|
+
clef: bass
|
72
|
+
beaming: manual
|
73
|
+
midi_instrument: voice oohs
|
74
|
+
basso2:
|
75
|
+
clef: bass
|
76
|
+
beaming: manual
|
77
|
+
midi_instrument: voice oohs
|
78
|
+
violin:
|
79
|
+
clef: treble
|
80
|
+
midi_instrument: violin
|
81
|
+
violon:
|
82
|
+
clef: treble
|
83
|
+
midi_instrument: violin
|
84
|
+
violino:
|
85
|
+
clef: treble
|
86
|
+
midi_instrument: violin
|
87
|
+
violin1:
|
88
|
+
clef: treble
|
89
|
+
midi_instrument: violin
|
90
|
+
violin2:
|
91
|
+
clef: treble
|
92
|
+
midi_instrument: violin
|
93
|
+
violon1:
|
94
|
+
clef: treble
|
95
|
+
midi_instrument: violin
|
96
|
+
violon2:
|
97
|
+
clef: treble
|
98
|
+
midi_instrument: violin
|
99
|
+
violino1:
|
100
|
+
clef: treble
|
101
|
+
midi_instrument: violin
|
102
|
+
violino2:
|
103
|
+
clef: treble
|
104
|
+
midi_instrument: violin
|
105
|
+
violini:
|
106
|
+
clef: treble
|
107
|
+
midi_instrument: violin
|
108
|
+
viola:
|
109
|
+
clef: alto
|
110
|
+
midi_instrument: viola
|
111
|
+
viola1:
|
112
|
+
clef: alto
|
113
|
+
midi_instrument: viola
|
114
|
+
viola2:
|
115
|
+
clef: alto
|
116
|
+
midi_instrument: viola
|
117
|
+
viola-da-gamba:
|
118
|
+
clef: bass
|
119
|
+
midi_instrument: viola
|
120
|
+
viola-da-gamba1:
|
121
|
+
clef: bass
|
122
|
+
midi_instrument: viola
|
123
|
+
viola-da-gamba2:
|
124
|
+
clef: bass
|
125
|
+
midi_instrument: viola
|
126
|
+
gamba1:
|
127
|
+
clef: alto
|
128
|
+
midi_instrument: viola
|
129
|
+
gamba2:
|
130
|
+
clef: alto
|
131
|
+
midi_instrument: viola
|
132
|
+
fagott:
|
133
|
+
clef: bass
|
134
|
+
midi_instrument: bassoon
|
135
|
+
fagotto:
|
136
|
+
clef: bass
|
137
|
+
midi_instrument: bassoon
|
138
|
+
violoncello:
|
139
|
+
clef: bass
|
140
|
+
midi_instrument: cello
|
141
|
+
cello:
|
142
|
+
clef: bass
|
143
|
+
midi_instrument: cello
|
144
|
+
continuo:
|
145
|
+
clef: bass
|
146
|
+
midi_instrument: cello
|
147
|
+
embed_figures: true
|
148
|
+
organo:
|
149
|
+
clef: bass
|
150
|
+
midi_instrument: church organ
|
151
|
+
oboe:
|
152
|
+
clef: treble
|
153
|
+
midi_instrument: oboe
|
154
|
+
oboe1:
|
155
|
+
clef: treble
|
156
|
+
midi_instrument: oboe
|
157
|
+
oboe2:
|
158
|
+
clef: treble
|
159
|
+
midi_instrument: oboe
|
160
|
+
flauto:
|
161
|
+
clef: treble
|
162
|
+
midi_instrument: recorder
|
163
|
+
flauto1:
|
164
|
+
clef: treble
|
165
|
+
midi_instrument: recorder
|
166
|
+
flauto2:
|
167
|
+
clef: treble
|
168
|
+
midi_instrument: recorder
|
169
|
+
flute:
|
170
|
+
midi_instrument: flute
|
171
|
+
flute1:
|
172
|
+
midi_instrument: flute
|
173
|
+
flute2:
|
174
|
+
midi_instrument: flute
|
175
|
+
score:
|
176
|
+
order:
|
177
|
+
- [flauto1, flauto2, flauto3, flute1, flute2, flute3]
|
178
|
+
- [oboe1, oboe2, oboe3]
|
179
|
+
- [violino1, violino2, violino3, violin1, violin2, violin3]
|
180
|
+
- viola
|
181
|
+
- [gamba1, gamba2]
|
182
|
+
- [soprano, alto, tenore, basso]
|
183
|
+
- [soprano1, alto1, tenore1, basso1]
|
184
|
+
- [soprano2, alto2, tenore2, basso2]
|
185
|
+
- continuo
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Lydown::Rendering
|
2
|
+
module Figures
|
3
|
+
def add_figures(figures, value)
|
4
|
+
if @work['process/running_values']
|
5
|
+
@work['process/running_values'].each do |v|
|
6
|
+
silence = "s"
|
7
|
+
if v != @work['process/last_figures_value']
|
8
|
+
silence << v
|
9
|
+
@work['process/last_figures_value'] = v
|
10
|
+
end
|
11
|
+
@work.emit(:figures, "#{silence} ")
|
12
|
+
end
|
13
|
+
@work['process/running_values'] = []
|
14
|
+
end
|
15
|
+
|
16
|
+
figures = lilypond_figures(figures)
|
17
|
+
if value != @work['process/last_figures_value']
|
18
|
+
figures << value
|
19
|
+
@work['process/last_figures_value'] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
@work.emit(:figures, "#{figures} ")
|
23
|
+
@work.emit(:figures, EXTENDERS_ON) if @event[:figure_extenders_on]
|
24
|
+
@work.emit(:figures, EXTENDERS_OFF) if @event[:figure_extenders_off]
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_stand_alone_figures(figures)
|
28
|
+
if @work['process/running_values']
|
29
|
+
# for stand alone figures, we regard the stand alone figure as being
|
30
|
+
# aligned to the last note. Therefore we pop its value from
|
31
|
+
# running_values array.
|
32
|
+
@work['process/running_values'].pop
|
33
|
+
end
|
34
|
+
value = @work['process/figures_duration_value'] || @work['process/last_value']
|
35
|
+
add_figures(figures, value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def lilypond_figures(figures)
|
39
|
+
if figures
|
40
|
+
check_tenues(figures)
|
41
|
+
"<#{translate_figures(figures)}>"
|
42
|
+
else
|
43
|
+
"s"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_tenues(figures)
|
48
|
+
next_event = next_figures_event
|
49
|
+
unless next_event
|
50
|
+
# if next figures event is not found, check if there is a tenue, and
|
51
|
+
# add extenders off flag
|
52
|
+
@event[:figure_extenders_off] = true if @event[:tenue]
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
if next_event[:figures]
|
57
|
+
next_event[:tenue] = next_event[:figures].include?('_')
|
58
|
+
if next_event[:tenue] && !@event[:tenue]
|
59
|
+
@event[:figure_extenders_on] = true
|
60
|
+
elsif !next_event[:tenue] && @event[:tenue]
|
61
|
+
@event[:figure_extenders_off] = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# transform underscores into figure components
|
65
|
+
next_event[:figures].each_with_index do |component, idx|
|
66
|
+
next_event[:figures][idx] = @event[:figures][idx] if component == '_'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def translate_figures(figures)
|
72
|
+
figures.map {|n| n.gsub(ALTERATION_RE) {|a| ALTERATION[a]}}.join(' ')
|
73
|
+
end
|
74
|
+
|
75
|
+
ALTERATION_RE = /[#bh`']/
|
76
|
+
ALTERATION = {
|
77
|
+
'#' => '_+',
|
78
|
+
'b' => '_-',
|
79
|
+
'h' => '_!',
|
80
|
+
'`' => '\\\\',
|
81
|
+
"'" => "/"
|
82
|
+
}
|
83
|
+
EXTENDERS_ON = "\\bassFigureExtendersOn "
|
84
|
+
EXTENDERS_OFF = "\\bassFigureExtendersOff "
|
85
|
+
|
86
|
+
HIDDEN_FORMAT = "\\once \\override BassFigure #'implicit = ##t"
|
87
|
+
|
88
|
+
def next_figures_event
|
89
|
+
idx = @idx + 1
|
90
|
+
while idx < @stream.size
|
91
|
+
event = @stream[idx]
|
92
|
+
case event[:type]
|
93
|
+
when :setting
|
94
|
+
if ['part', 'movement'].include? event[:key]
|
95
|
+
return nil
|
96
|
+
end
|
97
|
+
when :note
|
98
|
+
return event if event[:figures]
|
99
|
+
when :stand_alone_figures
|
100
|
+
return event
|
101
|
+
end
|
102
|
+
idx += 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Lydown::Rendering
|
2
|
+
class Lyrics < Base
|
3
|
+
def translate
|
4
|
+
value = lilypond_lyrics(@event[:content])
|
5
|
+
@work.emit(@event[:stream] || :lyrics, value, ' ')
|
6
|
+
end
|
7
|
+
|
8
|
+
def lilypond_lyrics(lyrics)
|
9
|
+
lyrics.
|
10
|
+
gsub(/_+/) {|m| " __ #{'_ ' * (m.size - 1)}"}.
|
11
|
+
gsub(/\-+/) {|m| " -- #{'_ ' * (m.size - 1)}"}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|