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.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +47 -0
  8. data/Rakefile +65 -0
  9. data/bin/midify +78 -0
  10. data/examples/hip.rb +32 -0
  11. data/examples/missed_connection.rb +26 -0
  12. data/examples/song1.rb +33 -0
  13. data/examples/song2.rb +32 -0
  14. data/lib/musicality/errors.rb +9 -0
  15. data/lib/musicality/notation/conversion/change_conversion.rb +19 -0
  16. data/lib/musicality/notation/conversion/measure_note_map.rb +40 -0
  17. data/lib/musicality/notation/conversion/measured_score_conversion.rb +70 -0
  18. data/lib/musicality/notation/conversion/measured_score_converter.rb +95 -0
  19. data/lib/musicality/notation/conversion/note_time_converter.rb +68 -0
  20. data/lib/musicality/notation/conversion/tempo_conversion.rb +25 -0
  21. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +47 -0
  22. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +64 -0
  23. data/lib/musicality/notation/model/articulations.rb +13 -0
  24. data/lib/musicality/notation/model/change.rb +62 -0
  25. data/lib/musicality/notation/model/dynamics.rb +12 -0
  26. data/lib/musicality/notation/model/link.rb +73 -0
  27. data/lib/musicality/notation/model/meter.rb +54 -0
  28. data/lib/musicality/notation/model/meters.rb +9 -0
  29. data/lib/musicality/notation/model/note.rb +120 -0
  30. data/lib/musicality/notation/model/part.rb +54 -0
  31. data/lib/musicality/notation/model/pitch.rb +163 -0
  32. data/lib/musicality/notation/model/pitches.rb +21 -0
  33. data/lib/musicality/notation/model/program.rb +53 -0
  34. data/lib/musicality/notation/model/score.rb +132 -0
  35. data/lib/musicality/notation/packing/change_packing.rb +46 -0
  36. data/lib/musicality/notation/packing/part_packing.rb +31 -0
  37. data/lib/musicality/notation/packing/program_packing.rb +16 -0
  38. data/lib/musicality/notation/packing/score_packing.rb +108 -0
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +264 -0
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +59 -0
  41. data/lib/musicality/notation/parsing/convenience_methods.rb +74 -0
  42. data/lib/musicality/notation/parsing/duration_nodes.rb +21 -0
  43. data/lib/musicality/notation/parsing/duration_parsing.rb +205 -0
  44. data/lib/musicality/notation/parsing/duration_parsing.treetop +25 -0
  45. data/lib/musicality/notation/parsing/link_nodes.rb +35 -0
  46. data/lib/musicality/notation/parsing/link_parsing.rb +270 -0
  47. data/lib/musicality/notation/parsing/link_parsing.treetop +33 -0
  48. data/lib/musicality/notation/parsing/meter_parsing.rb +190 -0
  49. data/lib/musicality/notation/parsing/meter_parsing.treetop +29 -0
  50. data/lib/musicality/notation/parsing/note_node.rb +40 -0
  51. data/lib/musicality/notation/parsing/note_parsing.rb +229 -0
  52. data/lib/musicality/notation/parsing/note_parsing.treetop +28 -0
  53. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +289 -0
  54. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop +29 -0
  55. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +64 -0
  56. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +17 -0
  57. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +86 -0
  58. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop +20 -0
  59. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +503 -0
  60. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop +33 -0
  61. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +95 -0
  62. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +19 -0
  63. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +84 -0
  64. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop +19 -0
  65. data/lib/musicality/notation/parsing/parseable.rb +30 -0
  66. data/lib/musicality/notation/parsing/pitch_node.rb +23 -0
  67. data/lib/musicality/notation/parsing/pitch_parsing.rb +448 -0
  68. data/lib/musicality/notation/parsing/pitch_parsing.treetop +52 -0
  69. data/lib/musicality/notation/parsing/segment_parsing.rb +141 -0
  70. data/lib/musicality/notation/parsing/segment_parsing.treetop +23 -0
  71. data/lib/musicality/notation/util/interpolation.rb +16 -0
  72. data/lib/musicality/notation/util/piecewise_function.rb +122 -0
  73. data/lib/musicality/notation/util/value_computer.rb +170 -0
  74. data/lib/musicality/performance/conversion/glissando_converter.rb +34 -0
  75. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +98 -0
  76. data/lib/musicality/performance/conversion/portamento_converter.rb +24 -0
  77. data/lib/musicality/performance/conversion/score_collator.rb +126 -0
  78. data/lib/musicality/performance/midi/midi_events.rb +34 -0
  79. data/lib/musicality/performance/midi/midi_util.rb +31 -0
  80. data/lib/musicality/performance/midi/part_sequencer.rb +123 -0
  81. data/lib/musicality/performance/midi/score_sequencer.rb +45 -0
  82. data/lib/musicality/performance/model/note_attacks.rb +19 -0
  83. data/lib/musicality/performance/model/note_sequence.rb +111 -0
  84. data/lib/musicality/performance/util/note_linker.rb +28 -0
  85. data/lib/musicality/performance/util/optimization.rb +31 -0
  86. data/lib/musicality/validatable.rb +38 -0
  87. data/lib/musicality/version.rb +3 -0
  88. data/lib/musicality.rb +81 -0
  89. data/musicality.gemspec +30 -0
  90. data/spec/musicality_spec.rb +7 -0
  91. data/spec/notation/conversion/change_conversion_spec.rb +40 -0
  92. data/spec/notation/conversion/measure_note_map_spec.rb +73 -0
  93. data/spec/notation/conversion/measured_score_conversion_spec.rb +141 -0
  94. data/spec/notation/conversion/measured_score_converter_spec.rb +329 -0
  95. data/spec/notation/conversion/note_time_converter_spec.rb +81 -0
  96. data/spec/notation/conversion/tempo_conversion_spec.rb +40 -0
  97. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +71 -0
  98. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +116 -0
  99. data/spec/notation/model/change_spec.rb +90 -0
  100. data/spec/notation/model/link_spec.rb +83 -0
  101. data/spec/notation/model/meter_spec.rb +97 -0
  102. data/spec/notation/model/note_spec.rb +183 -0
  103. data/spec/notation/model/part_spec.rb +69 -0
  104. data/spec/notation/model/pitch_spec.rb +180 -0
  105. data/spec/notation/model/program_spec.rb +50 -0
  106. data/spec/notation/model/score_spec.rb +211 -0
  107. data/spec/notation/packing/change_packing_spec.rb +153 -0
  108. data/spec/notation/packing/part_packing_spec.rb +66 -0
  109. data/spec/notation/packing/program_packing_spec.rb +33 -0
  110. data/spec/notation/packing/score_packing_spec.rb +301 -0
  111. data/spec/notation/parsing/articulation_parsing_spec.rb +23 -0
  112. data/spec/notation/parsing/convenience_methods_spec.rb +99 -0
  113. data/spec/notation/parsing/duration_nodes_spec.rb +83 -0
  114. data/spec/notation/parsing/duration_parsing_spec.rb +70 -0
  115. data/spec/notation/parsing/link_nodes_spec.rb +30 -0
  116. data/spec/notation/parsing/link_parsing_spec.rb +13 -0
  117. data/spec/notation/parsing/meter_parsing_spec.rb +23 -0
  118. data/spec/notation/parsing/note_node_spec.rb +87 -0
  119. data/spec/notation/parsing/note_parsing_spec.rb +46 -0
  120. data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +28 -0
  121. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +11 -0
  122. data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +11 -0
  123. data/spec/notation/parsing/numbers/positive_float_spec.rb +28 -0
  124. data/spec/notation/parsing/numbers/positive_integer_spec.rb +28 -0
  125. data/spec/notation/parsing/numbers/positive_rational_spec.rb +28 -0
  126. data/spec/notation/parsing/pitch_node_spec.rb +38 -0
  127. data/spec/notation/parsing/pitch_parsing_spec.rb +14 -0
  128. data/spec/notation/parsing/segment_parsing_spec.rb +27 -0
  129. data/spec/notation/util/value_computer_spec.rb +146 -0
  130. data/spec/performance/conversion/glissando_converter_spec.rb +93 -0
  131. data/spec/performance/conversion/note_sequence_extractor_spec.rb +230 -0
  132. data/spec/performance/conversion/portamento_converter_spec.rb +91 -0
  133. data/spec/performance/conversion/score_collator_spec.rb +183 -0
  134. data/spec/performance/midi/midi_util_spec.rb +110 -0
  135. data/spec/performance/midi/part_sequencer_spec.rb +40 -0
  136. data/spec/performance/midi/score_sequencer_spec.rb +50 -0
  137. data/spec/performance/model/note_sequence_spec.rb +147 -0
  138. data/spec/performance/util/note_linker_spec.rb +68 -0
  139. data/spec/performance/util/optimization_spec.rb +73 -0
  140. data/spec/spec_helper.rb +43 -0
  141. 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