musicality 0.3.0 → 0.5.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 +8 -1
- data/bin/midify +3 -4
- data/examples/composition/auto_counterpoint.rb +53 -0
- data/examples/composition/part_generator.rb +51 -0
- data/examples/composition/scale_exercise.rb +41 -0
- data/examples/{hip.rb → notation/hip.rb} +1 -1
- data/examples/{missed_connection.rb → notation/missed_connection.rb} +1 -1
- data/examples/{song1.rb → notation/song1.rb} +1 -1
- data/examples/{song2.rb → notation/song2.rb} +1 -1
- data/lib/musicality.rb +34 -4
- data/lib/musicality/composition/generation/counterpoint_generator.rb +153 -0
- data/lib/musicality/composition/generation/random_rhythm_generator.rb +39 -0
- data/lib/musicality/composition/model/pitch_class.rb +33 -0
- data/lib/musicality/composition/model/pitch_classes.rb +22 -0
- data/lib/musicality/composition/model/scale.rb +34 -0
- data/lib/musicality/composition/model/scale_class.rb +37 -0
- data/lib/musicality/composition/model/scale_classes.rb +91 -0
- data/lib/musicality/composition/note_generation.rb +31 -0
- data/lib/musicality/composition/transposition.rb +8 -0
- data/lib/musicality/composition/util/adding_sequence.rb +24 -0
- data/lib/musicality/composition/util/biinfinite_sequence.rb +130 -0
- data/lib/musicality/composition/util/compound_sequence.rb +44 -0
- data/lib/musicality/composition/util/probabilities.rb +20 -0
- data/lib/musicality/composition/util/random_sampler.rb +26 -0
- data/lib/musicality/composition/util/repeating_sequence.rb +24 -0
- data/lib/musicality/errors.rb +2 -0
- data/lib/musicality/notation/conversion/score_conversion.rb +1 -1
- data/lib/musicality/notation/conversion/score_converter.rb +3 -3
- data/lib/musicality/notation/model/link.rb +26 -24
- data/lib/musicality/notation/model/links.rb +11 -0
- data/lib/musicality/notation/model/note.rb +14 -15
- data/lib/musicality/notation/model/part.rb +3 -3
- data/lib/musicality/notation/model/pitch.rb +8 -0
- data/lib/musicality/notation/model/score.rb +70 -44
- data/lib/musicality/notation/model/symbols.rb +22 -0
- data/lib/musicality/notation/packing/score_packing.rb +2 -3
- data/lib/musicality/notation/parsing/articulation_parsing.rb +4 -4
- data/lib/musicality/notation/parsing/articulation_parsing.treetop +2 -2
- data/lib/musicality/notation/parsing/link_nodes.rb +2 -14
- data/lib/musicality/notation/parsing/link_parsing.rb +9 -107
- data/lib/musicality/notation/parsing/link_parsing.treetop +4 -12
- data/lib/musicality/notation/parsing/note_node.rb +23 -21
- data/lib/musicality/notation/parsing/note_parsing.rb +70 -70
- data/lib/musicality/notation/parsing/note_parsing.treetop +6 -3
- data/lib/musicality/notation/parsing/pitch_node.rb +4 -2
- data/lib/musicality/performance/conversion/score_collator.rb +3 -3
- data/lib/musicality/performance/midi/midi_util.rb +13 -6
- data/lib/musicality/performance/midi/score_sequencing.rb +17 -0
- data/lib/musicality/printing/lilypond/errors.rb +5 -0
- data/lib/musicality/printing/lilypond/meter_engraving.rb +11 -0
- data/lib/musicality/printing/lilypond/note_engraving.rb +53 -0
- data/lib/musicality/printing/lilypond/part_engraver.rb +12 -0
- data/lib/musicality/printing/lilypond/pitch_engraving.rb +30 -0
- data/lib/musicality/printing/lilypond/score_engraver.rb +78 -0
- data/lib/musicality/version.rb +1 -1
- data/spec/composition/generation/random_rhythm_generator_spec.rb +50 -0
- data/spec/composition/model/pitch_class_spec.rb +75 -0
- data/spec/composition/model/pitch_classes_spec.rb +24 -0
- data/spec/composition/model/scale_class_spec.rb +98 -0
- data/spec/composition/model/scale_spec.rb +110 -0
- data/spec/composition/note_generation_spec.rb +113 -0
- data/spec/composition/transposition_spec.rb +17 -0
- data/spec/composition/util/adding_sequence_spec.rb +176 -0
- data/spec/composition/util/compound_sequence_spec.rb +50 -0
- data/spec/composition/util/probabilities_spec.rb +39 -0
- data/spec/composition/util/random_sampler_spec.rb +47 -0
- data/spec/composition/util/repeating_sequence_spec.rb +151 -0
- data/spec/notation/conversion/score_conversion_spec.rb +3 -3
- data/spec/notation/conversion/score_converter_spec.rb +24 -24
- data/spec/notation/model/link_spec.rb +27 -25
- data/spec/notation/model/note_spec.rb +9 -6
- data/spec/notation/model/pitch_spec.rb +24 -1
- data/spec/notation/model/score_spec.rb +57 -16
- data/spec/notation/packing/score_packing_spec.rb +134 -206
- data/spec/notation/parsing/articulation_parsing_spec.rb +1 -8
- data/spec/notation/parsing/convenience_methods_spec.rb +1 -1
- data/spec/notation/parsing/link_nodes_spec.rb +3 -4
- data/spec/notation/parsing/link_parsing_spec.rb +10 -4
- data/spec/notation/parsing/note_node_spec.rb +8 -7
- data/spec/notation/parsing/note_parsing_spec.rb +9 -12
- data/spec/performance/conversion/score_collator_spec.rb +14 -14
- data/spec/performance/midi/midi_util_spec.rb +26 -0
- data/spec/performance/midi/score_sequencer_spec.rb +1 -1
- metadata +57 -12
- data/lib/musicality/notation/model/program.rb +0 -53
- data/lib/musicality/notation/packing/program_packing.rb +0 -16
- data/spec/notation/model/program_spec.rb +0 -50
- data/spec/notation/packing/program_packing_spec.rb +0 -33
@@ -120,18 +120,21 @@ describe Note do
|
|
120
120
|
[[C2],{}],
|
121
121
|
[[A5,D6],{ A5 => Link::Tie.new }],
|
122
122
|
[[C5,E6,Gb2],{ C5 => Link::Glissando.new(D5) }],
|
123
|
-
[[A5,D6],{ A5 => Link::Legato.new(B5), D6 => Link::Slur.new(E6) }],
|
124
123
|
[[C5,E6,Gb2],{ C5 => Link::Portamento.new(D5), Gb2 => Link::Tie.new }],
|
125
124
|
]
|
126
125
|
|
127
126
|
notes = []
|
128
127
|
durations.each do |d|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
128
|
+
pitches_links_sets.each do |pitches_links_set|
|
129
|
+
pitches,links = pitches_links_set
|
130
|
+
if pitches.any?
|
131
|
+
articulations.each do |art|
|
132
|
+
[true,false].each do |acc|
|
133
|
+
notes.push Note.new(d, pitches, articulation: art, links: links, accented: acc)
|
134
|
+
end
|
134
135
|
end
|
136
|
+
else
|
137
|
+
notes.push Note.new(d)
|
135
138
|
end
|
136
139
|
end
|
137
140
|
end
|
@@ -62,13 +62,36 @@ describe Pitch do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
describe '#transpose' do
|
65
|
-
it 'should
|
65
|
+
it 'should make a new pitch, adding the given interval to total semitones' do
|
66
66
|
[0,1,2,5,12,13,-1,-2,-5,-12,-13].each do |interval|
|
67
67
|
pitch = Eb3.transpose(interval)
|
68
|
+
pitch.should_not be Eb3
|
68
69
|
pitch.diff(Eb3).should eq(interval)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
73
|
+
|
74
|
+
describe '#+' do
|
75
|
+
it 'should produce same result as #transpose' do
|
76
|
+
[0,1,2,5,12,13,-1,-2,-5,-12,-13].each do |interval|
|
77
|
+
pitch = Eb3 + interval
|
78
|
+
pitch.should_not be Eb3
|
79
|
+
pitch2 = Eb3.transpose(interval)
|
80
|
+
pitch.should eq(pitch2)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#-' do
|
86
|
+
it 'should produce same result as #transpose, with negative interval' do
|
87
|
+
[0,1,2,5,12,13,-1,-2,-5,-12,-13].each do |interval|
|
88
|
+
pitch = Eb3 - interval
|
89
|
+
pitch.should_not be Eb3
|
90
|
+
pitch2 = Eb3.transpose(-interval)
|
91
|
+
pitch.should eq(pitch2)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
72
95
|
|
73
96
|
describe '.total_semitones' do
|
74
97
|
it 'should convert to whole/fractional total semitones value' do
|
@@ -4,14 +4,14 @@ describe Score do
|
|
4
4
|
describe '#collated?' do
|
5
5
|
context 'has program with more than one segment' do
|
6
6
|
it 'should return false' do
|
7
|
-
score = Score.new(program:
|
7
|
+
score = Score.new(program: [0..2,0..2])
|
8
8
|
score.collated?.should be false
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
context 'has program with 0 segments' do
|
13
13
|
it 'should return false' do
|
14
|
-
score = Score.new(program:
|
14
|
+
score = Score.new(program: [])
|
15
15
|
score.collated?.should be false
|
16
16
|
end
|
17
17
|
end
|
@@ -19,14 +19,14 @@ describe Score do
|
|
19
19
|
context 'has program with 1 segment' do
|
20
20
|
context 'program segment starts at 0' do
|
21
21
|
it 'should return true' do
|
22
|
-
score = Score.new(program:
|
22
|
+
score = Score.new(program: [0..2])
|
23
23
|
score.collated?.should be true
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'program segment does not start at 0' do
|
28
28
|
it 'should return false' do
|
29
|
-
score = Score.new(program:
|
29
|
+
score = Score.new(program: [1..2])
|
30
30
|
score.collated?.should be false
|
31
31
|
end
|
32
32
|
end
|
@@ -48,6 +48,32 @@ describe Score do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
describe '#valid?' do
|
53
|
+
context 'non-Range objects' do
|
54
|
+
it 'should return false' do
|
55
|
+
Score.new(program: [1,2,3]).should_not be_valid
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'increasing, positive segments' do
|
60
|
+
it 'should return true' do
|
61
|
+
Score.new(program: [0..2,1..2,0..4]).should be_valid
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'decreasing, positive segments' do
|
66
|
+
it 'should return false' do
|
67
|
+
Score.new(program: [2..0,2..1,04..0]).should be_invalid
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'increasing, negative segments' do
|
72
|
+
it 'should return false' do
|
73
|
+
Score.new(program: [-1..2,-2..0,-2..2]).should be_invalid
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
51
77
|
end
|
52
78
|
|
53
79
|
describe Score::Measured do
|
@@ -55,7 +81,7 @@ describe Score::Measured do
|
|
55
81
|
it 'should use empty containers for parameters not given' do
|
56
82
|
s = Score::Measured.new(FOUR_FOUR,120)
|
57
83
|
s.parts.should be_empty
|
58
|
-
s.program.
|
84
|
+
s.program.should be_empty
|
59
85
|
end
|
60
86
|
|
61
87
|
it 'should assign given parameters' do
|
@@ -65,7 +91,7 @@ describe Score::Measured do
|
|
65
91
|
s.start_tempo.should eq 120
|
66
92
|
|
67
93
|
parts = { "piano (LH)" => Samples::SAMPLE_PART }
|
68
|
-
program =
|
94
|
+
program = [0...0.75, 0...0.75]
|
69
95
|
mcs = { 1 => Change::Immediate.new(THREE_FOUR) }
|
70
96
|
tcs = { 1 => Change::Immediate.new(100) }
|
71
97
|
|
@@ -132,6 +158,21 @@ describe Score::Measured do
|
|
132
158
|
).measures_long.should eq(3.5)
|
133
159
|
end
|
134
160
|
end
|
161
|
+
|
162
|
+
context 'given specific note duration' do
|
163
|
+
it 'should change the given note duration to measures' do
|
164
|
+
score = Score::Measured.new(TWO_FOUR, 120,
|
165
|
+
meter_changes: {
|
166
|
+
2 => Change::Immediate.new(FOUR_FOUR),
|
167
|
+
4 => Change::Immediate.new(SIX_EIGHT)
|
168
|
+
})
|
169
|
+
|
170
|
+
{ 1 => 2, 1.5 => 2.5, 2 => 3, 3 => 4, 3.75 => 5
|
171
|
+
}.each do |note_dur, meas_dur|
|
172
|
+
score.measures_long(note_dur).should eq(meas_dur)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
135
176
|
end
|
136
177
|
|
137
178
|
describe '#valid?' do
|
@@ -142,7 +183,7 @@ describe Score::Measured do
|
|
142
183
|
'valid meter changes' => [ FOUR_FOUR, 120,
|
143
184
|
:meter_changes => { 1 => Change::Immediate.new(TWO_FOUR) } ],
|
144
185
|
'valid part' => [ FOUR_FOUR, 120, :parts => { "piano" => Samples::SAMPLE_PART }],
|
145
|
-
'valid program' => [ FOUR_FOUR, 120, :program =>
|
186
|
+
'valid program' => [ FOUR_FOUR, 120, :program => [0..2,0..2] ]
|
146
187
|
}.each do |context_str,args|
|
147
188
|
context context_str do
|
148
189
|
it 'should return true' do
|
@@ -165,7 +206,7 @@ describe Score::Measured do
|
|
165
206
|
'non-integer meter change offset' => [ FOUR_FOUR, 120,
|
166
207
|
:meter_changes => { 1.1 => Change::Immediate.new(TWO_FOUR) } ],
|
167
208
|
'invalid part' => [ FOUR_FOUR, 120, :parts => { "piano" => Part.new(-0.1) }],
|
168
|
-
'invalid program' => [ FOUR_FOUR, 120, :program =>
|
209
|
+
'invalid program' => [ FOUR_FOUR, 120, :program => [2..0] ],
|
169
210
|
}.each do |context_str,args|
|
170
211
|
context context_str do
|
171
212
|
it 'should return false' do
|
@@ -181,7 +222,7 @@ describe Score::Unmeasured do
|
|
181
222
|
it 'should use empty containers for parameters not given' do
|
182
223
|
s = Score::Unmeasured.new(30)
|
183
224
|
s.parts.should be_empty
|
184
|
-
s.program.
|
225
|
+
s.program.should be_empty
|
185
226
|
end
|
186
227
|
|
187
228
|
it 'should assign given parameters' do
|
@@ -189,7 +230,7 @@ describe Score::Unmeasured do
|
|
189
230
|
s.start_tempo.should eq(30)
|
190
231
|
|
191
232
|
parts = { "piano (LH)" => Samples::SAMPLE_PART }
|
192
|
-
program =
|
233
|
+
program = [0...0.75, 0...0.75]
|
193
234
|
tcs = { 1 => Change::Immediate.new(40) }
|
194
235
|
|
195
236
|
s = Score::Unmeasured.new(30,
|
@@ -218,7 +259,7 @@ describe Score::Unmeasured do
|
|
218
259
|
'valid tempo changes' => [ 30,
|
219
260
|
:tempo_changes => { 1 => Change::Gradual.linear(40, 2), 2 => Change::Immediate.new(50) } ],
|
220
261
|
'valid part' => [ 30, :parts => { "piano" => Samples::SAMPLE_PART }],
|
221
|
-
'valid program' => [ 30, :program =>
|
262
|
+
'valid program' => [ 30, :program => [0..2,0..2] ]
|
222
263
|
}.each do |context_str,args|
|
223
264
|
context context_str do
|
224
265
|
it 'should return true' do
|
@@ -233,7 +274,7 @@ describe Score::Unmeasured do
|
|
233
274
|
'tempo change value is not a valid value' => [ 30,
|
234
275
|
:tempo_changes => { 1 => Change::Gradual.linear(-1,1) } ],
|
235
276
|
'invalid part' => [ 30, :parts => { "piano" => Part.new(-0.1) }],
|
236
|
-
'invalid program' => [ 30, :program =>
|
277
|
+
'invalid program' => [ 30, :program => [2..0] ],
|
237
278
|
}.each do |context_str,args|
|
238
279
|
context context_str do
|
239
280
|
it 'should return false' do
|
@@ -249,12 +290,12 @@ describe Score::Timed do
|
|
249
290
|
it 'should use empty containers for parameters not given' do
|
250
291
|
s = Score::Timed.new
|
251
292
|
s.parts.should be_empty
|
252
|
-
s.program.
|
293
|
+
s.program.should be_empty
|
253
294
|
end
|
254
295
|
|
255
296
|
it 'should assign given parameters' do
|
256
297
|
parts = { "piano (LH)" => Samples::SAMPLE_PART }
|
257
|
-
program =
|
298
|
+
program = [0...0.75, 0...0.75]
|
258
299
|
|
259
300
|
s = Score::Timed.new(parts: parts, program: program)
|
260
301
|
s.parts.should eq parts
|
@@ -274,7 +315,7 @@ describe Score::Timed do
|
|
274
315
|
describe '#valid?' do
|
275
316
|
{
|
276
317
|
'valid part' => [ :parts => { "piano" => Samples::SAMPLE_PART }],
|
277
|
-
'valid program' => [ :program =>
|
318
|
+
'valid program' => [ :program => [0..2,0..2] ]
|
278
319
|
}.each do |context_str,args|
|
279
320
|
context context_str do
|
280
321
|
it 'should return true' do
|
@@ -285,7 +326,7 @@ describe Score::Timed do
|
|
285
326
|
|
286
327
|
{
|
287
328
|
'invalid part' => [ :parts => { "piano" => Part.new(-0.1) }],
|
288
|
-
'invalid program' => [ :program =>
|
329
|
+
'invalid program' => [ :program => [2..0] ],
|
289
330
|
}.each do |context_str,args|
|
290
331
|
context context_str do
|
291
332
|
it 'should return false' do
|
@@ -2,17 +2,26 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
|
3
3
|
measured_score = Score::Measured.new(FOUR_FOUR,120) do |s|
|
4
4
|
s.meter_changes[1] = Change::Immediate.new(THREE_FOUR)
|
5
|
-
s.
|
5
|
+
s.meter_changes[7] = Change::Immediate.new(SIX_EIGHT)
|
6
|
+
|
7
|
+
s.tempo_changes[2] = Change::Immediate.new(100)
|
8
|
+
s.tempo_changes[4] = Change::Gradual.linear(70,2)
|
9
|
+
s.tempo_changes[9] = Change::Gradual.sigmoid(99,5).trim(2,2)
|
10
|
+
|
11
|
+
s.program += [0...2, 0...2,2...4,0...2]
|
6
12
|
s.parts["lead"] = Part.new(Dynamics::MF) do |p|
|
7
13
|
riff = "/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
|
8
|
-
/6Bb3 /4 /12Db4= /4Db4= /
|
14
|
+
/6Bb3 /4 /12Db4= /4Db4= /8Db4= /8C4".to_notes
|
9
15
|
p.notes = riff + riff.map {|n| n.transpose(2) }
|
16
|
+
p.dynamic_changes[1] = Change::Gradual.linear(Dynamics::F,2)
|
10
17
|
end
|
11
18
|
|
12
19
|
s.parts["bass"] = Part.new(Dynamics::MP) do |p|
|
13
20
|
riff = "/6Bb2 /4 /3Ab2 /6F2 /12Ab2 \
|
14
21
|
/6Bb2 /4 /3Ab2 /4Ab2".to_notes
|
15
22
|
p.notes = riff + riff.map {|n| n.transpose(2) }
|
23
|
+
p.dynamic_changes[1] = Change::Immediate.new(Dynamics::F)
|
24
|
+
p.dynamic_changes[3] = Change::Gradual.sigmoid(Dynamics::PP,4).trim(1,1)
|
16
25
|
end
|
17
26
|
end
|
18
27
|
|
@@ -26,203 +35,162 @@ timed_score = Score::Timed.new do |s|
|
|
26
35
|
s.parts = measured_score.parts
|
27
36
|
end
|
28
37
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
describe '#pack' do
|
36
|
-
it 'should return a hash' do
|
37
|
-
@h.should be_a Hash
|
38
|
+
[ measured_score, unmeasured_score, timed_score ].each do |score|
|
39
|
+
describe score.class do
|
40
|
+
before :all do
|
41
|
+
@score = score
|
42
|
+
@h = @score.pack
|
38
43
|
end
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
@h.should
|
45
|
+
describe '#pack' do
|
46
|
+
it 'should return a hash' do
|
47
|
+
@h.should be_a Hash
|
43
48
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
it 'should pack start meter as a string' do
|
51
|
-
@h['start_meter'].should be_a String
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should pack meter changes as whatver type Change#pack returns' do
|
55
|
-
@h['meter_changes'].each do |offset,packed_v|
|
56
|
-
change_v = @score.meter_changes[offset]
|
57
|
-
t = change_v.pack.class
|
58
|
-
packed_v.should be_a t
|
49
|
+
|
50
|
+
it 'should return a hash with keys: "type","parts", and "program"' do
|
51
|
+
["type","parts","program"].each do |key|
|
52
|
+
@h.should have_key(key)
|
53
|
+
end
|
59
54
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
packed_v["end_value"].should be_a String
|
55
|
+
|
56
|
+
it 'should pack program as an array with same size' do
|
57
|
+
@h['program'].should be_a Array
|
58
|
+
@h['program'].size.should eq(@score.program.size)
|
65
59
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@h['start_tempo'].should be_a Numeric
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should pack tempo changes as whatver type Change#pack returns' do
|
73
|
-
@h['tempo_changes'].each do |offset,packed_v|
|
74
|
-
change_v = @score.tempo_changes[offset]
|
75
|
-
t = change_v.pack.class
|
76
|
-
packed_v.should be_a t
|
60
|
+
|
61
|
+
it 'should pack program segments as strings' do
|
62
|
+
@h['program'].each {|x| x.should be_a String }
|
77
63
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
64
|
+
|
65
|
+
it 'should pack parts as hash' do
|
66
|
+
@h['parts'].should be_a Hash
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should pack parts as whatever Part#pack returns' do
|
70
|
+
@score.parts.each do |name,part|
|
71
|
+
packing = part.pack
|
72
|
+
@h['parts'][name].should eq packing
|
73
|
+
end
|
83
74
|
end
|
84
75
|
end
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
packing = part.pack
|
102
|
-
@h['parts'][name].should eq packing
|
77
|
+
describe '.unpack' do
|
78
|
+
before :all do
|
79
|
+
@score2 = score.class.unpack @h
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return a #{score.class}" do
|
83
|
+
@score2.should be_a score.class
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should successfuly unpack the parts' do
|
87
|
+
@score2.parts.should eq @score.parts
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should successfuly unpack the program' do
|
91
|
+
@score2.program.should eq @score.program
|
103
92
|
end
|
104
93
|
end
|
105
94
|
end
|
106
|
-
|
107
|
-
|
95
|
+
end
|
96
|
+
|
97
|
+
[ measured_score, unmeasured_score ].each do |score|
|
98
|
+
describe score.class do
|
108
99
|
before :all do
|
109
|
-
@
|
110
|
-
|
111
|
-
|
112
|
-
it 'should return a Score::Measured' do
|
113
|
-
@score2.should be_a Score::Measured
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should successfuly unpack the parts' do
|
117
|
-
@score2.parts.should eq @score.parts
|
100
|
+
@score = score
|
101
|
+
@h = @score.pack
|
118
102
|
end
|
119
103
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
it 'should successfuly unpack the start tempo' do
|
125
|
-
@score2.start_tempo.should eq @score.start_tempo
|
126
|
-
end
|
104
|
+
describe '#pack' do
|
105
|
+
it 'should return a hash with keys: "start_tempo" and "tempo_changes"' do
|
106
|
+
["start_tempo","tempo_changes"].each {|key| @h.should have_key(key) }
|
107
|
+
end
|
127
108
|
|
128
|
-
|
129
|
-
|
130
|
-
|
109
|
+
it 'should pack start tempo as numeric' do
|
110
|
+
@h['start_tempo'].should be_a Numeric
|
111
|
+
end
|
131
112
|
|
132
|
-
|
133
|
-
|
113
|
+
it 'should pack tempo changes as a hash' do
|
114
|
+
@h['tempo_changes'].should be_a Hash
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should pack tempo changes values using Change#pack' do
|
118
|
+
@h['tempo_changes'].each do |offset,packed_v|
|
119
|
+
change = @score.tempo_changes[offset]
|
120
|
+
packed_v.should eq(change.pack)
|
121
|
+
end
|
122
|
+
end
|
134
123
|
end
|
135
|
-
|
136
|
-
|
137
|
-
|
124
|
+
|
125
|
+
describe '.unpack' do
|
126
|
+
before :all do
|
127
|
+
@score2 = score.class.unpack @h
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should successfuly unpack the start tempo' do
|
131
|
+
@score2.start_tempo.should eq @score.start_tempo
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should successfuly unpack the tempo changes' do
|
135
|
+
@score2.tempo_changes.should eq @score.tempo_changes
|
136
|
+
end
|
138
137
|
end
|
139
138
|
end
|
140
139
|
end
|
141
140
|
|
142
|
-
describe Score::
|
141
|
+
describe Score::Measured do
|
143
142
|
before :all do
|
144
|
-
@score =
|
143
|
+
@score = measured_score
|
145
144
|
@h = @score.pack
|
146
145
|
end
|
147
146
|
|
148
|
-
describe '#pack' do
|
149
|
-
it 'should return a hash' do
|
150
|
-
@h.should
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'should return a hash with keys: "type","parts", "program", ...' do
|
154
|
-
["type","parts","start_tempo","tempo_changes","program"].each do |key|
|
155
|
-
@h.should have_key(key)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'should set "type" key to "Unmeasured"' do
|
160
|
-
@h["type"].should eq("Unmeasured")
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'should pack start tempo as numeric' do
|
164
|
-
@h['start_tempo'].should be_a Numeric
|
147
|
+
describe '#pack' do
|
148
|
+
it 'should return a hash with keys: "start_meter" and "meter_changes"' do
|
149
|
+
["start_meter","meter_changes"].each { |key| @h.should have_key(key) }
|
165
150
|
end
|
166
151
|
|
167
|
-
it 'should
|
168
|
-
@h[
|
169
|
-
change_v = @score.tempo_changes[offset]
|
170
|
-
t = change_v.pack.class
|
171
|
-
packed_v.should be_a t
|
172
|
-
end
|
152
|
+
it 'should set "type" key to "Measured"' do
|
153
|
+
@h["type"].should eq("Measured")
|
173
154
|
end
|
174
155
|
|
175
|
-
it 'should pack
|
176
|
-
@h['
|
177
|
-
packed_v[0].should be_a Numeric
|
178
|
-
end
|
156
|
+
it 'should pack start meter as a string' do
|
157
|
+
@h['start_meter'].should be_a String
|
179
158
|
end
|
180
159
|
|
181
|
-
it 'should pack
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
it 'should pack program segments as strings' do
|
187
|
-
@h['program'].each {|x| x.should be_a String }
|
160
|
+
it 'should pack meter changes values using Change#pack(:with => :to_s)' do
|
161
|
+
@h['meter_changes'].each do |offset,packed_v|
|
162
|
+
change = @score.meter_changes[offset]
|
163
|
+
packed_v.should eq(change.pack(:with => :to_s))
|
164
|
+
end
|
188
165
|
end
|
189
166
|
|
190
|
-
it 'should pack
|
191
|
-
@h['
|
192
|
-
|
193
|
-
|
194
|
-
it 'should pack parts as whatever Part#pack returns' do
|
195
|
-
@score.parts.each do |name,part|
|
196
|
-
packing = part.pack
|
197
|
-
@h['parts'][name].should eq packing
|
167
|
+
it 'should pack meter change end values as strings' do
|
168
|
+
@h['meter_changes'].each do |offset,packed_v|
|
169
|
+
packed_v["end_value"].should be_a String
|
198
170
|
end
|
199
|
-
end
|
171
|
+
end
|
200
172
|
end
|
201
173
|
|
202
174
|
describe '.unpack' do
|
203
175
|
before :all do
|
204
|
-
@score2 = Score::
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'should return a Score::Unmeasured' do
|
208
|
-
@score2.should be_a Score::Unmeasured
|
209
|
-
end
|
210
|
-
|
211
|
-
it 'should successfuly unpack the parts' do
|
212
|
-
@score2.parts.should eq @score.parts
|
176
|
+
@score2 = Score::Measured.unpack @h
|
213
177
|
end
|
214
178
|
|
215
|
-
it 'should successfuly unpack the start
|
216
|
-
@score2.
|
179
|
+
it 'should successfuly unpack the start meter' do
|
180
|
+
@score2.start_meter.should eq @score.start_meter
|
217
181
|
end
|
218
182
|
|
219
|
-
it 'should successfuly unpack the
|
220
|
-
@score2.
|
183
|
+
it 'should successfuly unpack the meter changes' do
|
184
|
+
@score2.meter_changes.should eq @score.meter_changes
|
221
185
|
end
|
186
|
+
end
|
187
|
+
end
|
222
188
|
|
223
|
-
|
224
|
-
|
225
|
-
|
189
|
+
describe Score::Unmeasured do
|
190
|
+
describe '#pack' do
|
191
|
+
it 'should set "type" key to "Unmeasured"' do
|
192
|
+
unmeasured_score.pack["type"].should eq("Unmeasured")
|
193
|
+
end
|
226
194
|
end
|
227
195
|
end
|
228
196
|
|
@@ -233,57 +201,9 @@ describe Score::Timed do
|
|
233
201
|
end
|
234
202
|
|
235
203
|
describe '#pack' do
|
236
|
-
it 'should return a hash' do
|
237
|
-
@h.should be_a Hash
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'should return a hash with keys: "type","parts", and "program"' do
|
241
|
-
["type","parts","program"].each do |key|
|
242
|
-
@h.should have_key(key)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
204
|
it 'should set "type" key to "Timed"' do
|
247
205
|
@h["type"].should eq("Timed")
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'should pack program as whatever type Program#pack returns' do
|
251
|
-
t = @score.program.pack.class
|
252
|
-
@h['program'].should be_a t
|
253
|
-
end
|
254
|
-
|
255
|
-
it 'should pack program segments as strings' do
|
256
|
-
@h['program'].each {|x| x.should be_a String }
|
257
|
-
end
|
258
|
-
|
259
|
-
it 'should pack parts as hash' do
|
260
|
-
@h['parts'].should be_a Hash
|
261
|
-
end
|
262
|
-
|
263
|
-
it 'should pack parts as whatever Part#pack returns' do
|
264
|
-
@score.parts.each do |name,part|
|
265
|
-
packing = part.pack
|
266
|
-
@h['parts'][name].should eq packing
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
describe '.unpack' do
|
272
|
-
before :all do
|
273
|
-
@score2 = Score::Timed.unpack @h
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'should return a Score::Timed' do
|
277
|
-
@score2.should be_a Score::Timed
|
278
|
-
end
|
279
|
-
|
280
|
-
it 'should successfuly unpack the parts' do
|
281
|
-
@score2.parts.should eq @score.parts
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'should successfuly unpack the program' do
|
285
|
-
@score2.program.should eq @score.program
|
286
|
-
end
|
206
|
+
end
|
287
207
|
end
|
288
208
|
end
|
289
209
|
|
@@ -291,10 +211,18 @@ describe Score do
|
|
291
211
|
describe '.unpack' do
|
292
212
|
[ timed_score, unmeasured_score, measured_score ].each do |score|
|
293
213
|
context "given packing from a #{score.class} object" do
|
214
|
+
before :all do
|
215
|
+
@packing = score.pack
|
216
|
+
@score2 = Score.unpack(@packing)
|
217
|
+
end
|
218
|
+
|
294
219
|
it "should return a #{score.class} object equal to original" do
|
295
|
-
score2
|
296
|
-
score2.should
|
297
|
-
|
220
|
+
@score2.should be_a score.class
|
221
|
+
@score2.should eq(score)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should return a score equal to what #{score.class}.unpack returns" do
|
225
|
+
@score2.should eq(score.class.unpack(@packing))
|
298
226
|
end
|
299
227
|
end
|
300
228
|
end
|