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,66 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe Part do
4
- before :all do
5
- @p = Part.new(
6
- Dynamics::MP,
7
- notes: Note.split_parse("/4Bb2 /8 /8F3= /2F3 /4Bb2 /8 /8F3= /2F3"),
8
- dynamic_changes: {
9
- 1 => Change::Immediate.new(Dynamics::PP),
10
- 2 => Change::Gradual.linear(Dynamics::FF, 2.0)
11
- }
12
- )
13
-
14
- @h = @p.pack
15
- end
16
-
17
- describe '#pack' do
18
- it 'should produce a hash' do
19
- @h.should be_a Hash
20
- end
21
-
22
- it 'should return a hash with keys: "notes", "start_dynamic", and "dynamic_changes"' do
23
- @h.keys.should include("notes")
24
- @h.keys.should include("start_dynamic")
25
- @h.keys.should include("dynamic_changes")
26
- end
27
-
28
- it 'should pack notes into a string' do
29
- @h['notes'].should be_a String
30
- end
31
-
32
- it 'should pack start dynamic as plain numeric value' do
33
- @h['start_dynamic'].should be_a Numeric
34
- end
35
-
36
- it 'should pack dynamic changes as whatver type Change#pack returns' do
37
- @h['dynamic_changes'].each do |offset,packed_v|
38
- change_v = @p.dynamic_changes[offset]
39
- t = change_v.pack.class
40
- packed_v.should be_a t
41
- end
42
- end
43
- end
44
-
45
- describe '.unpack' do
46
- before :all do
47
- @p2 = Part.unpack @h
48
- end
49
-
50
- it 'should return a Part' do
51
- @p2.should be_a Part
52
- end
53
-
54
- it 'should successfuly unpack the notes' do
55
- @p2.notes.should eq @p.notes
56
- end
57
-
58
- it 'should successfuly unpack the start dynamic' do
59
- @p2.start_dynamic.should eq @p.start_dynamic
60
- end
61
-
62
- it 'should successfuly unpack the dynamic changes' do
63
- @p2.dynamic_changes.should eq @p.dynamic_changes
64
- end
65
- end
66
- end
@@ -1,255 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- measured_score = Score::Measured.new(FOUR_FOUR,120) do |s|
4
- s.title "The best song ever"
5
- s.composer "James T."
6
-
7
- s.meter_changes[1] = Change::Immediate.new(THREE_FOUR)
8
- s.meter_changes[7] = Change::Immediate.new(SIX_EIGHT)
9
-
10
- s.tempo_changes[2] = Change::Immediate.new(100)
11
- s.tempo_changes[4] = Change::Gradual.linear(70,2)
12
- s.tempo_changes[9] = Change::Gradual.sigmoid(99,5).trim(2,2)
13
-
14
- s.program += [0...2, 0...2,2...4,0...2]
15
- s.parts["lead"] = Part.new(Dynamics::MF) do |p|
16
- riff = "/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
17
- /6Bb3 /4 /12Db4= /4Db4= /8Db4= /8C4".to_notes
18
- p.notes = riff + riff.map {|n| n.transpose(2) }
19
- p.dynamic_changes[1] = Change::Gradual.linear(Dynamics::F,2)
20
- end
21
-
22
- s.parts["bass"] = Part.new(Dynamics::MP) do |p|
23
- riff = "/6Bb2 /4 /3Ab2 /6F2 /12Ab2 \
24
- /6Bb2 /4 /3Ab2 /4Ab2".to_notes
25
- p.notes = riff + riff.map {|n| n.transpose(2) }
26
- p.dynamic_changes[1] = Change::Immediate.new(Dynamics::F)
27
- p.dynamic_changes[3] = Change::Gradual.sigmoid(Dynamics::PP,4).trim(1,1)
28
- end
29
- end
30
-
31
- unmeasured_score = Score::Unmeasured.new(30) do |s|
32
- s.program = measured_score.program
33
- s.parts = measured_score.parts
34
- s.title measured_score.title
35
- s.composer measured_score.composer
36
- end
37
-
38
- timed_score = Score::Timed.new do |s|
39
- s.program = measured_score.program
40
- s.parts = measured_score.parts
41
- s.title measured_score.title
42
- s.composer measured_score.composer
43
- end
44
-
45
- [ measured_score, unmeasured_score, timed_score ].each do |score|
46
- describe score.class do
47
- before :all do
48
- @score = score
49
- @h = @score.pack
50
- end
51
-
52
- describe '#pack' do
53
- it 'should return a hash' do
54
- @h.should be_a Hash
55
- end
56
-
57
- it 'should return a hash with keys: "type","parts", and "program"' do
58
- ["type","parts","program"].each do |key|
59
- @h.should have_key(key)
60
- end
61
- end
62
-
63
- it 'should pack program as an array with same size' do
64
- @h['program'].should be_a Array
65
- @h['program'].size.should eq(@score.program.size)
66
- end
67
-
68
- it 'should pack program segments as strings' do
69
- @h['program'].each {|x| x.should be_a String }
70
- end
71
-
72
- it 'should pack parts as hash' do
73
- @h['parts'].should be_a Hash
74
- end
75
-
76
- it 'should pack parts as whatever Part#pack returns' do
77
- @score.parts.each do |name,part|
78
- packing = part.pack
79
- @h['parts'][name].should eq packing
80
- end
81
- end
82
-
83
- it 'should add title to packing' do
84
- @h.should have_key "title"
85
- @h["title"].should eq @score.title
86
- end
87
-
88
- it 'should add composer to packing' do
89
- @h.should have_key "composer"
90
- @h["composer"].should eq @score.composer
91
- end
92
- end
93
-
94
- describe '.unpack' do
95
- before :all do
96
- @score2 = score.class.unpack @h
97
- end
98
-
99
- it "should return a #{score.class}" do
100
- @score2.should be_a score.class
101
- end
102
-
103
- it 'should successfuly unpack the parts' do
104
- @score2.parts.should eq @score.parts
105
- end
106
-
107
- it 'should successfuly unpack the program' do
108
- @score2.program.should eq @score.program
109
- end
110
-
111
- it 'should successfuly unpack the title' do
112
- @score2.title.should eq @score.title
113
- end
114
-
115
- it 'should successfuly unpack the composer' do
116
- @score2.composer.should eq @score.composer
117
- end
118
- end
119
- end
120
- end
121
-
122
- [ measured_score, unmeasured_score ].each do |score|
123
- describe score.class do
124
- before :all do
125
- @score = score
126
- @h = @score.pack
127
- end
128
-
129
- describe '#pack' do
130
- it 'should return a hash with keys: "start_tempo" and "tempo_changes"' do
131
- ["start_tempo","tempo_changes"].each {|key| @h.should have_key(key) }
132
- end
133
-
134
- it 'should pack start tempo as numeric' do
135
- @h['start_tempo'].should be_a Numeric
136
- end
137
-
138
- it 'should pack tempo changes as a hash' do
139
- @h['tempo_changes'].should be_a Hash
140
- end
141
-
142
- it 'should pack tempo changes values using Change#pack' do
143
- @h['tempo_changes'].each do |offset,packed_v|
144
- change = @score.tempo_changes[offset]
145
- packed_v.should eq(change.pack)
146
- end
147
- end
148
- end
149
-
150
- describe '.unpack' do
151
- before :all do
152
- @score2 = score.class.unpack @h
153
- end
154
-
155
- it 'should successfuly unpack the start tempo' do
156
- @score2.start_tempo.should eq @score.start_tempo
157
- end
158
-
159
- it 'should successfuly unpack the tempo changes' do
160
- @score2.tempo_changes.should eq @score.tempo_changes
161
- end
162
- end
163
- end
164
- end
165
-
166
- describe Score::Measured do
167
- before :all do
168
- @score = measured_score
169
- @h = @score.pack
170
- end
171
-
172
- describe '#pack' do
173
- it 'should return a hash with keys: "start_meter" and "meter_changes"' do
174
- ["start_meter","meter_changes"].each { |key| @h.should have_key(key) }
175
- end
176
-
177
- it 'should set "type" key to "Measured"' do
178
- @h["type"].should eq("Measured")
179
- end
180
-
181
- it 'should pack start meter as a string' do
182
- @h['start_meter'].should be_a String
183
- end
184
-
185
- it 'should pack meter changes values using Change#pack(:with => :to_s)' do
186
- @h['meter_changes'].each do |offset,packed_v|
187
- change = @score.meter_changes[offset]
188
- packed_v.should eq(change.pack(:with => :to_s))
189
- end
190
- end
191
-
192
- it 'should pack meter change end values as strings' do
193
- @h['meter_changes'].each do |offset,packed_v|
194
- packed_v["end_value"].should be_a String
195
- end
196
- end
197
- end
198
-
199
- describe '.unpack' do
200
- before :all do
201
- @score2 = Score::Measured.unpack @h
202
- end
203
-
204
- it 'should successfuly unpack the start meter' do
205
- @score2.start_meter.should eq @score.start_meter
206
- end
207
-
208
- it 'should successfuly unpack the meter changes' do
209
- @score2.meter_changes.should eq @score.meter_changes
210
- end
211
- end
212
- end
213
-
214
- describe Score::Unmeasured do
215
- describe '#pack' do
216
- it 'should set "type" key to "Unmeasured"' do
217
- unmeasured_score.pack["type"].should eq("Unmeasured")
218
- end
219
- end
220
- end
221
-
222
- describe Score::Timed do
223
- before :all do
224
- @score = timed_score
225
- @h = @score.pack
226
- end
227
-
228
- describe '#pack' do
229
- it 'should set "type" key to "Timed"' do
230
- @h["type"].should eq("Timed")
231
- end
232
- end
233
- end
234
-
235
- describe Score do
236
- describe '.unpack' do
237
- [ timed_score, unmeasured_score, measured_score ].each do |score|
238
- context "given packing from a #{score.class} object" do
239
- before :all do
240
- @packing = score.pack
241
- @score2 = Score.unpack(@packing)
242
- end
243
-
244
- it "should return a #{score.class} object equal to original" do
245
- @score2.should be_a score.class
246
- @score2.should eq(score)
247
- end
248
-
249
- it "should return a score equal to what #{score.class}.unpack returns" do
250
- @score2.should eq(score.class.unpack(@packing))
251
- end
252
- end
253
- end
254
- end
255
- end
@@ -1,68 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe NoteLinker do
4
- describe '.find_unlinked_pitches' do
5
- {
6
- 'note has no pitches' => [Note.quarter,[]],
7
- 'note has 1 pitch, no links' => [Note.quarter([C4]),[C4]],
8
- 'note has 2 pitches, no links' => [Note.quarter([C4,E4]),[C4,E4]],
9
- 'note has 1 pitch, which is linked' => [Note.quarter([C4], links: {C4 => Link::Tie.new} ),[]],
10
- 'note has 2 pitch, 1 of which is linked' => [Note.quarter([C4,E4], links: {C4 => Link::Tie.new} ),[E4]],
11
- 'note has 2 pitches, both of which are linked' => [Note.quarter([C4,E4], links: {C4 => Link::Tie.new, E4 => Link::Tie.new} ),[]],
12
- 'note has 1 pitch, and 1 unrelated link' => [Note.quarter([C4], links: {D4 => Link::Tie.new}),[C4]],
13
- 'note has 2 pitch, and 2 unrelated links' => [Note.quarter([C4,E4], links: {D4 => Link::Tie.new, F4 => Link::Tie.new}),[C4,E4]],
14
- }.each do |descr,given_expected|
15
- context descr do
16
- given, expected = given_expected
17
- it "should return #{expected}" do
18
- actual = NoteLinker.find_unlinked_pitches(given)
19
- actual.should eq(expected)
20
- end
21
- end
22
- end
23
- end
24
-
25
- describe '.find_untargeted_pitches' do
26
- {
27
- 'note has no pitches, next note has no pitches' => [Note.quarter,Note.quarter,[]],
28
- 'note has no pitches, next note has 3 pitch' => [Note.quarter,Note.quarter([C3,E3,F3]),[C3,E3,F3]],
29
- 'note has 3 pitches + no links, next note has 2 pitches' => [Note.quarter([C3,E3,F3]),Note.quarter([D2,F2]),[D2,F2]],
30
- 'note has 1 pitch + 1 unrelated link, next note has 1 pitch' => [Note.quarter([C3], links: {C3 => Link::Slur.new(C2)}),Note.quarter([D2]),[D2]],
31
- 'note has 1 pitch + 1 related link, next note has 1 pitch' => [Note.quarter([C3], links: {C3 => Link::Slur.new(D2)}),Note.quarter([D2]),[]],
32
- 'note has 2 pitches + 2 related link, next note has 2 pitches' => [Note.quarter([C3,E3], links: {C3 => Link::Slur.new(D2), E3 => Link::Slur.new(E2) }),Note.quarter([D2,E2]),[]],
33
- 'note has 2 pitches + 1 unrelated link, next note has 2 pitches' => [Note.quarter([C3,E3], links: {C3 => Link::Slur.new(D2), E3 => Link::Slur.new(F2) }),Note.quarter([D2,E2]),[E2]],
34
- }.each do |descr,given_expected|
35
- context descr do
36
- given_note, given_next_note, expected = given_expected
37
- it "should return #{expected}" do
38
- actual = NoteLinker.find_untargeted_pitches(given_note, given_next_note)
39
- actual.should eq(expected)
40
- end
41
- end
42
- end
43
- end
44
-
45
- describe '.fully_link' do
46
- [
47
- [ Note.quarter([C4,E4,G4]), Note.quarter, Note.quarter([C4,E4,G4]) ],
48
- [ Note.quarter([G4]), Note.quarter([A4]), Note.quarter([G4], links: {G4 => Link::Slur.new(A4)}) ],
49
- [
50
- Note.quarter([G4,A4]),
51
- Note.quarter([A4]),
52
- Note.quarter([G4,A4], links: {A4 => Link::Slur.new(A4)})
53
- ],
54
- [
55
- Note.quarter([G4,A4], links: {A4 => Link::Slur.new(B4)}),
56
- Note.quarter([A4,B4]),
57
- Note.quarter([G4,A4], links: {G4 => Link::Slur.new(A4), A4 => Link::Slur.new(B4)})
58
- ],
59
- ].each do |note,next_note,modified|
60
- context "given note: #{note.to_s}, next_note: #{next_note.to_s}" do
61
- it "should modifiy note to equal #{modified.to_s}" do
62
- NoteLinker.fully_link(note, next_note, Link::Slur)
63
- note.should eq(modified)
64
- end
65
- end
66
- end
67
- end
68
- end