musicality 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +8 -1
  3. data/bin/midify +3 -4
  4. data/examples/composition/auto_counterpoint.rb +53 -0
  5. data/examples/composition/part_generator.rb +51 -0
  6. data/examples/composition/scale_exercise.rb +41 -0
  7. data/examples/{hip.rb → notation/hip.rb} +1 -1
  8. data/examples/{missed_connection.rb → notation/missed_connection.rb} +1 -1
  9. data/examples/{song1.rb → notation/song1.rb} +1 -1
  10. data/examples/{song2.rb → notation/song2.rb} +1 -1
  11. data/lib/musicality.rb +34 -4
  12. data/lib/musicality/composition/generation/counterpoint_generator.rb +153 -0
  13. data/lib/musicality/composition/generation/random_rhythm_generator.rb +39 -0
  14. data/lib/musicality/composition/model/pitch_class.rb +33 -0
  15. data/lib/musicality/composition/model/pitch_classes.rb +22 -0
  16. data/lib/musicality/composition/model/scale.rb +34 -0
  17. data/lib/musicality/composition/model/scale_class.rb +37 -0
  18. data/lib/musicality/composition/model/scale_classes.rb +91 -0
  19. data/lib/musicality/composition/note_generation.rb +31 -0
  20. data/lib/musicality/composition/transposition.rb +8 -0
  21. data/lib/musicality/composition/util/adding_sequence.rb +24 -0
  22. data/lib/musicality/composition/util/biinfinite_sequence.rb +130 -0
  23. data/lib/musicality/composition/util/compound_sequence.rb +44 -0
  24. data/lib/musicality/composition/util/probabilities.rb +20 -0
  25. data/lib/musicality/composition/util/random_sampler.rb +26 -0
  26. data/lib/musicality/composition/util/repeating_sequence.rb +24 -0
  27. data/lib/musicality/errors.rb +2 -0
  28. data/lib/musicality/notation/conversion/score_conversion.rb +1 -1
  29. data/lib/musicality/notation/conversion/score_converter.rb +3 -3
  30. data/lib/musicality/notation/model/link.rb +26 -24
  31. data/lib/musicality/notation/model/links.rb +11 -0
  32. data/lib/musicality/notation/model/note.rb +14 -15
  33. data/lib/musicality/notation/model/part.rb +3 -3
  34. data/lib/musicality/notation/model/pitch.rb +8 -0
  35. data/lib/musicality/notation/model/score.rb +70 -44
  36. data/lib/musicality/notation/model/symbols.rb +22 -0
  37. data/lib/musicality/notation/packing/score_packing.rb +2 -3
  38. data/lib/musicality/notation/parsing/articulation_parsing.rb +4 -4
  39. data/lib/musicality/notation/parsing/articulation_parsing.treetop +2 -2
  40. data/lib/musicality/notation/parsing/link_nodes.rb +2 -14
  41. data/lib/musicality/notation/parsing/link_parsing.rb +9 -107
  42. data/lib/musicality/notation/parsing/link_parsing.treetop +4 -12
  43. data/lib/musicality/notation/parsing/note_node.rb +23 -21
  44. data/lib/musicality/notation/parsing/note_parsing.rb +70 -70
  45. data/lib/musicality/notation/parsing/note_parsing.treetop +6 -3
  46. data/lib/musicality/notation/parsing/pitch_node.rb +4 -2
  47. data/lib/musicality/performance/conversion/score_collator.rb +3 -3
  48. data/lib/musicality/performance/midi/midi_util.rb +13 -6
  49. data/lib/musicality/performance/midi/score_sequencing.rb +17 -0
  50. data/lib/musicality/printing/lilypond/errors.rb +5 -0
  51. data/lib/musicality/printing/lilypond/meter_engraving.rb +11 -0
  52. data/lib/musicality/printing/lilypond/note_engraving.rb +53 -0
  53. data/lib/musicality/printing/lilypond/part_engraver.rb +12 -0
  54. data/lib/musicality/printing/lilypond/pitch_engraving.rb +30 -0
  55. data/lib/musicality/printing/lilypond/score_engraver.rb +78 -0
  56. data/lib/musicality/version.rb +1 -1
  57. data/spec/composition/generation/random_rhythm_generator_spec.rb +50 -0
  58. data/spec/composition/model/pitch_class_spec.rb +75 -0
  59. data/spec/composition/model/pitch_classes_spec.rb +24 -0
  60. data/spec/composition/model/scale_class_spec.rb +98 -0
  61. data/spec/composition/model/scale_spec.rb +110 -0
  62. data/spec/composition/note_generation_spec.rb +113 -0
  63. data/spec/composition/transposition_spec.rb +17 -0
  64. data/spec/composition/util/adding_sequence_spec.rb +176 -0
  65. data/spec/composition/util/compound_sequence_spec.rb +50 -0
  66. data/spec/composition/util/probabilities_spec.rb +39 -0
  67. data/spec/composition/util/random_sampler_spec.rb +47 -0
  68. data/spec/composition/util/repeating_sequence_spec.rb +151 -0
  69. data/spec/notation/conversion/score_conversion_spec.rb +3 -3
  70. data/spec/notation/conversion/score_converter_spec.rb +24 -24
  71. data/spec/notation/model/link_spec.rb +27 -25
  72. data/spec/notation/model/note_spec.rb +9 -6
  73. data/spec/notation/model/pitch_spec.rb +24 -1
  74. data/spec/notation/model/score_spec.rb +57 -16
  75. data/spec/notation/packing/score_packing_spec.rb +134 -206
  76. data/spec/notation/parsing/articulation_parsing_spec.rb +1 -8
  77. data/spec/notation/parsing/convenience_methods_spec.rb +1 -1
  78. data/spec/notation/parsing/link_nodes_spec.rb +3 -4
  79. data/spec/notation/parsing/link_parsing_spec.rb +10 -4
  80. data/spec/notation/parsing/note_node_spec.rb +8 -7
  81. data/spec/notation/parsing/note_parsing_spec.rb +9 -12
  82. data/spec/performance/conversion/score_collator_spec.rb +14 -14
  83. data/spec/performance/midi/midi_util_spec.rb +26 -0
  84. data/spec/performance/midi/score_sequencer_spec.rb +1 -1
  85. metadata +57 -12
  86. data/lib/musicality/notation/model/program.rb +0 -53
  87. data/lib/musicality/notation/packing/program_packing.rb +0 -16
  88. data/spec/notation/model/program_spec.rb +0 -50
  89. data/spec/notation/packing/program_packing_spec.rb +0 -33
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe CompoundSequence do
4
+ seqs = [ AddingSequence.new([1,1,0,2,-1]),
5
+ RepeatingSequence.new([0,1,0,5,-13]) ]
6
+
7
+ describe "#at" do
8
+ context 'given single offset' do
9
+ [ :+, :* ].each do |sym|
10
+ cseq = CompoundSequence.new(sym,seqs)
11
+ context "given #{sym} as combine method" do
12
+ it "should get a value from each sequence using #at and combine using #{sym}" do
13
+ [0, 1, -5, 33].each do |offset|
14
+ vals = seqs.map {|s| s.at(offset) }
15
+ val = vals[1..-1].inject(vals.first,sym)
16
+ val2 = cseq.send(:at,offset)
17
+ val2.should eq(val)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ { :at => [[-5,1,33,2,0,-11], [-3,-2,-1,0,1,2,-3,-2,-1]],
26
+ :take => [ 0, 5, 10, 13 ],
27
+ :take_back => [ 0, 2, 6, 15 ],
28
+ :over => [ 0..12, -3...5, -10..-3 ]
29
+ }.each do |method,args|
30
+ describe "##{method}" do
31
+ [ :+, :* ].each do |sym|
32
+ cseq = CompoundSequence.new(sym,seqs)
33
+ context "given #{sym} as combine method" do
34
+ it "should get values from each sequence using #{method} and combine each set of values using #{sym}" do
35
+ args.each do |arg|
36
+ enums = seqs.map {|s| s.send(method,arg) }
37
+ n = arg.is_a?(Fixnum) ? arg : arg.size
38
+ vals = Array.new(n) do |i|
39
+ _vals = enums.map {|e| e.next }
40
+ _vals[1..-1].inject(_vals.first,sym)
41
+ end
42
+ vals2 = cseq.send(method,arg).to_a
43
+ vals2.should eq(vals)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'set'
4
+
5
+ describe Probabilities do
6
+ [:random,:uniform].each do |class_method|
7
+ describe ".#{class_method}" do
8
+ it 'should return array of given size, with sum of 1' do
9
+ (1..10).step(2) do |n|
10
+ 5.times do
11
+ x = Probabilities.send(class_method,n)
12
+ x.size.should eq(n)
13
+ x.inject(0,:+).should eq(1)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '.random' do
21
+ it 'should return array of all-different values' do
22
+ x = Probabilities.random(100)
23
+ Set.new(x).size.should eq(100)
24
+ end
25
+ end
26
+
27
+ describe '.uniform' do
28
+ it 'should return array of all (or all-but-one) same values' do
29
+ [2,6,10,33,78,100].each do |n|
30
+ x = Probabilities.uniform(n)
31
+ y = Set.new(x)
32
+ (y.size == 1 || y.size == 2).should eq(true)
33
+ if y.size == 2
34
+ y.entries[0].should be_within(1e-9).of(y.entries[1])
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe RandomSampler do
4
+ describe '#initialize' do
5
+ context 'given probabilities that do not add up to 1' do
6
+ it 'should raise ArgumentError' do
7
+ [ [[1,2],[0.4,0.59]],
8
+ [[1/2.to_r, 1/4.to_r],[0.5,0.5001]] ].each do |vals,probs|
9
+ expect { RandomSampler.new(vals,probs) }.to raise_error(ArgumentError)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ before :all do
16
+ @samplers = [
17
+ [[ 1/8.to_r, 1/4.to_r, 1/2.to_r ], [0.25, 0.5, 0.25 ]],
18
+ [[ 1/6.to_r, 1/4.to_r, 1/3.to_r, 1/12.to_r], [0.25,0.25,0.25,0.25]]
19
+ ].map {|vals,probs| RandomSampler.new(vals,probs) }
20
+ end
21
+
22
+ describe '#sample' do
23
+ context 'given no arg' do
24
+ it 'should return a random value, according to the probabilities given at initialization' do
25
+ @samplers.each do |sampler|
26
+ counts = Hash[ sampler.values.map {|val| [val,0] } ]
27
+ 1000.times { counts[sampler.sample] += 1 }
28
+ sampler.values.each_with_index do |val,i|
29
+ count = counts[val]
30
+ tgt_prob = sampler.probabilities[i]
31
+ (count / 1000.to_f).should be_within(0.05).of(tgt_prob)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'given number of samples to take' do
38
+ it 'should return array with the given number of samples' do
39
+ @samplers.each do |sampler|
40
+ [1,2,5,10].each do |n|
41
+ sampler.sample(n).size.should eq(n)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,151 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe RepeatingSequence do
4
+ describe '#initialize' do
5
+ context 'given an empty pattern' do
6
+ it 'should raise EmptyError' do
7
+ expect do
8
+ RepeatingSequence.new([])
9
+ end.to raise_error(EmptyError)
10
+ end
11
+ end
12
+ end
13
+
14
+ describe '#pattern_size' do
15
+ it 'should return the pattern size' do
16
+ RepeatingSequence.new([1,2,3,4,5]).pattern_size.should eq(5)
17
+ end
18
+ end
19
+
20
+ before :all do
21
+ @pattern = [2,1,5,4,3]
22
+ @seq = RepeatingSequence.new(@pattern)
23
+ end
24
+
25
+ describe '#at' do
26
+ context 'given single offset' do
27
+ it 'should module index into pattern using given offset' do
28
+ n = @pattern.size
29
+ (0..n*2).each do |i|
30
+ @seq.at(i).should eq(@pattern[i%n])
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'given array of offsets' do
36
+ context 'not given block' do
37
+ it 'should return enumerator' do
38
+ @seq.at([1,2,3]).should be_a Enumerator
39
+ end
40
+ end
41
+
42
+ context 'given block' do
43
+ it 'should yield sequence value for each offset' do
44
+ [ (0..@seq.pattern_size).to_a, (-@seq.pattern_size..0).to_a,
45
+ [-5,11,0,-33,2,15,-8] ].each do |offsets|
46
+ @seq.at(offsets).each_with_index do |val,i|
47
+ val.should eq(@seq.at(offsets[i]))
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#take' do
56
+ context 'given negative integer' do
57
+ it 'should raise NegativeError' do
58
+ expect { @seq.take(-1) }.to raise_error(NegativeError)
59
+ expect { @seq.take(-10) }.to raise_error(NegativeError)
60
+ end
61
+ end
62
+
63
+ context 'given 0' do
64
+ it 'should return empty array' do
65
+ @seq.take(0).to_a.should eq([])
66
+ end
67
+ end
68
+
69
+ context 'given positive integer' do
70
+ context 'given block' do
71
+ it 'should yield the given number of pattern elements in forward direction (repeating as necessary)' do
72
+ i = 0
73
+ @seq.take(@pattern.size*2+3) do |n|
74
+ n.should eq(@seq.at(i))
75
+ i += 1
76
+ end
77
+ end
78
+ end
79
+
80
+ context 'no block given' do
81
+ it 'should return an enumerator' do
82
+ @seq.take(20).should be_a Enumerator
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ describe '#take_back' do
89
+ context 'given negative integer' do
90
+ it 'should raise NegativeError' do
91
+ expect { @seq.take_back(-1) }.to raise_error(NegativeError)
92
+ expect { @seq.take_back(-10) }.to raise_error(NegativeError)
93
+ end
94
+ end
95
+
96
+ context 'given 0' do
97
+ it 'should return empty array' do
98
+ @seq.take_back(0).to_a.should eq([])
99
+ end
100
+ end
101
+
102
+ context 'given positive integer' do
103
+ context 'given block' do
104
+ it 'should yield the given number of pattern elements in backward direction (repeating as necessary)' do
105
+ i, m = 0, @pattern.size*2+3
106
+ @seq.take_back(m) do |n|
107
+ n.should eq(@seq.at(i-1))
108
+ i -= 1
109
+ end
110
+ (-i).should eq(m)
111
+ end
112
+ end
113
+
114
+ context 'no block given' do
115
+ it 'should return an enumerator' do
116
+ @seq.take_back(20).should be_a Enumerator
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '#over' do
123
+ context 'given empty (invalid) range' do
124
+ it 'should raise EmptyError' do
125
+ [ 3...-2, 0...0, 5..2, -3..-5 ].each do |range|
126
+ expect { @seq.over(range) }.to raise_error(EmptyError)
127
+ end
128
+ end
129
+ end
130
+
131
+ context 'given range over positive indices' do
132
+ it 'should return seq values at all offsets in range' do
133
+ [ 0..0, 0..2, 1...10, 4..17 ].each do |range|
134
+ vals = @seq.over(range).to_a
135
+ vals2 = range.map {|i| @seq.at(i) }
136
+ vals.should eq(vals2)
137
+ end
138
+ end
139
+ end
140
+
141
+ context 'given negative min and/or max' do
142
+ it 'should return seq values at all offsets in range' do
143
+ [ -5..2, -10..-7, -1...1 ].each do |range|
144
+ vals = @seq.over(range).to_a
145
+ vals2 = range.map {|i| @seq.at(i) }
146
+ vals.should eq(vals2)
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -13,7 +13,7 @@ describe Score::Measured do
13
13
  }
