musicality 0.1.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/.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
|