musicality 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +65 -0
- data/bin/midify +78 -0
- data/examples/hip.rb +32 -0
- data/examples/missed_connection.rb +26 -0
- data/examples/song1.rb +33 -0
- data/examples/song2.rb +32 -0
- data/lib/musicality/errors.rb +9 -0
- data/lib/musicality/notation/conversion/change_conversion.rb +19 -0
- data/lib/musicality/notation/conversion/measure_note_map.rb +40 -0
- data/lib/musicality/notation/conversion/measured_score_conversion.rb +70 -0
- data/lib/musicality/notation/conversion/measured_score_converter.rb +95 -0
- data/lib/musicality/notation/conversion/note_time_converter.rb +68 -0
- data/lib/musicality/notation/conversion/tempo_conversion.rb +25 -0
- data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +47 -0
- data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +64 -0
- data/lib/musicality/notation/model/articulations.rb +13 -0
- data/lib/musicality/notation/model/change.rb +62 -0
- data/lib/musicality/notation/model/dynamics.rb +12 -0
- data/lib/musicality/notation/model/link.rb +73 -0
- data/lib/musicality/notation/model/meter.rb +54 -0
- data/lib/musicality/notation/model/meters.rb +9 -0
- data/lib/musicality/notation/model/note.rb +120 -0
- data/lib/musicality/notation/model/part.rb +54 -0
- data/lib/musicality/notation/model/pitch.rb +163 -0
- data/lib/musicality/notation/model/pitches.rb +21 -0
- data/lib/musicality/notation/model/program.rb +53 -0
- data/lib/musicality/notation/model/score.rb +132 -0
- data/lib/musicality/notation/packing/change_packing.rb +46 -0
- data/lib/musicality/notation/packing/part_packing.rb +31 -0
- data/lib/musicality/notation/packing/program_packing.rb +16 -0
- data/lib/musicality/notation/packing/score_packing.rb +108 -0
- data/lib/musicality/notation/parsing/articulation_parsing.rb +264 -0
- data/lib/musicality/notation/parsing/articulation_parsing.treetop +59 -0
- data/lib/musicality/notation/parsing/convenience_methods.rb +74 -0
- data/lib/musicality/notation/parsing/duration_nodes.rb +21 -0
- data/lib/musicality/notation/parsing/duration_parsing.rb +205 -0
- data/lib/musicality/notation/parsing/duration_parsing.treetop +25 -0
- data/lib/musicality/notation/parsing/link_nodes.rb +35 -0
- data/lib/musicality/notation/parsing/link_parsing.rb +270 -0
- data/lib/musicality/notation/parsing/link_parsing.treetop +33 -0
- data/lib/musicality/notation/parsing/meter_parsing.rb +190 -0
- data/lib/musicality/notation/parsing/meter_parsing.treetop +29 -0
- data/lib/musicality/notation/parsing/note_node.rb +40 -0
- data/lib/musicality/notation/parsing/note_parsing.rb +229 -0
- data/lib/musicality/notation/parsing/note_parsing.treetop +28 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +289 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop +29 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +64 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +17 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +86 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop +20 -0
- data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +503 -0
- data/lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop +33 -0
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +95 -0
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +19 -0
- data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +84 -0
- data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop +19 -0
- data/lib/musicality/notation/parsing/parseable.rb +30 -0
- data/lib/musicality/notation/parsing/pitch_node.rb +23 -0
- data/lib/musicality/notation/parsing/pitch_parsing.rb +448 -0
- data/lib/musicality/notation/parsing/pitch_parsing.treetop +52 -0
- data/lib/musicality/notation/parsing/segment_parsing.rb +141 -0
- data/lib/musicality/notation/parsing/segment_parsing.treetop +23 -0
- data/lib/musicality/notation/util/interpolation.rb +16 -0
- data/lib/musicality/notation/util/piecewise_function.rb +122 -0
- data/lib/musicality/notation/util/value_computer.rb +170 -0
- data/lib/musicality/performance/conversion/glissando_converter.rb +34 -0
- data/lib/musicality/performance/conversion/note_sequence_extractor.rb +98 -0
- data/lib/musicality/performance/conversion/portamento_converter.rb +24 -0
- data/lib/musicality/performance/conversion/score_collator.rb +126 -0
- data/lib/musicality/performance/midi/midi_events.rb +34 -0
- data/lib/musicality/performance/midi/midi_util.rb +31 -0
- data/lib/musicality/performance/midi/part_sequencer.rb +123 -0
- data/lib/musicality/performance/midi/score_sequencer.rb +45 -0
- data/lib/musicality/performance/model/note_attacks.rb +19 -0
- data/lib/musicality/performance/model/note_sequence.rb +111 -0
- data/lib/musicality/performance/util/note_linker.rb +28 -0
- data/lib/musicality/performance/util/optimization.rb +31 -0
- data/lib/musicality/validatable.rb +38 -0
- data/lib/musicality/version.rb +3 -0
- data/lib/musicality.rb +81 -0
- data/musicality.gemspec +30 -0
- data/spec/musicality_spec.rb +7 -0
- data/spec/notation/conversion/change_conversion_spec.rb +40 -0
- data/spec/notation/conversion/measure_note_map_spec.rb +73 -0
- data/spec/notation/conversion/measured_score_conversion_spec.rb +141 -0
- data/spec/notation/conversion/measured_score_converter_spec.rb +329 -0
- data/spec/notation/conversion/note_time_converter_spec.rb +81 -0
- data/spec/notation/conversion/tempo_conversion_spec.rb +40 -0
- data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +71 -0
- data/spec/notation/conversion/unmeasured_score_converter_spec.rb +116 -0
- data/spec/notation/model/change_spec.rb +90 -0
- data/spec/notation/model/link_spec.rb +83 -0
- data/spec/notation/model/meter_spec.rb +97 -0
- data/spec/notation/model/note_spec.rb +183 -0
- data/spec/notation/model/part_spec.rb +69 -0
- data/spec/notation/model/pitch_spec.rb +180 -0
- data/spec/notation/model/program_spec.rb +50 -0
- data/spec/notation/model/score_spec.rb +211 -0
- data/spec/notation/packing/change_packing_spec.rb +153 -0
- data/spec/notation/packing/part_packing_spec.rb +66 -0
- data/spec/notation/packing/program_packing_spec.rb +33 -0
- data/spec/notation/packing/score_packing_spec.rb +301 -0
- data/spec/notation/parsing/articulation_parsing_spec.rb +23 -0
- data/spec/notation/parsing/convenience_methods_spec.rb +99 -0
- data/spec/notation/parsing/duration_nodes_spec.rb +83 -0
- data/spec/notation/parsing/duration_parsing_spec.rb +70 -0
- data/spec/notation/parsing/link_nodes_spec.rb +30 -0
- data/spec/notation/parsing/link_parsing_spec.rb +13 -0
- data/spec/notation/parsing/meter_parsing_spec.rb +23 -0
- data/spec/notation/parsing/note_node_spec.rb +87 -0
- data/spec/notation/parsing/note_parsing_spec.rb +46 -0
- data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +28 -0
- data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +11 -0
- data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +11 -0
- data/spec/notation/parsing/numbers/positive_float_spec.rb +28 -0
- data/spec/notation/parsing/numbers/positive_integer_spec.rb +28 -0
- data/spec/notation/parsing/numbers/positive_rational_spec.rb +28 -0
- data/spec/notation/parsing/pitch_node_spec.rb +38 -0
- data/spec/notation/parsing/pitch_parsing_spec.rb +14 -0
- data/spec/notation/parsing/segment_parsing_spec.rb +27 -0
- data/spec/notation/util/value_computer_spec.rb +146 -0
- data/spec/performance/conversion/glissando_converter_spec.rb +93 -0
- data/spec/performance/conversion/note_sequence_extractor_spec.rb +230 -0
- data/spec/performance/conversion/portamento_converter_spec.rb +91 -0
- data/spec/performance/conversion/score_collator_spec.rb +183 -0
- data/spec/performance/midi/midi_util_spec.rb +110 -0
- data/spec/performance/midi/part_sequencer_spec.rb +40 -0
- data/spec/performance/midi/score_sequencer_spec.rb +50 -0
- data/spec/performance/model/note_sequence_spec.rb +147 -0
- data/spec/performance/util/note_linker_spec.rb +68 -0
- data/spec/performance/util/optimization_spec.rb +73 -0
- data/spec/spec_helper.rb +43 -0
- metadata +323 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
measured_score = Score::Measured.new(FOUR_FOUR,120) do |s|
|
4
|
+
s.program = Program.new([0...2, 0...2,2...4,0...2])
|
5
|
+
s.parts["lead"] = Part.new(Dynamics::MF) do |p|
|
6
|
+
riff = "/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
|
7
|
+
/6Bb3 /4 /12Db4= /4Db4= /8=Db4 /8C4".to_notes
|
8
|
+
p.notes = riff + riff.map {|n| n.transpose(2) }
|
9
|
+
end
|
10
|
+
|
11
|
+
s.parts["bass"] = Part.new(Dynamics::MP) do |p|
|
12
|
+
riff = "/6Bb2 /4 /3Ab2 /6F2 /12Ab2 \
|
13
|
+
/6Bb2 /4 /3Ab2 /4Ab2".to_notes
|
14
|
+
p.notes = riff + riff.map {|n| n.transpose(2) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
unmeasured_score = Score::Unmeasured.new(30) do |s|
|
19
|
+
s.program = measured_score.program
|
20
|
+
s.parts = measured_score.parts
|
21
|
+
end
|
22
|
+
|
23
|
+
timed_score = Score::Timed.new do |s|
|
24
|
+
s.program = measured_score.program
|
25
|
+
s.parts = measured_score.parts
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Score::Measured do
|
29
|
+
before :all do
|
30
|
+
@score = measured_score
|
31
|
+
@h = @score.pack
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#pack' do
|
35
|
+
it 'should return a hash' do
|
36
|
+
@h.should be_a Hash
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should return a hash with keys: "type","parts", "start_meter", ...' do
|
40
|
+
["type","parts","start_tempo","tempo_changes","program","start_meter","meter_changes"].each do |key|
|
41
|
+
@h.should have_key(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should set "type" key to "Measured"' do
|
46
|
+
@h["type"].should eq("Measured")
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should pack start meter as a string' do
|
50
|
+
@h['start_meter'].should be_a String
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should pack meter changes as whatver type Change#pack returns' do
|
54
|
+
@h['meter_changes'].each do |offset,packed_v|
|
55
|
+
change_v = @score.meter_changes[offset]
|
56
|
+
t = change_v.pack.class
|
57
|
+
packed_v.should be_a t
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should pack meter change values as strings' do
|
62
|
+
@h['meter_changes'].each do |offset,packed_v|
|
63
|
+
packed_v[0].should be_a String
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should pack start tempo as numeric' do
|
68
|
+
@h['start_tempo'].should be_a Numeric
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should pack tempo changes as whatver type Change#pack returns' do
|
72
|
+
@h['tempo_changes'].each do |offset,packed_v|
|
73
|
+
change_v = @score.tempo_changes[offset]
|
74
|
+
t = change_v.pack.class
|
75
|
+
packed_v.should be_a t
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should pack tempo change values as numerics' do
|
80
|
+
@h['tempo_changes'].each do |offset,packed_v|
|
81
|
+
packed_v[0].should be_a Numeric
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should pack program as whatever type Program#pack returns' do
|
86
|
+
t = @score.program.pack.class
|
87
|
+
@h['program'].should be_a t
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should pack program segments as strings' do
|
91
|
+
@h['program'].each {|x| x.should be_a String }
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should pack parts as hash' do
|
95
|
+
@h['parts'].should be_a Hash
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should pack parts as whatever Part#pack returns' do
|
99
|
+
@score.parts.each do |name,part|
|
100
|
+
packing = part.pack
|
101
|
+
@h['parts'][name].should eq packing
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '.unpack' do
|
107
|
+
before :all do
|
108
|
+
@score2 = Score::Measured.unpack @h
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should return a Score::Measured' do
|
112
|
+
@score2.should be_a Score::Measured
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should successfuly unpack the parts' do
|
116
|
+
@score2.parts.should eq @score.parts
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should successfuly unpack the start meter' do
|
120
|
+
@score2.start_meter.should eq @score.start_meter
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should successfuly unpack the start tempo' do
|
124
|
+
@score2.start_tempo.should eq @score.start_tempo
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should successfuly unpack the meter changes' do
|
128
|
+
@score2.meter_changes.should eq @score.meter_changes
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should successfuly unpack the tempo changes' do
|
132
|
+
@score2.tempo_changes.should eq @score.tempo_changes
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should successfuly unpack the program' do
|
136
|
+
@score2.program.should eq @score.program
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe Score::Unmeasured do
|
142
|
+
before :all do
|
143
|
+
@score = unmeasured_score
|
144
|
+
@h = @score.pack
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#pack' do
|
148
|
+
it 'should return a hash' do
|
149
|
+
@h.should be_a Hash
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should return a hash with keys: "type","parts", "program", ...' do
|
153
|
+
["type","parts","start_tempo","tempo_changes","program"].each do |key|
|
154
|
+
@h.should have_key(key)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should set "type" key to "Unmeasured"' do
|
159
|
+
@h["type"].should eq("Unmeasured")
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should pack start tempo as numeric' do
|
163
|
+
@h['start_tempo'].should be_a Numeric
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should pack tempo changes as whatver type Change#pack returns' do
|
167
|
+
@h['tempo_changes'].each do |offset,packed_v|
|
168
|
+
change_v = @score.tempo_changes[offset]
|
169
|
+
t = change_v.pack.class
|
170
|
+
packed_v.should be_a t
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should pack tempo change values as numerics' do
|
175
|
+
@h['tempo_changes'].each do |offset,packed_v|
|
176
|
+
packed_v[0].should be_a Numeric
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should pack program as whatever type Program#pack returns' do
|
181
|
+
t = @score.program.pack.class
|
182
|
+
@h['program'].should be_a t
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should pack program segments as strings' do
|
186
|
+
@h['program'].each {|x| x.should be_a String }
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should pack parts as hash' do
|
190
|
+
@h['parts'].should be_a Hash
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should pack parts as whatever Part#pack returns' do
|
194
|
+
@score.parts.each do |name,part|
|
195
|
+
packing = part.pack
|
196
|
+
@h['parts'][name].should eq packing
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe '.unpack' do
|
202
|
+
before :all do
|
203
|
+
@score2 = Score::Unmeasured.unpack @h
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should return a Score::Unmeasured' do
|
207
|
+
@score2.should be_a Score::Unmeasured
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should successfuly unpack the parts' do
|
211
|
+
@score2.parts.should eq @score.parts
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'should successfuly unpack the start tempo' do
|
215
|
+
@score2.start_tempo.should eq @score.start_tempo
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should successfuly unpack the tempo changes' do
|
219
|
+
@score2.tempo_changes.should eq @score.tempo_changes
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'should successfuly unpack the program' do
|
223
|
+
@score2.program.should eq @score.program
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe Score::Timed do
|
229
|
+
before :all do
|
230
|
+
@score = timed_score
|
231
|
+
@h = @score.pack
|
232
|
+
end
|
233
|
+
|
234
|
+
describe '#pack' do
|
235
|
+
it 'should return a hash' do
|
236
|
+
@h.should be_a Hash
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'should return a hash with keys: "type","parts", and "program"' do
|
240
|
+
["type","parts","program"].each do |key|
|
241
|
+
@h.should have_key(key)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'should set "type" key to "Timed"' do
|
246
|
+
@h["type"].should eq("Timed")
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'should pack program as whatever type Program#pack returns' do
|
250
|
+
t = @score.program.pack.class
|
251
|
+
@h['program'].should be_a t
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should pack program segments as strings' do
|
255
|
+
@h['program'].each {|x| x.should be_a String }
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'should pack parts as hash' do
|
259
|
+
@h['parts'].should be_a Hash
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should pack parts as whatever Part#pack returns' do
|
263
|
+
@score.parts.each do |name,part|
|
264
|
+
packing = part.pack
|
265
|
+
@h['parts'][name].should eq packing
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe '.unpack' do
|
271
|
+
before :all do
|
272
|
+
@score2 = Score::Timed.unpack @h
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'should return a Score::Timed' do
|
276
|
+
@score2.should be_a Score::Timed
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'should successfuly unpack the parts' do
|
280
|
+
@score2.parts.should eq @score.parts
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should successfuly unpack the program' do
|
284
|
+
@score2.program.should eq @score.program
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe Score do
|
290
|
+
describe '.unpack' do
|
291
|
+
[ timed_score, unmeasured_score, measured_score ].each do |score|
|
292
|
+
context "given packing from a #{score.class} object" do
|
293
|
+
it "should return a #{score.class} object equal to original" do
|
294
|
+
score2 = Score.unpack(score.pack)
|
295
|
+
score2.should be_a score.class
|
296
|
+
score2.should eq(score)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::ArticulationParser do
|
4
|
+
parser = Parsing::ArticulationParser.new
|
5
|
+
|
6
|
+
{
|
7
|
+
'=' => SLUR,
|
8
|
+
'|' => LEGATO,
|
9
|
+
'_' => TENUTO,
|
10
|
+
'%' => PORTATO,
|
11
|
+
'.' => STACCATO,
|
12
|
+
"'" => STACCATISSIMO
|
13
|
+
}.each do |str,art|
|
14
|
+
res = parser.parse(str)
|
15
|
+
it "should parse '#{str}'" do
|
16
|
+
res.should_not be nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should return a node to responds to :to_articulation correctly' do
|
20
|
+
res.to_articulation.should eq art
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
class_cases = { Duration => {
|
4
|
+
'/2' => "1/2".to_r,
|
5
|
+
'5/29' => "5/29".to_r,
|
6
|
+
'200/' => "200/1".to_r,
|
7
|
+
'66' => "66/1".to_r
|
8
|
+
},
|
9
|
+
Note => {
|
10
|
+
'/2' => Note::half,
|
11
|
+
'99/10C2' => Note.new('99/10'.to_r, [C2]),
|
12
|
+
'5/2.Db4,Eb5' => Note.new('5/2'.to_r, [Db4,Eb5], articulation:STACCATO)
|
13
|
+
},
|
14
|
+
Pitch => {
|
15
|
+
'C2' => C2,
|
16
|
+
'Db4' => Db4,
|
17
|
+
'A#9' => Bb9
|
18
|
+
},
|
19
|
+
Meter => {
|
20
|
+
'2/2' => Meter.new(2,"1/2".to_r),
|
21
|
+
"4/4" => Meter.new(4,"1/4".to_r),
|
22
|
+
"6/8" => Meter.new(6,"1/8".to_r),
|
23
|
+
"12/3" => Meter.new(12,"1/3".to_r),
|
24
|
+
"133/55" => Meter.new(133,"1/55".to_r),
|
25
|
+
},
|
26
|
+
Segment => {
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
class_cases.each do |klass,cases|
|
31
|
+
describe("#{klass}.parse") do
|
32
|
+
it "should produce a single #{klass}" do
|
33
|
+
cases.each do |str,tgt|
|
34
|
+
klass.parse(str).should eq(tgt)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe("#{klass}.split_parse") do
|
40
|
+
context 'joined with whitespace, using default pattern' do
|
41
|
+
it "should produce multiple of #{klass}" do
|
42
|
+
str = cases.keys.join(" ")
|
43
|
+
klass.split_parse(str).should eq(cases.values)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'joined by custom separator, using matching pattern' do
|
48
|
+
it "should raise produce multiple of #{klass}" do
|
49
|
+
str = cases.keys.join(";")
|
50
|
+
klass.split_parse(str,";").should eq(cases.values)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
{
|
57
|
+
Duration => [:to_d, :to_dur, :to_duration],
|
58
|
+
Pitch => [:to_p, :to_pitch],
|
59
|
+
Note => [:to_n, :to_note],
|
60
|
+
Meter => [:to_meter],
|
61
|
+
}.each do |klass,str_parse_methods|
|
62
|
+
describe 'String' do
|
63
|
+
str_parse_methods.each do |method|
|
64
|
+
describe "\##{method}" do
|
65
|
+
it "should return a #{klass}" do
|
66
|
+
class_cases[klass].each do |str,tgt|
|
67
|
+
str.send(method).should eq(tgt)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
{
|
76
|
+
Duration => [:to_ds, :to_durs, :to_durations],
|
77
|
+
Pitch => [:to_ps, :to_pitches],
|
78
|
+
Note => [:to_ns, :to_notes],
|
79
|
+
}.each do |klass,str_parse_methods|
|
80
|
+
describe 'String' do
|
81
|
+
str_parse_methods.each do |method|
|
82
|
+
describe "\##{method}" do
|
83
|
+
context 'joined with whitespace' do
|
84
|
+
it "should return multiple of #{klass}" do
|
85
|
+
str = class_cases[klass].keys.join(" ")
|
86
|
+
str.send(method).should eq(class_cases[klass].values)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'joined by custom separator, using matching pattern' do
|
91
|
+
it "should raise produce multiple of #{klass}" do
|
92
|
+
str = class_cases[klass].keys.join(";")
|
93
|
+
str.send(method,";").should eq(class_cases[klass].values)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::NumDenNode do
|
4
|
+
dur_parser = Parsing::DurationParser.new
|
5
|
+
|
6
|
+
{
|
7
|
+
'1/2' => Rational(1,2),
|
8
|
+
'5/100' => Rational(5,100),
|
9
|
+
'007/777' => Rational(7,777)
|
10
|
+
}.each do |str,tgt|
|
11
|
+
res = dur_parser.parse(str)
|
12
|
+
context str do
|
13
|
+
it 'should parse as NumDenNode' do
|
14
|
+
res.should be_a Parsing::NumDenNode
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#to_r' do
|
18
|
+
r = res.to_r
|
19
|
+
it 'should produce a Rational' do
|
20
|
+
r.should be_a Rational
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should produce value matching input str' do
|
24
|
+
r.should eq tgt
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Parsing::NumOnlyNode do
|
32
|
+
dur_parser = Parsing::DurationParser.new
|
33
|
+
{
|
34
|
+
'1/' => Rational(1,1),
|
35
|
+
'5' => Rational(5,1),
|
36
|
+
'007/' => Rational(7,1)
|
37
|
+
}.each do |str,tgt|
|
38
|
+
res = dur_parser.parse(str)
|
39
|
+
context str do
|
40
|
+
it 'should parse as NumOnlyNode' do
|
41
|
+
res.should be_a Parsing::NumOnlyNode
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#to_r' do
|
45
|
+
r = res.to_r
|
46
|
+
it 'should produce a Rational' do
|
47
|
+
r.should be_a Rational
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should produce value matching input str' do
|
51
|
+
r.should eq tgt
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe Parsing::DenOnlyNode do
|
59
|
+
dur_parser = Parsing::DurationParser.new
|
60
|
+
{
|
61
|
+
'/2' => Rational(1,2),
|
62
|
+
'/100' => Rational(1,100),
|
63
|
+
'/777' => Rational(1,777)
|
64
|
+
}.each do |str,tgt|
|
65
|
+
res = dur_parser.parse(str)
|
66
|
+
context str do
|
67
|
+
it 'should parse as DenOnlyNode' do
|
68
|
+
res.should be_a Parsing::DenOnlyNode
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#to_r' do
|
72
|
+
r = res.to_r
|
73
|
+
it 'should produce a Rational' do
|
74
|
+
r.should be_a Rational
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should produce value matching input str' do
|
78
|
+
r.should eq tgt
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::DurationParser do
|
4
|
+
dur_parser = Parsing::DurationParser.new
|
5
|
+
before :all do
|
6
|
+
@valid = {
|
7
|
+
:numbers => [1,5,50,3999,01,0010,0000005050],
|
8
|
+
}
|
9
|
+
|
10
|
+
@invalid = {
|
11
|
+
:numbers => [0,00],
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'valid (non-zero) numerator and denominator' do
|
16
|
+
["n","n/","n/d","/d"].each do |expr|
|
17
|
+
it "should parse durations of the form #{expr}" do
|
18
|
+
@valid[:numbers].each do |n|
|
19
|
+
@valid[:numbers].each do |d|
|
20
|
+
str = expr.gsub('n',"#{n}")
|
21
|
+
str = str.gsub('d',"#{d}")
|
22
|
+
dur_parser.parse(str).should_not be nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'invalid (zero) numerator and valid denominator' do
|
30
|
+
["n","n/","n/d"].each do |expr|
|
31
|
+
it "should parse durations of the form #{expr}" do
|
32
|
+
@invalid[:numbers].each do |n|
|
33
|
+
@valid[:numbers].each do |d|
|
34
|
+
str = expr.gsub('n',"#{n}")
|
35
|
+
str = str.gsub('d',"#{d}")
|
36
|
+
dur_parser.parse(str).should be nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'valid numerator and invalid (zero) denominator' do
|
44
|
+
["n/d","/d"].each do |expr|
|
45
|
+
it "should parse durations of the form #{expr}" do
|
46
|
+
@valid[:numbers].each do |n|
|
47
|
+
@invalid[:numbers].each do |d|
|
48
|
+
str = expr.gsub('n',"#{n}")
|
49
|
+
str = str.gsub('d',"#{d}")
|
50
|
+
dur_parser.parse(str).should be nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'invalid numerator and invalid denominator' do
|
58
|
+
["n","n/","n/d","/d"].each do |expr|
|
59
|
+
it "should parse durations of the form #{expr}" do
|
60
|
+
@invalid[:numbers].each do |n|
|
61
|
+
@invalid[:numbers].each do |d|
|
62
|
+
str = expr.gsub('n',"#{n}")
|
63
|
+
str = str.gsub('d',"#{d}")
|
64
|
+
dur_parser.parse(str).should be nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::LinkNode do
|
4
|
+
parser = Parsing::LinkParser.new
|
5
|
+
|
6
|
+
{
|
7
|
+
'=C4' => Link::Slur.new(C4),
|
8
|
+
'/Db2' => Link::Portamento.new(Db2),
|
9
|
+
'~C#2' => Link::Glissando.new(Db2),
|
10
|
+
'|Db2' => Link::Legato.new(Db2),
|
11
|
+
}.each do |str,tgt|
|
12
|
+
res = parser.parse(str)
|
13
|
+
context str do
|
14
|
+
it 'should parse as LinkNode' do
|
15
|
+
res.should be_a Parsing::LinkNode
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#to_pitch' do
|
19
|
+
l = res.to_link
|
20
|
+
it 'should produce a Link object' do
|
21
|
+
l.should be_a Link
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should produce pitch matching input str' do
|
25
|
+
l.should eq tgt
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::LinkParser do
|
4
|
+
before :all do
|
5
|
+
@parser = Parsing::LinkParser.new
|
6
|
+
end
|
7
|
+
|
8
|
+
["=C2","|C2","~C2","/C2"].each do |str|
|
9
|
+
it "should parse #{str}" do
|
10
|
+
@parser.should parse(str)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Parsing::MeterParser do
|
4
|
+
parser = Parsing::MeterParser.new
|
5
|
+
|
6
|
+
{
|
7
|
+
'4/4' => FOUR_FOUR,
|
8
|
+
'2*3/8' => SIX_EIGHT,
|
9
|
+
'12/3' => Meter.new(12,"1/3".to_r),
|
10
|
+
'3*3/8' => Meter.new(3,"3/8".to_r),
|
11
|
+
'3/4' => THREE_FOUR
|
12
|
+
}.each do |str,met|
|
13
|
+
res = parser.parse(str)
|
14
|
+
|
15
|
+
it "should parse #{str}" do
|
16
|
+
res.should_not be nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should produce node that properly converts to meter' do
|
20
|
+
res.to_meter.should eq met
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|