musicality 0.8.0 → 0.9.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 +4 -4
- data/ChangeLog.md +27 -1
- data/README.md +153 -10
- data/bin/collidify +102 -0
- data/bin/lilify +57 -29
- data/bin/midify +64 -24
- data/bin/musicality +39 -0
- data/examples/composition/auto_counterpoint.rb +4 -5
- data/examples/composition/part_generator.rb +8 -2
- data/examples/composition/scale_exercise.rb +1 -1
- data/examples/notation/notes.rb +27 -0
- data/examples/notation/parts.rb +51 -0
- data/examples/notation/scores.rb +38 -0
- data/examples/notation/twinkle.rb +34 -0
- data/examples/notation/twinkle.score +33 -0
- data/lib/musicality.rb +46 -11
- data/lib/musicality/composition/dsl/score_dsl.rb +2 -2
- data/lib/musicality/composition/dsl/score_methods.rb +10 -7
- data/lib/musicality/notation/conversion/change_conversion.rb +1 -1
- data/lib/musicality/notation/conversion/note_time_converter.rb +6 -23
- data/lib/musicality/notation/conversion/score_conversion.rb +15 -15
- data/lib/musicality/notation/conversion/score_converter.rb +50 -67
- data/lib/musicality/notation/model/articulations.rb +3 -2
- data/lib/musicality/notation/model/change.rb +15 -6
- data/lib/musicality/notation/model/dynamics.rb +11 -8
- data/lib/musicality/notation/model/instrument.rb +61 -0
- data/lib/musicality/notation/model/instruments.rb +111 -0
- data/lib/musicality/notation/model/key.rb +137 -0
- data/lib/musicality/notation/model/keys.rb +37 -0
- data/lib/musicality/notation/model/link.rb +6 -19
- data/lib/musicality/notation/model/mark.rb +43 -0
- data/lib/musicality/notation/model/marks.rb +11 -0
- data/lib/musicality/notation/model/meter.rb +4 -0
- data/lib/musicality/notation/model/note.rb +42 -28
- data/lib/musicality/notation/model/part.rb +18 -5
- data/lib/musicality/notation/model/pitch.rb +13 -4
- data/lib/musicality/notation/model/score.rb +104 -66
- data/lib/musicality/notation/model/symbols.rb +16 -11
- data/lib/musicality/notation/parsing/articulation_parsing.rb +38 -38
- data/lib/musicality/notation/parsing/articulation_parsing.treetop +14 -14
- data/lib/musicality/notation/parsing/link_parsing.rb +6 -6
- data/lib/musicality/notation/parsing/link_parsing.treetop +3 -3
- data/lib/musicality/notation/parsing/mark_parsing.rb +138 -0
- data/lib/musicality/notation/parsing/mark_parsing.treetop +31 -0
- data/lib/musicality/notation/parsing/note_node.rb +19 -12
- data/lib/musicality/notation/parsing/note_parsing.rb +218 -87
- data/lib/musicality/notation/parsing/note_parsing.treetop +9 -5
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +7 -2
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +1 -1
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +6 -4
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +1 -1
- data/lib/musicality/notation/util/function.rb +41 -18
- data/lib/musicality/packable.rb +156 -0
- data/lib/musicality/performance/conversion/glissando_converter.rb +2 -2
- data/lib/musicality/performance/conversion/note_sequence_extractor.rb +223 -70
- data/lib/musicality/performance/conversion/portamento_converter.rb +5 -2
- data/lib/musicality/performance/conversion/score_collator.rb +70 -64
- data/lib/musicality/performance/midi/midi_events.rb +3 -3
- data/lib/musicality/performance/midi/midi_settings.rb +127 -0
- data/lib/musicality/performance/midi/midi_util.rb +8 -2
- data/lib/musicality/performance/midi/part_sequencer.rb +19 -18
- data/lib/musicality/performance/midi/score_sequencer.rb +13 -9
- data/lib/musicality/performance/midi/score_sequencing.rb +5 -5
- data/lib/musicality/performance/model/attack.rb +8 -0
- data/lib/musicality/performance/model/duration_functions.rb +23 -0
- data/lib/musicality/performance/model/note_sequence.rb +52 -95
- data/lib/musicality/performance/model/separation.rb +10 -0
- data/lib/musicality/performance/supercollider/add_actions.rb +13 -0
- data/lib/musicality/performance/supercollider/bundle.rb +18 -0
- data/lib/musicality/performance/supercollider/conductor.rb +125 -0
- data/lib/musicality/performance/supercollider/group.rb +71 -0
- data/lib/musicality/performance/supercollider/message.rb +26 -0
- data/lib/musicality/performance/supercollider/node.rb +122 -0
- data/lib/musicality/performance/supercollider/performer.rb +123 -0
- data/lib/musicality/performance/supercollider/score_conducting.rb +17 -0
- data/lib/musicality/performance/supercollider/server.rb +8 -0
- data/lib/musicality/performance/supercollider/synth.rb +43 -0
- data/lib/musicality/performance/supercollider/synthdef.rb +57 -0
- data/lib/musicality/performance/supercollider/synthdef_settings.rb +23 -0
- data/lib/musicality/performance/supercollider/synthdefs.rb +1654 -0
- data/lib/musicality/{composition/model/pitch_class.rb → pitch_class.rb} +1 -1
- data/lib/musicality/{composition/model/pitch_classes.rb → pitch_classes.rb} +9 -9
- data/lib/musicality/printing/lilypond/clef.rb +12 -0
- data/lib/musicality/printing/lilypond/key_engraving.rb +9 -0
- data/lib/musicality/printing/lilypond/lilypond_settings.rb +105 -0
- data/lib/musicality/printing/lilypond/meter_engraving.rb +1 -1
- data/lib/musicality/printing/lilypond/note_engraving.rb +112 -30
- data/lib/musicality/printing/lilypond/part_engraver.rb +114 -3
- data/lib/musicality/printing/lilypond/pitch_class_engraving.rb +22 -0
- data/lib/musicality/printing/lilypond/pitch_engraving.rb +2 -15
- data/lib/musicality/printing/lilypond/score_engraver.rb +44 -73
- data/lib/musicality/printing/lilypond/score_engraving.rb +3 -3
- data/lib/musicality/project/create_tasks.rb +31 -0
- data/lib/musicality/project/file_cleaner.rb +19 -0
- data/lib/musicality/project/file_raker.rb +107 -0
- data/lib/musicality/project/load_config.rb +43 -0
- data/lib/musicality/project/project.rb +64 -0
- data/lib/musicality/version.rb +1 -1
- data/musicality.gemspec +3 -0
- data/spec/composition/util/random_sampler_spec.rb +1 -1
- data/spec/notation/conversion/measure_note_map_spec.rb +1 -1
- data/spec/notation/conversion/note_time_converter_spec.rb +5 -85
- data/spec/notation/conversion/score_conversion_spec.rb +6 -41
- data/spec/notation/conversion/score_converter_spec.rb +19 -137
- data/spec/notation/model/change_spec.rb +55 -0
- data/spec/notation/model/key_spec.rb +171 -0
- data/spec/notation/model/link_spec.rb +34 -5
- data/spec/notation/model/meter_spec.rb +15 -0
- data/spec/notation/model/note_spec.rb +33 -27
- data/spec/notation/model/part_spec.rb +53 -4
- data/spec/notation/model/pitch_spec.rb +15 -0
- data/spec/notation/model/score_spec.rb +64 -72
- data/spec/notation/parsing/link_nodes_spec.rb +3 -3
- data/spec/notation/parsing/link_parsing_spec.rb +6 -6
- data/spec/notation/parsing/note_node_spec.rb +34 -9
- data/spec/notation/parsing/note_parsing_spec.rb +11 -9
- data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +4 -0
- data/spec/notation/parsing/pitch_node_spec.rb +0 -1
- data/spec/notation/util/value_computer_spec.rb +2 -2
- data/spec/performance/conversion/glissando_converter_spec.rb +9 -9
- data/spec/performance/conversion/note_sequence_extractor_spec.rb +48 -53
- data/spec/performance/conversion/portamento_converter_spec.rb +11 -9
- data/spec/performance/conversion/score_collator_spec.rb +59 -63
- data/spec/performance/midi/midi_util_spec.rb +22 -8
- data/spec/performance/midi/part_sequencer_spec.rb +2 -2
- data/spec/performance/midi/score_sequencer_spec.rb +12 -10
- data/spec/performance/midi/score_sequencing_spec.rb +2 -2
- data/spec/performance/model/note_sequence_spec.rb +41 -134
- data/spec/printing/note_engraving_spec.rb +204 -0
- data/spec/printing/score_engraver_spec.rb +40 -0
- data/spec/spec_helper.rb +1 -0
- metadata +69 -23
- data/examples/notation/hip.rb +0 -32
- data/examples/notation/missed_connection.rb +0 -26
- data/examples/notation/song1.rb +0 -33
- data/examples/notation/song2.rb +0 -32
- data/lib/musicality/notation/model/links.rb +0 -11
- data/lib/musicality/notation/packing/change_packing.rb +0 -56
- data/lib/musicality/notation/packing/part_packing.rb +0 -31
- data/lib/musicality/notation/packing/score_packing.rb +0 -123
- data/lib/musicality/performance/model/note_attacks.rb +0 -19
- data/lib/musicality/performance/util/note_linker.rb +0 -28
- data/spec/notation/packing/change_packing_spec.rb +0 -304
- data/spec/notation/packing/part_packing_spec.rb +0 -66
- data/spec/notation/packing/score_packing_spec.rb +0 -255
- 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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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
|
262
|
-
|
263
|
-
|
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
|
270
|
-
|
271
|
-
|
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
|
-
|
289
|
-
|
290
|
-
|
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 '
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
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[
|
8
|
-
(LINK_SYMBOLS[
|
9
|
-
(LINK_SYMBOLS[
|
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[
|
9
|
-
@parser.should parse(LINK_SYMBOLS[
|
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[
|
13
|
-
@parser.should parse(LINK_SYMBOLS[
|
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[
|
17
|
-
@parser.should parse(LINK_SYMBOLS[
|
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
|
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
|
-
'
|
38
|
-
"56/33B1
|
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
|
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
|
64
|
-
'/2C2,D2,E2
|
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,
|
67
|
-
'56/33B1,B2,B3,B4,
|
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
|
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
|
13
|
-
'with accent' => ['/4C2
|
14
|
-
'with links' => ['/2C2
|
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
|
17
|
+
'(3/4D2~','5/8F2;G2.','/8Db4:Db5','/3G4;B4_'],
|
17
18
|
'with multiple pitches + articulation + links + accent' => [
|
18
|
-
'5/4D2
|
19
|
+
'5/4D2~,G4:A4,C3;D3.','5/8F2~,B4:A4_'],
|
19
20
|
}
|
20
21
|
invalid_cases = {
|
21
|
-
'duration +
|
22
|
-
'duration +
|
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
|
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|
|
@@ -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
|
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(
|
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
|
-
@
|
74
|
-
@els = GlissandoConverter.glissando_elements(C4,A4,@dur,@
|
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
|
78
|
-
@els.each {|el| el.should be_a
|
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
|
87
|
-
els = GlissandoConverter.glissando_elements(C4,A4,1,
|
88
|
-
els.each {|el| el.
|
89
|
-
els = GlissandoConverter.glissando_elements(C4,A4,1,
|
90
|
-
els.each {|el| el.
|
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
|