14
14
  )
15
15
  }
16
- @prog = Program.new([0...3,4...7,1...20,17..."45/2".to_r])
16
+ @prog = [0...3,4...7,1...20,17..."45/2".to_r]
17
17
  tcs = {
18
18
  0 => Change::Immediate.new(120),
19
19
  4 => Change::Gradual.linear(60,2),
@@ -63,7 +63,7 @@ describe Score::Measured do
63
63
  end
64
64
 
65
65
  it 'should include offsets from program segments' do
66
- @score.program.segments.each do |seg|
66
+ @score.program.each do |seg|
67
67
  @moffs.should include(seg.first)
68
68
  @moffs.should include(seg.last)
69
69
  end
@@ -153,7 +153,7 @@ describe Score::Unmeasured do
153
153
  }
154
154
  )
155
155
  }
156
- @prog = Program.new([0...3,4...7,1...20,17..."45/2".to_r])
156
+ @prog = [0...3,4...7,1...20,17..."45/2".to_r]
157
157
  tcs = {
158
158
  0 => Change::Immediate.new(120),
159
159
  4 => Change::Gradual.linear(60,2),
@@ -74,32 +74,32 @@ describe ScoreConverter::Measured do
74
74
 
75
75
  describe '#convert_program' do
76
76
  before :each do
77
- @prog = Program.new([0...4,2...5])
77
+ @prog = [0...4,2...5]
78
78
  @score = Score::Measured.new(FOUR_FOUR, 120, program: @prog)
79
79
  @converter = ScoreConverter::Measured.new(@score,200)
80
80
  end
81
81
 
82
- it 'shuld return Program with same number of segments' do
82
+ it 'shuld return array with same size' do
83
83
  prog = @converter.convert_program
84
- prog.should be_a Program
85
- prog.segments.size.should eq(@score.program.segments.size)
84
+ prog.should be_a Array
85
+ prog.size.should eq(@score.program.size)
86
86
  end
87
87
 
88
88
  it 'should convert program segments offsets from measure-based to note-based' do
89
89
  prog = ScoreConverter::Measured.new(@score,200).convert_program
90
- prog.segments.size.should eq(2)
91
- prog.segments[0].first.should eq(0)
92
- prog.segments[0].last.should eq(8)
93
- prog.segments[1].first.should eq(4)
94
- prog.segments[1].last.should eq(10)
90
+ prog.size.should eq(2)
91
+ prog[0].first.should eq(0)
92
+ prog[0].last.should eq(8)
93
+ prog[1].first.should eq(4)
94
+ prog[1].last.should eq(10)
95
95
 
96
96
  @score.start_meter = THREE_FOUR
97
97
  prog = ScoreConverter::Measured.new(@score,200).convert_program
98
- prog.segments.size.should eq(2)
99
- prog.segments[0].first.should eq(0)
100
- prog.segments[0].last.should eq(6)
101
- prog.segments[1].first.should eq(3)
102
- prog.segments[1].last.should eq(7.5)
98
+ prog.size.should eq(2)
99
+ prog[0].first.should eq(0)
100
+ prog[0].last.should eq(6)
101
+ prog[1].first.should eq(3)
102
+ prog[1].last.should eq(7.5)
103
103
  end
104
104
  end
105
105
 
@@ -111,7 +111,7 @@ describe ScoreConverter::Measured do
111
111
  end
112
112
 
113
113
  it 'should use output from convert_program' do
114
- prog = Program.new([0...4,2...5])
114
+ prog =[0...4,2...5]
115
115
  score = Score::Measured.new(FOUR_FOUR, 120, program: prog)
116
116
  converter = ScoreConverter::Measured.new(score,200)
117
117
  nscore = converter.convert_score
@@ -197,23 +197,23 @@ describe ScoreConverter::Unmeasured do
197
197
 
198
198
  describe '#convert_program' do
199
199
  before :each do
200
- @prog = Program.new([0...4,2...5])
200
+ @prog = [0...4,2...5]
201
201
  @score = Score::Unmeasured.new(120, program: @prog)
202
202
  @converter = ScoreConverter::Unmeasured.new(@score,200)
203
203
  @prog2 = @converter.convert_program
204
204
  end
205
205
 
206
- it 'should return Program with same number of segments' do
207
- @prog2.should be_a Program
208
- @prog2.segments.size.should eq(@prog.segments.size)
206
+ it 'should return array with same size' do
207
+ @prog2.should be_a Array
208
+ @prog2.size.should eq(@prog.size)
209
209
  end
210
210
 
211
211
  it 'should convert program segments offsets from note-based to time-based' do
212
212
  prog = @prog2
213
- prog.segments[0].first.should eq(0)
214
- prog.segments[0].last.should eq(8)
215
- prog.segments[1].first.should eq(4)
216
- prog.segments[1].last.should eq(10)
213
+ prog[0].first.should eq(0)
214
+ prog[0].last.should eq(8)
215
+ prog[1].first.should eq(4)
216
+ prog[1].last.should eq(10)
217
217
  end
218
218
  end
219
219
 
@@ -225,7 +225,7 @@ describe ScoreConverter::Unmeasured do
225
225
  end
226
226
 
227
227
  it 'should use output from convert_program' do
228
- prog = Program.new([0...4,2...5])
228
+ prog = [0...4,2...5]
229
229
  score = Score::Unmeasured.new(120, program: prog)
230
230
  converter = ScoreConverter::Unmeasured.new(score,200)
231
231
  nscore = converter.convert_score
@@ -1,83 +1,85 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
- {
4
- Link::Glissando => Link::Portamento,
5
- Link::Portamento => Link::Glissando,
6
- Link::Slur => Link::Legato,
7
- Link::Legato => Link::Slur
8
- }.each do |klass,klass2|
3
+ [
4
+ [Link::Glissando, Link::Portamento, LINK_SYMBOLS[Links::GLISSANDO]],
5
+ [Link::Portamento, Link::Glissando, LINK_SYMBOLS[Links::PORTAMENTO]],
6
+ ].each do |klass,klass2,link_symbol|
9
7
  describe klass do
8
+ before :all do
9
+ @tgt_pitch = C2
10
+ @obj = klass.new(@tgt_pitch)
11
+ end
12
+
10
13
  describe '#initialize' do
11
14
  it 'should assign the given pitch to :target_pitch' do
12
- klass.new(C2).target_pitch.should eq(C2)
15
+ @obj.target_pitch.should eq(@tgt_pitch)
13
16
  end
14
17
  end
15
18
 
16
19
  describe '#==' do
17
20
  it 'should return true if two links have the same target pitch' do
18
- klass.new(C2).should eq(klass.new(C2))
21
+ @obj.should eq(klass.new(@tgt_pitch))
19
22
  end
20
23
 
21
24
  it 'should return false if two links do not have the same target pitch' do
22
- klass.new(C2).should_not eq(klass.new(F5))
25
+ @obj.should_not eq(klass.new(@tgt_pitch.transpose(1)))
23
26
  end
24
27
 
25
28
  it 'should return false if the link type is different' do
26
- klass.new(C2).should_not eq(klass2.new(C2))
29
+ @obj.should_not eq(klass2.new(@tgt_pitch))
27
30
  end
28
31
  end
29
32
 
30
33
  describe '#clone' do
31
34
  it 'should return a link equal to original' do
32
- l = klass.new(C4)
33
- l.clone.should eq l
35
+ @obj.clone.should eq @obj
34
36
  end
35
37
  end
36
38
 
37
39
  describe '#to_yaml' do
38
40
  it 'should produce YAML that can be loaded' do
39
- l = klass.new(C5)
40
- YAML.load(l.to_yaml).should eq l
41
+ YAML.load(@obj.to_yaml).should eq @obj
41
42
  end
42
43
  end
43
44
 
44
45
  describe '#to_s' do
45
46
  it 'should produce string that include link char and target pitch str' do
46
- l = klass.new(C3)
47
- l.to_s.should eq(l.link_char + "C3")
47
+ @obj.to_s.should eq(link_symbol + @tgt_pitch.to_s)
48
48
  end
49
49
  end
50
50
  end
51
51
  end
52
52
 
53
53
  describe Link::Tie do
54
+ before :all do
55
+ @obj = Link::Tie.new
56
+ end
57
+
54
58
  describe '#==' do
55
59
  it 'should return true if another Tie object is given' do
56
- Link::Tie.new.should eq(Link::Tie.new)
60
+ @obj.should eq(Link::Tie.new)
57
61
  end
58
62
 
59
- it 'should return false if a non-Tie object is given' do
60
- Link::Tie.new.should_not eq(Link::Portamento.new(C2))
63
+ it 'should return false if an object of another class is given' do
64
+ @obj.should_not eq(5)
61
65
  end
62
66
  end
63
67
 
64
68
  describe '#clone' do
65
69
  it 'should return a link equal to original' do
66
- l = Link::Tie.new
67
- l.clone.should eq l
70
+ @obj.clone.should eq @obj
68
71
  end
69
72
  end
70
73
 
71
74
  describe '#to_yaml' do
72
75
  it 'should produce YAML that can be loaded' do
73
- l = Link::Tie.new
74
- YAML.load(l.to_yaml).should eq l
76
+ YAML.load(@obj.to_yaml).should eq @obj
75
77
  end
76
78
  end
77
79
 
78
80
  describe '#to_s' do
79
- it 'should return =' do
80
- Link::Tie.new.to_s.should eq("=")
81
+ it "should return #{LINK_SYMBOLS[Links::TIE]}" do
82
+ @obj.to_s.should eq(LINK_SYMBOLS[Links::TIE])
81
83
  end
82
84
  end
83
85
  end