musicality 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +27 -1
  3. data/README.md +153 -10
  4. data/bin/collidify +102 -0
  5. data/bin/lilify +57 -29
  6. data/bin/midify +64 -24
  7. data/bin/musicality +39 -0
  8. data/examples/composition/auto_counterpoint.rb +4 -5
  9. data/examples/composition/part_generator.rb +8 -2
  10. data/examples/composition/scale_exercise.rb +1 -1
  11. data/examples/notation/notes.rb +27 -0
  12. data/examples/notation/parts.rb +51 -0
  13. data/examples/notation/scores.rb +38 -0
  14. data/examples/notation/twinkle.rb +34 -0
  15. data/examples/notation/twinkle.score +33 -0
  16. data/lib/musicality.rb +46 -11
  17. data/lib/musicality/composition/dsl/score_dsl.rb +2 -2
  18. data/lib/musicality/composition/dsl/score_methods.rb +10 -7
  19. data/lib/musicality/notation/conversion/change_conversion.rb +1 -1
  20. data/lib/musicality/notation/conversion/note_time_converter.rb +6 -23
  21. data/lib/musicality/notation/conversion/score_conversion.rb +15 -15
  22. data/lib/musicality/notation/conversion/score_converter.rb +50 -67
  23. data/lib/musicality/notation/model/articulations.rb +3 -2
  24. data/lib/musicality/notation/model/change.rb +15 -6
  25. data/lib/musicality/notation/model/dynamics.rb +11 -8
  26. data/lib/musicality/notation/model/instrument.rb +61 -0
  27. data/lib/musicality/notation/model/instruments.rb +111 -0
  28. data/lib/musicality/notation/model/key.rb +137 -0
  29. data/lib/musicality/notation/model/keys.rb +37 -0
  30. data/lib/musicality/notation/model/link.rb +6 -19
  31. data/lib/musicality/notation/model/mark.rb +43 -0
  32. data/lib/musicality/notation/model/marks.rb +11 -0
  33. data/lib/musicality/notation/model/meter.rb +4 -0
  34. data/lib/musicality/notation/model/note.rb +42 -28
  35. data/lib/musicality/notation/model/part.rb +18 -5
  36. data/lib/musicality/notation/model/pitch.rb +13 -4
  37. data/lib/musicality/notation/model/score.rb +104 -66
  38. data/lib/musicality/notation/model/symbols.rb +16 -11
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +38 -38
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +14 -14
  41. data/lib/musicality/notation/parsing/link_parsing.rb +6 -6
  42. data/lib/musicality/notation/parsing/link_parsing.treetop +3 -3
  43. data/lib/musicality/notation/parsing/mark_parsing.rb +138 -0
  44. data/lib/musicality/notation/parsing/mark_parsing.treetop +31 -0
  45. data/lib/musicality/notation/parsing/note_node.rb +19 -12
  46. data/lib/musicality/notation/parsing/note_parsing.rb +218 -87
  47. data/lib/musicality/notation/parsing/note_parsing.treetop +9 -5
  48. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +7 -2
  49. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +1 -1
  50. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +6 -4
  51. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +1 -1
  52. data/lib/musicality/notation/util/function.rb +41 -18
  53. data/lib/musicality/packable.rb +156 -0
  54. data/lib/musicality/performance/conversion/glissando_converter.rb +2 -2
  55. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +223 -70
  56. data/lib/musicality/performance/conversion/portamento_converter.rb +5 -2
  57. data/lib/musicality/performance/conversion/score_collator.rb +70 -64
  58. data/lib/musicality/performance/midi/midi_events.rb +3 -3
  59. data/lib/musicality/performance/midi/midi_settings.rb +127 -0
  60. data/lib/musicality/performance/midi/midi_util.rb +8 -2
  61. data/lib/musicality/performance/midi/part_sequencer.rb +19 -18
  62. data/lib/musicality/performance/midi/score_sequencer.rb +13 -9
  63. data/lib/musicality/performance/midi/score_sequencing.rb +5 -5
  64. data/lib/musicality/performance/model/attack.rb +8 -0
  65. data/lib/musicality/performance/model/duration_functions.rb +23 -0
  66. data/lib/musicality/performance/model/note_sequence.rb +52 -95
  67. data/lib/musicality/performance/model/separation.rb +10 -0
  68. data/lib/musicality/performance/supercollider/add_actions.rb +13 -0
  69. data/lib/musicality/performance/supercollider/bundle.rb +18 -0
  70. data/lib/musicality/performance/supercollider/conductor.rb +125 -0
  71. data/lib/musicality/performance/supercollider/group.rb +71 -0
  72. data/lib/musicality/performance/supercollider/message.rb +26 -0
  73. data/lib/musicality/performance/supercollider/node.rb +122 -0
  74. data/lib/musicality/performance/supercollider/performer.rb +123 -0
  75. data/lib/musicality/performance/supercollider/score_conducting.rb +17 -0
  76. data/lib/musicality/performance/supercollider/server.rb +8 -0
  77. data/lib/musicality/performance/supercollider/synth.rb +43 -0
  78. data/lib/musicality/performance/supercollider/synthdef.rb +57 -0
  79. data/lib/musicality/performance/supercollider/synthdef_settings.rb +23 -0
  80. data/lib/musicality/performance/supercollider/synthdefs.rb +1654 -0
  81. data/lib/musicality/{composition/model/pitch_class.rb → pitch_class.rb} +1 -1
  82. data/lib/musicality/{composition/model/pitch_classes.rb → pitch_classes.rb} +9 -9
  83. data/lib/musicality/printing/lilypond/clef.rb +12 -0
  84. data/lib/musicality/printing/lilypond/key_engraving.rb +9 -0
  85. data/lib/musicality/printing/lilypond/lilypond_settings.rb +105 -0
  86. data/lib/musicality/printing/lilypond/meter_engraving.rb +1 -1
  87. data/lib/musicality/printing/lilypond/note_engraving.rb +112 -30
  88. data/lib/musicality/printing/lilypond/part_engraver.rb +114 -3
  89. data/lib/musicality/printing/lilypond/pitch_class_engraving.rb +22 -0
  90. data/lib/musicality/printing/lilypond/pitch_engraving.rb +2 -15
  91. data/lib/musicality/printing/lilypond/score_engraver.rb +44 -73
  92. data/lib/musicality/printing/lilypond/score_engraving.rb +3 -3
  93. data/lib/musicality/project/create_tasks.rb +31 -0
  94. data/lib/musicality/project/file_cleaner.rb +19 -0
  95. data/lib/musicality/project/file_raker.rb +107 -0
  96. data/lib/musicality/project/load_config.rb +43 -0
  97. data/lib/musicality/project/project.rb +64 -0
  98. data/lib/musicality/version.rb +1 -1
  99. data/musicality.gemspec +3 -0
  100. data/spec/composition/util/random_sampler_spec.rb +1 -1
  101. data/spec/notation/conversion/measure_note_map_spec.rb +1 -1
  102. data/spec/notation/conversion/note_time_converter_spec.rb +5 -85
  103. data/spec/notation/conversion/score_conversion_spec.rb +6 -41
  104. data/spec/notation/conversion/score_converter_spec.rb +19 -137
  105. data/spec/notation/model/change_spec.rb +55 -0
  106. data/spec/notation/model/key_spec.rb +171 -0
  107. data/spec/notation/model/link_spec.rb +34 -5
  108. data/spec/notation/model/meter_spec.rb +15 -0
  109. data/spec/notation/model/note_spec.rb +33 -27
  110. data/spec/notation/model/part_spec.rb +53 -4
  111. data/spec/notation/model/pitch_spec.rb +15 -0
  112. data/spec/notation/model/score_spec.rb +64 -72
  113. data/spec/notation/parsing/link_nodes_spec.rb +3 -3
  114. data/spec/notation/parsing/link_parsing_spec.rb +6 -6
  115. data/spec/notation/parsing/note_node_spec.rb +34 -9
  116. data/spec/notation/parsing/note_parsing_spec.rb +11 -9
  117. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +4 -0
  118. data/spec/notation/parsing/pitch_node_spec.rb +0 -1
  119. data/spec/notation/util/value_computer_spec.rb +2 -2
  120. data/spec/performance/conversion/glissando_converter_spec.rb +9 -9
  121. data/spec/performance/conversion/note_sequence_extractor_spec.rb +48 -53
  122. data/spec/performance/conversion/portamento_converter_spec.rb +11 -9
  123. data/spec/performance/conversion/score_collator_spec.rb +59 -63
  124. data/spec/performance/midi/midi_util_spec.rb +22 -8
  125. data/spec/performance/midi/part_sequencer_spec.rb +2 -2
  126. data/spec/performance/midi/score_sequencer_spec.rb +12 -10
  127. data/spec/performance/midi/score_sequencing_spec.rb +2 -2
  128. data/spec/performance/model/note_sequence_spec.rb +41 -134
  129. data/spec/printing/note_engraving_spec.rb +204 -0
  130. data/spec/printing/score_engraver_spec.rb +40 -0
  131. data/spec/spec_helper.rb +1 -0
  132. metadata +69 -23
  133. data/examples/notation/hip.rb +0 -32
  134. data/examples/notation/missed_connection.rb +0 -26
  135. data/examples/notation/song1.rb +0 -33
  136. data/examples/notation/song2.rb +0 -32
  137. data/lib/musicality/notation/model/links.rb +0 -11
  138. data/lib/musicality/notation/packing/change_packing.rb +0 -56
  139. data/lib/musicality/notation/packing/part_packing.rb +0 -31
  140. data/lib/musicality/notation/packing/score_packing.rb +0 -123
  141. data/lib/musicality/performance/model/note_attacks.rb +0 -19
  142. data/lib/musicality/performance/util/note_linker.rb +0 -28
  143. data/spec/notation/packing/change_packing_spec.rb +0 -304
  144. data/spec/notation/packing/part_packing_spec.rb +0 -66
  145. data/spec/notation/packing/score_packing_spec.rb +0 -255
  146. data/spec/performance/util/note_linker_spec.rb +0 -68
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'yaml'
2
3
 
