brevity 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +27 -0
- data/Rakefile +67 -0
- data/bin/debrief +56 -0
- data/brevity.gemspec +28 -0
- data/examples/alley_cat.br +50 -0
- data/examples/hip.br +15 -0
- data/examples/missed_connection.br +6 -0
- data/examples/song1.br +11 -0
- data/examples/song2.br +10 -0
- data/examples/twinkle.br +18 -0
- data/lib/brevity/commands/constants.rb +18 -0
- data/lib/brevity/commands/expr.rb +17 -0
- data/lib/brevity/commands/meter.rb +20 -0
- data/lib/brevity/commands/part.rb +47 -0
- data/lib/brevity/commands/tempo.rb +13 -0
- data/lib/brevity/itemization.rb +73 -0
- data/lib/brevity/parsing/expression/dynamic.rb +280 -0
- data/lib/brevity/parsing/expression/dynamic.treetop +41 -0
- data/lib/brevity/parsing/expression/dynamic_nodes.rb +55 -0
- data/lib/brevity/parsing/expression/expression.rb +429 -0
- data/lib/brevity/parsing/expression/expression.treetop +39 -0
- data/lib/brevity/parsing/expression/expression_nodes.rb +26 -0
- data/lib/brevity/parsing/expression/gradual.rb +44 -0
- data/lib/brevity/parsing/expression/gradual.treetop +9 -0
- data/lib/brevity/parsing/expression/gradual_node.rb +11 -0
- data/lib/brevity/parsing/expression/label.rb +75 -0
- data/lib/brevity/parsing/expression/label.treetop +9 -0
- data/lib/brevity/parsing/expression/label_node.rb +15 -0
- data/lib/brevity/parsing/expression/sequence.rb +130 -0
- data/lib/brevity/parsing/expression/sequence.treetop +12 -0
- data/lib/brevity/parsing/expression/sequence_node.rb +14 -0
- data/lib/brevity/parsing/file/command.rb +216 -0
- data/lib/brevity/parsing/file/command.treetop +17 -0
- data/lib/brevity/parsing/file/command_node.rb +11 -0
- data/lib/brevity/parsing/file/comment.rb +178 -0
- data/lib/brevity/parsing/file/comment.treetop +21 -0
- data/lib/brevity/parsing/file/comment_node.rb +3 -0
- data/lib/brevity/parsing/file/file.rb +152 -0
- data/lib/brevity/parsing/file/file.treetop +16 -0
- data/lib/brevity/parsing/file/file_node.rb +7 -0
- data/lib/brevity/parsing/file/path.rb +235 -0
- data/lib/brevity/parsing/file/path.treetop +12 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier.rb +65 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier_node.rb +8 -0
- data/lib/brevity/parsing/modifiers/modifier.rb +64 -0
- data/lib/brevity/parsing/modifiers/modifier.treetop +13 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier.rb +69 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier_node.rb +21 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier.rb +69 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier_node.rb +13 -0
- data/lib/brevity/parsing/note/accent.rb +44 -0
- data/lib/brevity/parsing/note/accent.treetop +9 -0
- data/lib/brevity/parsing/note/duration.rb +203 -0
- data/lib/brevity/parsing/note/duration.treetop +23 -0
- data/lib/brevity/parsing/note/duration_nodes.rb +19 -0
- data/lib/brevity/parsing/note/link.rb +69 -0
- data/lib/brevity/parsing/note/link.treetop +11 -0
- data/lib/brevity/parsing/note/link_node.rb +19 -0
- data/lib/brevity/parsing/note/note.rb +300 -0
- data/lib/brevity/parsing/note/note.treetop +30 -0
- data/lib/brevity/parsing/note/note_nodes.rb +77 -0
- data/lib/brevity/parsing/note/pitch.rb +81 -0
- data/lib/brevity/parsing/note/pitch.treetop +9 -0
- data/lib/brevity/parsing/note/pitch_node.rb +50 -0
- data/lib/brevity/parsing/numbers/nonnegative_integer.rb +53 -0
- data/lib/brevity/parsing/numbers/nonnegative_integer.treetop +9 -0
- data/lib/brevity/parsing/numbers/positive_integer.rb +91 -0
- data/lib/brevity/parsing/numbers/positive_integer.treetop +15 -0
- data/lib/brevity/read_file.rb +18 -0
- data/lib/brevity/score_maker.rb +64 -0
- data/lib/brevity/version.rb +4 -0
- data/lib/brevity.rb +53 -0
- data/manuals/brevity.pdf +0 -0
- data/manuals/brevity.tex +273 -0
- data/spec/brevity_spec.rb +8 -0
- data/spec/commands/expr_spec.rb +15 -0
- data/spec/commands/meter_spec.rb +21 -0
- data/spec/commands/part_spec.rb +16 -0
- data/spec/commands/tempo_spec.rb +20 -0
- data/spec/itemization_spec.rb +46 -0
- data/spec/parsing/expression/dynamic_nodes_spec.rb +32 -0
- data/spec/parsing/expression/dynamic_spec.rb +23 -0
- data/spec/parsing/expression/expression_nodes_spec.rb +87 -0
- data/spec/parsing/expression/expression_spec.rb +85 -0
- data/spec/parsing/expression/gradual_spec.rb +10 -0
- data/spec/parsing/expression/label_node_spec.rb +13 -0
- data/spec/parsing/expression/label_spec.rb +35 -0
- data/spec/parsing/file/command_node_spec.rb +29 -0
- data/spec/parsing/file/command_spec.rb +18 -0
- data/spec/parsing/file/comment_spec.rb +14 -0
- data/spec/parsing/file/file_node_spec.rb +19 -0
- data/spec/parsing/file/file_spec.rb +30 -0
- data/spec/parsing/modifiers/modifier_nodes_spec.rb +25 -0
- data/spec/parsing/modifiers/modifier_parsers_spec.rb +20 -0
- data/spec/parsing/note/accent_spec.rb +27 -0
- data/spec/parsing/note/duration_nodes_spec.rb +79 -0
- data/spec/parsing/note/duration_spec.rb +69 -0
- data/spec/parsing/note/link_node_spec.rb +30 -0
- data/spec/parsing/note/link_spec.rb +23 -0
- data/spec/parsing/note/note_nodes_spec.rb +82 -0
- data/spec/parsing/note/note_spec.rb +188 -0
- data/spec/parsing/note/pitch_node_spec.rb +48 -0
- data/spec/parsing/note/pitch_spec.rb +23 -0
- data/spec/parsing/numbers/nonnegative_integer_spec.rb +11 -0
- data/spec/parsing/numbers/positive_integer_spec.rb +17 -0
- data/spec/spec_helper.rb +112 -0
- metadata +293 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe RestNoteNode do
|
4
|
+
{
|
5
|
+
'/2' => Note.new(Rational(1,2)),
|
6
|
+
'4/2' => Note.new(Rational(4,2)),
|
7
|
+
'28' => Note.new(Rational(28,1)),
|
8
|
+
'56/33' => Note.new(Rational(56,33)),
|
9
|
+
}.each do |str,tgt|
|
10
|
+
res = NOTE_PARSER.parse(str)
|
11
|
+
context str do
|
12
|
+
it 'should parse as RestNoteNode' do
|
13
|
+
res.should be_a RestNoteNode
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#to_note' do
|
17
|
+
n = res.to_note
|
18
|
+
it 'should produce a Note' do
|
19
|
+
n.should be_a Note
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should produce value matching input str' do
|
23
|
+
n.should eq tgt
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe MonophonicNoteNode do
|
31
|
+
{
|
32
|
+
'/2C2=C2' => Note.new(Rational(1,2),[C2],links:{C2=>Link::Slur.new(C2)}),
|
33
|
+
'4/2D#6^' => Note.new(Rational(4,2),[Eb6],accent:Accent::Martellato.new),
|
34
|
+
'28Eb7>' => Note.new(Rational(28,1),[Eb7],accent:Accent::Marcato.new),
|
35
|
+
'56/33B1.' => Note.new(Rational(56,33),[B1],accent:Accent::Staccato.new),
|
36
|
+
}.each do |str,tgt|
|
37
|
+
res = NOTE_PARSER.parse(str)
|
38
|
+
context str do
|
39
|
+
it 'should parse as MonophonicNoteNode' do
|
40
|
+
res.should be_a MonophonicNoteNode
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#to_note' do
|
44
|
+
n = res.to_note
|
45
|
+
it 'should produce a Note' do
|
46
|
+
n.should be_a Note
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should produce value matching input str' do
|
50
|
+
n.should eq tgt
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe PolyphonicNoteNode do
|
58
|
+
{
|
59
|
+
'/2C2,D2,E2-F2' => Note.new(Rational(1,2),[C2,D2,E2],links:{E2=>Link::Legato.new(F2)}),
|
60
|
+
'4/2D#6,G4' => Note.new(Rational(4,2),[Eb6,G4]),
|
61
|
+
'28Eb7,D7,G7_' => Note.new(Rational(28,1),[Eb7,D7,G7],accent:Accent::Tenuto.new),
|
62
|
+
'56/33B1,B2,B3,B4,B5' => Note.new(Rational(56,33),[B1,B2,B3,B4,B5]),
|
63
|
+
}.each do |str,tgt|
|
64
|
+
res = NOTE_PARSER.parse(str)
|
65
|
+
context str do
|
66
|
+
it 'should parse as PolyphonicNoteNode' do
|
67
|
+
res.should be_a PolyphonicNoteNode
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#to_note' do
|
71
|
+
n = res.to_note
|
72
|
+
it 'should produce a Note' do
|
73
|
+
n.should be_a Note
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should produce value matching input str' do
|
77
|
+
n.should eq tgt
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe NoteParser do
|
4
|
+
before :all do
|
5
|
+
@parser = NoteParser.new
|
6
|
+
@valid = {
|
7
|
+
:numbers => [1,5,50,3999,01,0010,0000005050],
|
8
|
+
:links => ["=","-","~","/"],
|
9
|
+
:accents => [".","'",">","^","_",""],
|
10
|
+
:pitch_classes => ["A","B","C","D","E","F","G"],
|
11
|
+
:accidentals => ["\#","b",""],
|
12
|
+
:octaves => [0,1,2,3,4,5,6,7,8,9],
|
13
|
+
}
|
14
|
+
|
15
|
+
@invalid = {
|
16
|
+
:numbers => [0,00],
|
17
|
+
:links => ["{",";"],
|
18
|
+
:accents => ["*","&"],
|
19
|
+
:pitch_classes => ["H","Z"],
|
20
|
+
:accidentals => ["$"],
|
21
|
+
:octaves => [-1,10],
|
22
|
+
}
|
23
|
+
|
24
|
+
@valid[:pitches] = []
|
25
|
+
@valid[:pitch_classes].each do |pc|
|
26
|
+
@valid[:accidentals].each do |a|
|
27
|
+
@valid[:octaves].each do |o|
|
28
|
+
@valid[:pitches].push "#{pc}#{a}#{o}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@invalid[:pitches] = []
|
34
|
+
@invalid[:pitch_classes].each do |pc|
|
35
|
+
@valid[:accidentals].each do |a|
|
36
|
+
@valid[:octaves].each do |o|
|
37
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@valid[:pitch_classes].each do |pc|
|
42
|
+
@invalid[:accidentals].each do |a|
|
43
|
+
@valid[:octaves].each do |o|
|
44
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@valid[:pitch_classes].each do |pc|
|
49
|
+
@valid[:accidentals].each do |a|
|
50
|
+
@invalid[:octaves].each do |o|
|
51
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@invalid[:pitch_classes].each do |pc|
|
56
|
+
@invalid[:accidentals].each do |a|
|
57
|
+
@valid[:octaves].each do |o|
|
58
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@invalid[:pitch_classes].each do |pc|
|
63
|
+
@valid[:accidentals].each do |a|
|
64
|
+
@invalid[:octaves].each do |o|
|
65
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
@valid[:pitch_classes].each do |pc|
|
70
|
+
@invalid[:accidentals].each do |a|
|
71
|
+
@invalid[:octaves].each do |o|
|
72
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
#puts @valid[:pitches]
|
77
|
+
end
|
78
|
+
|
79
|
+
context "note duration only" do
|
80
|
+
it 'should parse' do
|
81
|
+
@parser.parse("1/4").should_not be nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'duration and one pitch' do
|
86
|
+
context 'valid pitch' do
|
87
|
+
context 'without link marker' do
|
88
|
+
it 'should parse' do
|
89
|
+
@valid[:pitches].each do |pitch|
|
90
|
+
str = "1/4#{pitch}"
|
91
|
+
@parser.parse(str).should_not be nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'with link marker' do
|
97
|
+
context 'link marker is valid' do
|
98
|
+
it 'should parse' do
|
99
|
+
@valid[:pitches].each do |pitch|
|
100
|
+
@valid[:links].each do |link|
|
101
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
102
|
+
@parser.parse(str).should_not be nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'link marker is not valid' do
|
109
|
+
it 'should not parse' do
|
110
|
+
@valid[:pitches].each do |pitch|
|
111
|
+
@invalid[:links].each do |link|
|
112
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
113
|
+
@parser.parse(str).should be nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'invalid pitch' do
|
122
|
+
context 'without link marker' do
|
123
|
+
it 'should parse' do
|
124
|
+
@invalid[:pitches].each do |pitch|
|
125
|
+
str = "1/4#{pitch}"
|
126
|
+
@parser.parse(str).should be nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with link marker' do
|
132
|
+
it 'should not parse' do
|
133
|
+
@invalid[:pitches].each do |pitch|
|
134
|
+
@valid[:links].each do |link|
|
135
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
136
|
+
@parser.parse(str).should be nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'duration and multiple pitches' do
|
145
|
+
context 'all valid pitches' do
|
146
|
+
context 'without links' do
|
147
|
+
it 'should parse' do
|
148
|
+
str = "4/" + @valid[:pitches].join(",")
|
149
|
+
@parser.parse(str).should_not be nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with link marker' do
|
154
|
+
context 'link marker is valid' do
|
155
|
+
it 'should parse' do
|
156
|
+
@valid[:links].each do |link|
|
157
|
+
str = "4/" + @valid[:pitches].join("#{link}C4,")
|
158
|
+
@parser.parse(str).should_not be nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'link marker is not valid' do
|
164
|
+
it 'should not parse' do
|
165
|
+
@invalid[:links].each do |link|
|
166
|
+
str = "4/" + @valid[:pitches].join("#{link}C4,")
|
167
|
+
@parser.parse(str).should be nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'one invalid pitch' do
|
175
|
+
it 'should not parse' do
|
176
|
+
str = "4/" + ([@invalid[:pitches][0]] + @valid[:pitches]).join(",")
|
177
|
+
@parser.parse(str).should be nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'all invalid pitches' do
|
182
|
+
it 'should not parse' do
|
183
|
+
str = "4/" + @invalid[:pitches].join(",")
|
184
|
+
@parser.parse(str).should be nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe 'String#to_pitch' do
|
4
|
+
it 'should create a Pitch object that matches the musical note' do
|
5
|
+
{
|
6
|
+
"Ab2" => Pitch.new(octave: 2, semitone: 8),
|
7
|
+
"C0" => Pitch.new(octave: 0, semitone: 0),
|
8
|
+
"db4" => Pitch.new(octave: 4, semitone: 1),
|
9
|
+
"F#12" => Pitch.new(octave: 12, semitone: 6),
|
10
|
+
"E#7" => Pitch.new(octave: 7, semitone: 5),
|
11
|
+
"G9" => Pitch.new(octave: 9, semitone: 7),
|
12
|
+
"Bb10" => Pitch.new(octave: 10, semitone: 10),
|
13
|
+
}.each do |str, expected_pitch|
|
14
|
+
str.to_pitch.should eq(expected_pitch)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe PitchNode do
|
20
|
+
parser = PitchParser.new
|
21
|
+
|
22
|
+
{
|
23
|
+
'C4' => C4,
|
24
|
+
'Db2' => Db2,
|
25
|
+
'C#2' => Db2,
|
26
|
+
'Db2' => Db2,
|
27
|
+
'F7' => F7,
|
28
|
+
'B1' => B1,
|
29
|
+
}.each do |str,tgt|
|
30
|
+
res = parser.parse(str)
|
31
|
+
context str do
|
32
|
+
it 'should parse as PitchNode' do
|
33
|
+
res.should be_a PitchNode
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#to_pitch' do
|
37
|
+
p = res.to_pitch
|
38
|
+
it 'should produce a Pitch object' do
|
39
|
+
p.should be_a Pitch
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should produce pitch matching input str' do
|
43
|
+
p.should eq tgt
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe PitchParser do
|
4
|
+
before :all do
|
5
|
+
@parser = PitchParser.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should parse "C4"' do
|
9
|
+
@parser.parse("C4").should_not be nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should parse "C#9"' do
|
13
|
+
@parser.parse("C#9").should_not be nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should parse "Ab0"' do
|
17
|
+
@parser.parse("Ab0").should_not be nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse "G#2"' do
|
21
|
+
@parser.parse("G#2").should_not be nil
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe NonnegativeIntegerParser do
|
4
|
+
parser = NonnegativeIntegerParser.new
|
5
|
+
|
6
|
+
["1","50","05","502530","0"].each do |str|
|
7
|
+
it "should parse '#{str}'" do
|
8
|
+
parser.parse(str).should_not be nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe PositiveIntegerParser do
|
4
|
+
parser = PositiveIntegerParser.new
|
5
|
+
|
6
|
+
["1","50","05","502530"].each do |str|
|
7
|
+
it "should parse '#{str}'" do
|
8
|
+
parser.parse(str).should_not be nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
["0"].each do |str|
|
13
|
+
it "should not parse '#{str}'" do
|
14
|
+
parser.parse(str).should be nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'brevity'
|
3
|
+
|
4
|
+
include Brevity
|
5
|
+
include Music::Transcription
|
6
|
+
include Pitches
|
7
|
+
|
8
|
+
RSpec::Matchers.define :parse do |str|
|
9
|
+
match do |parser|
|
10
|
+
!parser.parse(str).nil?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec::Matchers.define :parse_as do |str,nodeclass|
|
15
|
+
match do |parser|
|
16
|
+
parser.parse(str).is_a?(nodeclass)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
LABELS = ["riff","GUITAR2","_my_part_"]
|
21
|
+
NOTES = {
|
22
|
+
'/2A7' => Note::Half.new([A7]),
|
23
|
+
'/4A3.' => Note::Quarter.new([A3],accent: Accent::Staccato.new),
|
24
|
+
'/2Bb2' => Note::Half.new([Bb2]),
|
25
|
+
'/2G2,C2-Eb3' => Note::Half.new([G2,C2],links: {C2=>Link::Legato.new(Eb3)}),
|
26
|
+
'1Eb3' => Note::Whole.new([Eb3]),
|
27
|
+
}
|
28
|
+
sequences = {}
|
29
|
+
[2,3].each do |n|
|
30
|
+
NOTES.entries.permutation(n).each do |perm|
|
31
|
+
strs, notes = perm.transpose
|
32
|
+
sequences[strs.join(" ")] = notes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
SEQUENCES = sequences
|
36
|
+
|
37
|
+
MODIFIERS = {
|
38
|
+
:duplicate => {
|
39
|
+
':1' => lambda {|primitives| primitives.clone },
|
40
|
+
':2' => lambda {|primitives| primitives.clone + primitives.clone },
|
41
|
+
':3' => lambda {|primitives| primitives.clone + primitives.clone + primitives.clone }
|
42
|
+
},
|
43
|
+
:stretch => {
|
44
|
+
'*1' => lambda {|primitives| primitives.clone },
|
45
|
+
'*3/2' => lambda do |primitives|
|
46
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch('3/2'.to_r) : p }
|
47
|
+
end,
|
48
|
+
'*/4' => lambda do |primitives|
|
49
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch('1/4'.to_r) : p }
|
50
|
+
end,
|
51
|
+
'=1' => lambda do |primitives|
|
52
|
+
duration = primitives.map do |p|
|
53
|
+
p.respond_to?(:duration) ? p.duration : 0
|
54
|
+
end.inject(0,:+)
|
55
|
+
ratio = 1 / duration
|
56
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
57
|
+
end,
|
58
|
+
'=/2' => lambda do |primitives|
|
59
|
+
duration = primitives.map do |p|
|
60
|
+
p.respond_to?(:duration) ? p.duration : 0
|
61
|
+
end.inject(0,:+)
|
62
|
+
ratio = Rational(1,2) / duration
|
63
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
64
|
+
end,
|
65
|
+
'=2/3' => lambda do |primitives|
|
66
|
+
duration = primitives.map do |p|
|
67
|
+
p.respond_to?(:duration) ? p.duration : 0
|
68
|
+
end.inject(0,:+)
|
69
|
+
ratio = Rational(2,3) / duration
|
70
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
71
|
+
end,
|
72
|
+
},
|
73
|
+
:transpose => {
|
74
|
+
'+0' => lambda {|primitives| primitives.clone },
|
75
|
+
'-0' => lambda {|primitives| primitives.clone },
|
76
|
+
'+4' => lambda do |primitives|
|
77
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(4) : p }
|
78
|
+
end,
|
79
|
+
'-4' => lambda do |primitives|
|
80
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(-4) : p }
|
81
|
+
end,
|
82
|
+
'+10' => lambda do |primitives|
|
83
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(10) : p }
|
84
|
+
end,
|
85
|
+
'-99' => lambda do |primitives|
|
86
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(-99) : p }
|
87
|
+
end
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
EXPR_PARSER = ExpressionParser.new
|
92
|
+
DUR_PARSER = DurationParser.new
|
93
|
+
NOTE_PARSER = NoteParser.new
|
94
|
+
LABEL_PARSER = LabelParser.new
|
95
|
+
COMMENT_PARSER = CommentParser.new
|
96
|
+
COMMAND_PARSER = CommandParser.new
|
97
|
+
FILE_PARSER = FileParser.new
|
98
|
+
|
99
|
+
class CommandTester
|
100
|
+
include Commands
|
101
|
+
|
102
|
+
attr_reader :env
|
103
|
+
def initialize
|
104
|
+
@env = {}
|
105
|
+
@env[ENV_START_TEMPO] = nil
|
106
|
+
@env[ENV_START_METER] = nil
|
107
|
+
@env[ENV_TEMPO_CHANGES] = {}
|
108
|
+
@env[ENV_METER_CHANGES] = {}
|
109
|
+
@env[ENV_EXPRS] = {}
|
110
|
+
@env[ENV_PARTS] = {}
|
111
|
+
end
|
112
|
+
end
|