3
4
  describe Pitch do
4
5
 
@@ -158,6 +159,20 @@ describe Pitch do
158
159
  YAML.load(p.to_yaml).should eq p
159
160
  end
160
161
  end
162
+
163
+ describe '#pack' do
164
+ it 'should produce a Hash' do
165
+ Bb3.pack.should be_a Hash
166
+ end
167
+ end
168
+
169
+ describe 'unpack' do
170
+ it 'should produce an object equal the original' do
171
+ p2 = Pitch.unpack Bb3.pack
172
+ p2.should be_a Pitch
173
+ p2.should eq Bb3
174
+ end
175
+ end
161
176
 
162
177
  describe '#to_s' do
163
178
  context 'on-letter semitones' do
@@ -117,17 +117,31 @@ describe Score do
117
117
  end
118
118
  end
119
119
 
120
- describe Score::Measured do
120
+ describe Score::Tempo do
121
+ before :all do
122
+ @basic_score = Score::Tempo.new(TWO_FOUR, 120,
123
+ meter_changes: {
124
+ 2 => Change::Immediate.new(FOUR_FOUR),
125
+ 4 => Change::Immediate.new(SIX_EIGHT),
126
+ },
127
+ parts: {
128
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
129
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1 /2".to_notes)
130
+ },
131
+ program: [ (0.5)..Rational(1,2), 0..1, 1..2 ]
132
+ )
133
+ end
134
+
121
135
  describe '#initialize' do
122
136
  it 'should use empty containers for parameters not given' do
123
- s = Score::Measured.new(FOUR_FOUR,120)
137
+ s = Score::Tempo.new(FOUR_FOUR,120)
124
138
  s.parts.should be_empty
125
139
  s.program.should be_empty
126
140
  end
127
141
 
128
142
  it 'should assign given parameters' do
129
143
  m = FOUR_FOUR
130
- s = Score::Measured.new(m,120)
144
+ s = Score::Tempo.new(m,120)
131
145
  s.start_meter.should eq m
132
146
  s.start_tempo.should eq 120
133
147
 
@@ -136,7 +150,7 @@ describe Score::Measured do
136
150
  mcs = { 1 => Change::Immediate.new(THREE_FOUR) }
137
151
  tcs = { 1 => Change::Immediate.new(100) }
138
152
 
139
- s = Score::Measured.new(m,120,
153
+ s = Score::Tempo.new(m,120,
140
154
  parts: parts,
141
155
  program: program,
142
156
  meter_changes: mcs,
@@ -153,13 +167,13 @@ describe Score::Measured do
153
167
  context 'with no meter changes' do
154
168
  context 'with no parts' do
155
169
  it 'should return 0' do
156
- Score::Measured.new(TWO_FOUR, 120).measures_long.should eq(0)
170
+ Score::Tempo.new(TWO_FOUR, 120).measures_long.should eq(0)
157
171
  end
158
172
  end
159
173
 
160
174
  context 'with one part' do
161
175
  it 'should return the duration of the part, in measures' do
162
- Score::Measured.new(TWO_FOUR, 120, parts: {
176
+ Score::Tempo.new(TWO_FOUR, 120, parts: {
163
177
  "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes)
164
178
  }).measures_long.should eq(3.5)
165
179
  end
@@ -167,7 +181,7 @@ describe Score::Measured do
167
181
 
168
182
  context 'with two parts' do
169
183
  it 'should return the duration of the longest part, in measures' do
170
- Score::Measured.new(TWO_FOUR, 120, parts: {
184
+ Score::Tempo.new(TWO_FOUR, 120, parts: {
171
185
  "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
172
186
  "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
173
187
  }).measures_long.should eq(4)
@@ -177,7 +191,7 @@ describe Score::Measured do
177
191
 
178
192
  context 'with meter changes' do
179
193
  it 'should return the duration of the longest part, in measures' do
180
- Score::Measured.new(TWO_FOUR, 120,
194
+ Score::Tempo.new(TWO_FOUR, 120,
181
195
  meter_changes: {
182
196
  2 => Change::Immediate.new(FOUR_FOUR),
183
197
  },
@@ -187,7 +201,7 @@ describe Score::Measured do
187
201
  }
188
202
  ).measures_long.should eq(3)
189
203
 
190
- Score::Measured.new(TWO_FOUR, 120,
204
+ Score::Tempo.new(TWO_FOUR, 120,
191
205
  meter_changes: {
192
206
  2 => Change::Immediate.new(FOUR_FOUR),
193
207
  4 => Change::Immediate.new(SIX_EIGHT),
@@ -202,7 +216,7 @@ describe Score::Measured do
202
216
 
203
217
  context 'given specific note duration' do
204
218
  it 'should change the given note duration to measures' do
205
- score = Score::Measured.new(TWO_FOUR, 120,
219
+ score = Score::Tempo.new(TWO_FOUR, 120,
206
220
  meter_changes: {
207
221
  2 => Change::Immediate.new(FOUR_FOUR),
208
222
  4 => Change::Immediate.new(SIX_EIGHT)
@@ -228,7 +242,7 @@ describe Score::Measured do
228
242
  }.each do |context_str,args|
229
243
  context context_str do
230
244
  it 'should return true' do
231
- Score::Measured.new(*args).should be_valid
245
+ Score::Tempo.new(*args).should be_valid
232
246
  end
233
247
  end
234
248
  end
@@ -251,77 +265,33 @@ describe Score::Measured do
251
265
  }.each do |context_str,args|
252
266
  context context_str do
253
267
  it 'should return false' do
254
- Score::Measured.new(*args).should be_invalid
268
+ Score::Tempo.new(*args).should be_invalid
255
269
  end
256
270
  end
257
271
  end
258
272
  end
259
- end
260
273
 
261
- describe Score::Unmeasured do
262
- describe '#initialize' do
263
- it 'should use empty containers for parameters not given' do
264
- s = Score::Unmeasured.new(30)
265
- s.parts.should be_empty
266
- s.program.should be_empty
274
+ describe '#pack' do
275
+ it 'should produce a Hash' do
276
+ @basic_score.pack.should be_a Hash
267
277
  end
268
-
269
- it 'should assign given parameters' do
270
- s = Score::Unmeasured.new(30)
271
- s.start_tempo.should eq(30)
272
-
273
- parts = { "piano (LH)" => Samples::SAMPLE_PART }
274
- program = [0...0.75, 0...0.75]
275
- tcs = { 1 => Change::Immediate.new(40) }
276
-
277
- s = Score::Unmeasured.new(30,
278
- parts: parts,
279
- program: program,
280
- tempo_changes: tcs
281
- )
282
- s.parts.should eq parts
283
- s.program.should eq program
284
- s.tempo_changes.should eq tcs
278
+
279
+ it 'should pack program as an array of strings' do
280
+ program = @basic_score.pack[:program]
281
+ program.each {|entry| entry.should be_a String}
285
282
  end
286
- end
287
283
 
288
- describe '#notes_long' do
289
- it 'should return the duration of the longest part' do
290
- Score::Unmeasured.new(120, parts: {
291
- "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
292
- "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
293
- }).notes_long.should eq(2)
284
+ it 'should pack sections as a Hash of strings' do
285
+ program = @basic_score.pack[:sections]
286
+ program.each {|name,entry| entry.should be_a String}
294
287
  end
295
288
  end
296
-
297
- describe '#valid?' do
298
- {
299
- 'valid start tempo' => [ 40 ],
300
- 'valid tempo changes' => [ 30,
301
- :tempo_changes => { 1 => Change::Gradual.linear(40, 2), 2 => Change::Immediate.new(50) } ],
302
- 'valid part' => [ 30, :parts => { "piano" => Samples::SAMPLE_PART }],
303
- 'valid program' => [ 30, :program => [0..2,0..2] ]
304
- }.each do |context_str,args|
305
- context context_str do
306
- it 'should return true' do
307
- Score::Unmeasured.new(*args).should be_valid
308
- end
309
- end
310
- end
311
-
312
- {
313
- 'start tempo valid is zero' => [ 0 ],
314
- 'start tempo valid is negative' => [ -1 ],
315
- 'tempo change value is not a valid value' => [ 30,
316
- :tempo_changes => { 1 => Change::Gradual.linear(-1,1) } ],
317
- 'invalid part' => [ 30, :parts => { "piano" => Part.new(-0.1) }],
318
- 'invalid program' => [ 30, :program => [2..0] ],
319
- }.each do |context_str,args|
320
- context context_str do
321
- it 'should return false' do
322
- Score::Unmeasured.new(*args).should be_invalid
323
- end
324
- end
289
+
290
+ describe 'unpack' do
291
+ it 'should produce an object equal the original' do
292
+ score2 = Score::Tempo.unpack @basic_score.pack
293
+ score2.should be_a Score
294
+ score2.should eq @basic_score
325
295
  end
326
296
  end
327
297
  end
@@ -376,4 +346,26 @@ describe Score::Timed do
376
346
  end
377
347
  end
378
348
  end
349
+
350
+ describe '#pack' do
351
+ it 'should produce a Hash' do
352
+ score = Score::Timed.new(parts: {
353
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
354
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
355
+ })
356
+ score.pack.should be_a Hash
357
+ end
358
+ end
359
+
360
+ describe 'unpack' do
361
+ it 'should produce an object equal the original' do
362
+ score = Score::Timed.new(parts: {
363
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
364
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
365
+ })
366
+ score2 = Score::Timed.unpack score.pack
367
+ score2.should be_a score.class
368
+ score2.should eq score
369
+ end
370
+ end
379
371
  end
@@ -4,9 +4,9 @@ describe Parsing::LinkNode do
4
4
  parser = Parsing::LinkParser.new
5
5
 
6
6
  {
7
- LINK_SYMBOLS[Links::TIE] => Link::Tie.new,
8
- (LINK_SYMBOLS[Links::GLISSANDO] + Db2.to_s) => Link::Glissando.new(Db2),
9
- (LINK_SYMBOLS[Links::PORTAMENTO] + Db2.to_s) => Link::Portamento.new(Db2),
7
+ LINK_SYMBOLS[Link::Tie] => Link::Tie.new,
8
+ (LINK_SYMBOLS[Link::Glissando] + Db2.to_s) => Link::Glissando.new(Db2),
9
+ (LINK_SYMBOLS[Link::Portamento] + Db2.to_s) => Link::Portamento.new(Db2),
10
10
  }.each do |str,tgt|
11
11
  res = parser.parse(str)
12
12
  context str do
@@ -5,15 +5,15 @@ describe Parsing::LinkParser do
5
5
  @parser = Parsing::LinkParser.new
6
6
  end
7
7
 
8
- it "should parse #{LINK_SYMBOLS[Links::TIE]}" do
9
- @parser.should parse(LINK_SYMBOLS[Links::TIE])
8
+ it "should parse #{LINK_SYMBOLS[Link::Tie]}" do
9
+ @parser.should parse(LINK_SYMBOLS[Link::Tie])
10
10
  end
11
11
 
12
- it "should parse #{LINK_SYMBOLS[Links::GLISSANDO]} with target pitch" do
13
- @parser.should parse(LINK_SYMBOLS[Links::GLISSANDO] + C3.to_s)
12
+ it "should parse #{LINK_SYMBOLS[Link::Glissando]} with target pitch" do
13
+ @parser.should parse(LINK_SYMBOLS[Link::Glissando] + C3.to_s)
14
14
  end
15
15
 
16
- it "should parse #{LINK_SYMBOLS[Links::PORTAMENTO]} with target pitch" do
17
- @parser.should parse(LINK_SYMBOLS[Links::GLISSANDO] + C3.to_s)
16
+ it "should parse #{LINK_SYMBOLS[Link::Portamento]} with target pitch" do
17
+ @parser.should parse(LINK_SYMBOLS[Link::Portamento] + C3.to_s)
18
18
  end
19
19
  end
@@ -32,15 +32,15 @@ describe Parsing::NoteNode do
32
32
 
33
33
  context 'monophonic note' do
34
34
  {
35
- '/2C2=' => Note.new(Rational(1,2),[C2], links: { C2 => Link::Tie.new}),
35
+ '/2C2~' => Note.new(Rational(1,2),[C2], links: { C2 => Link::Tie.new}),
36
36
  '4/2D#6.' => Note.new(Rational(4,2),[Eb6],articulation:STACCATO),
37
- '28Eb7%!' => Note.new(Rational(28,1),[Eb7],articulation:PORTATO, accented: true),
38
- "56/33B1'" => Note.new(Rational(56,33),[B1],articulation:STACCATISSIMO),
37
+ '28Eb7_' => Note.new(Rational(28,1),[Eb7],articulation:PORTATO),
38
+ "56/33B1!" => Note.new(Rational(56,33),[B1],articulation:STACCATISSIMO),
39
39
  }.each do |str,tgt|
40
40
  res = NOTE_PARSER.parse(str)
41
41
 
42
42
  context str do
43
- it 'should parse as MonophonicNoteNode' do
43
+ it 'should parse as `Node' do
44
44
  res.should be_a Parsing::NoteNode
45
45
  end
46
46
 
@@ -60,20 +60,21 @@ describe Parsing::NoteNode do
60
60
 
61
61
  context 'polyphonic note' do
62
62
  {
63
- '/2C2,D2,E2(' => Note.new(Rational(1,2),[C2,D2,E2],articulation: Articulations::SLUR),
64
- '/2C2,D2,E2[' => Note.new(Rational(1,2),[C2,D2,E2],articulation: Articulations::LEGATO),
63
+ '/2C2,D2,E2>' => Note.new(Rational(1,2),[C2,D2,E2],articulation: Articulations::ACCENT),
64
+ '/2C2,D2,E2^' => Note.new(Rational(1,2),[C2,D2,E2],articulation: Articulations::MARCATO),
65
65
  '4/2D#6,G4.' => Note.new(Rational(4,2),[Eb6,G4], articulation: Articulations::STACCATO),
66
- '28Eb7,D7,G7_' => Note.new(Rational(28,1),[Eb7,D7,G7],articulation: Articulations::TENUTO),
67
- '56/33B1,B2,B3,B4,B5!' => Note.new(Rational(56,33),[B1,B2,B3,B4,B5], accented: true),
66
+ '28Eb7,D7,G7-' => Note.new(Rational(28,1),[Eb7,D7,G7], articulation: Articulations::TENUTO),
67
+ '56/33B1,B2,B3,B4,B5_' => Note.new(Rational(56,33),[B1,B2,B3,B4,B5], articulation: Articulations::PORTATO),
68
68
  }.each do |str,tgt|
69
69
  res = NOTE_PARSER.parse(str)
70
70
  context str do
71
- it 'should parse as PolyphonicNoteNode' do
71
+ it 'should parse as NoteNode' do
72
72
  res.should be_a Parsing::NoteNode
73
73
  end
74
74
 
75
75
  describe '#to_note' do
76
76
  n = res.to_note
77
+
77
78
  it 'should produce a Note' do
78
79
  n.should be_a Note
79
80
  end
@@ -85,4 +86,28 @@ describe Parsing::NoteNode do
85
86
  end
86
87
  end
87
88
  end
89
+
90
+ context 'with marks' do
91
+ [[BEGIN_SLUR],[BEGIN_SLUR, BEGIN_TRIPLET],[BEGIN_TRIPLET]].each do |begin_marks|
92
+ begin_marks_str = begin_marks.map {|m| m.to_s}.join
93
+ [[END_SLUR],[END_SLUR, END_TRIPLET],[END_TRIPLET]].each do |end_marks|
94
+ end_marks_str = end_marks.map {|m| m.to_s}.join
95
+ describe '#to_note' do
96
+ it 'should produce a Note with marks set correctly' do
97
+ str = "#{begin_marks_str}/4Bb2#{end_marks_str}"
98
+ n = NOTE_PARSER.parse(str).to_note
99
+ n.marks.should eq(begin_marks+end_marks)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'without marks' do
107
+ it 'should produce a Note with marks set to []' do
108
+ str = "/4Bb2"
109
+ n = NOTE_PARSER.parse(str).to_note
110
+ n.marks.should eq([])
111
+ end
112
+ end
88
113
  end
@@ -9,20 +9,22 @@ describe Parsing::NoteParser do
9
9
  'duration only' => ['1/4','/2','1','55/33'],
10
10
  'single pitch' => ['/4C2','5/3Db3','/33E#8'],
11
11
  'multiple pitches' => ['/4C2,C3,c5','5/3Db3,Bb2,E5','/33E#8,F1,B9'],
12
- 'with articulation' => ['/4C2.',"5/3Db3,Bb2,E5'",'/33F3(','/2D3,F4_'],
13
- 'with accent' => ['/4C2!','3/2Db3,Bb4!'],
14
- 'with links' => ['/2C2=','/2C2|D2','/4D4|E4,G4~A5.'],
12
+ 'with articulation' => ['/4C2.',"5/3Db3,Bb2,E5.",'/2D3,F4_'],
13
+ 'with accent' => ['/4C2','3/2Db3,Bb4'],
14
+ 'with links' => ['/2C2~','/2C2:D2','/4D4:E4,G4;A5.'],
15
+ 'with marks' => ['(3/4Bb3]', '[/2F3,G3)', '[(2/4C3', '([1B2', '/3B2,C2)]', '2/3D4])'],
15
16
  'with single pitch + articulation + link + accent' => [
16
- '3/4D2=(!','5/8F2~G2.!','/8Db4|Db5!','/3G4~B4_!'],
17
+ '(3/4D2~','5/8F2;G2.','/8Db4:Db5','/3G4;B4_'],
17
18
  'with multiple pitches + articulation + links + accent' => [
18
- '5/4D2=,G4|A4,C3~D3.!','5/8F2=,B4|A4_!'],
19
+ '5/4D2~,G4:A4,C3;D3.','5/8F2~,B4:A4_'],
19
20
  }
20
21
  invalid_cases = {
21
- 'duration + accent' => ['1/4!','/2!'],
22
- 'duration + articulation' => ['1/4.','/2%','2/3('],
23
- 'duration + accent + link' => ['1/4!~','/2!/','2/3=!'],
22
+ 'duration + articulation' => ['1/4.','/2.','2/3!'],
23
+ 'duration + accent + link' => ['1/4;','/2:','2/3~'],
24
24
  'single pith with bad letter' => ['5/3Hb3'],
25
- 'single pitch without octave' => ['/33E(2'],
25
+ 'single pitch without octave' => ['/33E)'],
26
+ 'begins marks at the end' => ['1Bb3(', '2Bb3['],
27
+ 'end marks at the beginning ' => [']1B5', ')3C3']
26
28
  }
27
29
 
28
30
  valid_cases.each do |descr, strs|
@@ -8,4 +8,8 @@ describe Parsing::NonnegativeIntegerParser do
8
8
  parser.parse(str).should_not be nil
9
9
  end
10
10
  end
11
+
12
+ it 'should not parse an empty string' do
13
+ parser.parse("").should be nil
14
+ end
11
15
  end
@@ -7,7 +7,6 @@ describe Parsing::PitchNode do
7
7
  'C4' => C4,
8
8
  'Db2' => Db2,
9
9
  'C#2' => Db2,
10
- 'Db2' => Db2,
11
10
  'F7' => F7,
12
11
  'B1' => B1,
13
12
  "Bb22" => Pitch.new(octave: 22, semitone: 10),
@@ -14,7 +14,7 @@ describe ValueComputer do
14
14
  end
15
15
 
16
16
  it "should always return default value if no changes are given" do
17
- [ValueComputer::DOMAIN_MIN, -1000, 0, 1, 5, 100, 10000, ValueComputer::DOMAIN_MAX].each do |offset|
17
+ [ValueComputer::DOMAIN_MIN, -1000, 0, 1, 5, 100, 10000].each do |offset|
18
18
  @comp.at(offset).should eq(0.5)
19
19
  end
20
20
  end
@@ -38,7 +38,7 @@ describe ValueComputer do
38
38
  end
39
39
 
40
40
  it "should be at the second value for all time after" do
41
- @comp.at(ValueComputer::DOMAIN_MAX).should eq(0.6)
41
+ @comp.at(100_000).should eq(0.6)
42
42
  end
43
43
  end
44
44
 
@@ -70,12 +70,12 @@ describe GlissandoConverter do
70
70
  describe '.glissando_elements' do
71
71
  before :all do
72
72
  @dur = Rational(3,2)
73
- @acc = false
74
- @els = GlissandoConverter.glissando_elements(C4,A4,@dur,@acc)
73
+ @att = Attack::TENUTO
74
+ @els = GlissandoConverter.glissando_elements(C4,A4,@dur,@att)
75
75
  end
76
76
 
77
- it 'should return an array of LegatoElement objects' do
78
- @els.each {|el| el.should be_a LegatoElement }
77
+ it 'should return an array of NoteSequence::Element objects' do
78
+ @els.each {|el| el.should be_a NoteSequence::Element }
79
79
  end
80
80
 
81
81
  it 'should split up duration among elements' do
@@ -83,11 +83,11 @@ describe GlissandoConverter do
83
83
  sum.should eq(@dur)
84
84
  end
85
85
 
86
- it 'should set accented as given' do
87
- els = GlissandoConverter.glissando_elements(C4,A4,1,false)
88
- els.each {|el| el.accented.should eq(false) }
89
- els = GlissandoConverter.glissando_elements(C4,A4,1,true)
90
- els.each {|el| el.accented.should eq(true) }
86
+ it 'should set attack as given for each element' do
87
+ els = GlissandoConverter.glissando_elements(C4,A4,1,Attack::TENUTO)
88
+ els.each {|el| el.attack.should eq(Attack::TENUTO) }
89
+ els = GlissandoConverter.glissando_elements(C4,A4,1,Attack::ACCENT)
90
+ els.each {|el| el.attack.should eq(Attack::ACCENT) }
91
91
  end
92
92
  end
93
93
  end