jmtk 0.0.3.3-java
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.
- data/.yardopts +10 -0
- data/DEVELOPMENT_NOTES.md +115 -0
- data/INTRO.md +129 -0
- data/LICENSE.txt +27 -0
- data/README.md +50 -0
- data/Rakefile +102 -0
- data/bin/jmtk +250 -0
- data/bin/mtk +250 -0
- data/examples/crescendo.rb +20 -0
- data/examples/drum_pattern.rb +23 -0
- data/examples/dynamic_pattern.rb +36 -0
- data/examples/gets_and_play.rb +27 -0
- data/examples/notation.rb +22 -0
- data/examples/play_midi.rb +17 -0
- data/examples/print_midi.rb +13 -0
- data/examples/random_tone_row.rb +18 -0
- data/examples/syntax_to_midi.rb +28 -0
- data/examples/test_output.rb +7 -0
- data/examples/tone_row_melody.rb +23 -0
- data/lib/mtk.rb +76 -0
- data/lib/mtk/core/duration.rb +213 -0
- data/lib/mtk/core/intensity.rb +158 -0
- data/lib/mtk/core/interval.rb +157 -0
- data/lib/mtk/core/pitch.rb +154 -0
- data/lib/mtk/core/pitch_class.rb +194 -0
- data/lib/mtk/events/event.rb +119 -0
- data/lib/mtk/events/note.rb +112 -0
- data/lib/mtk/events/parameter.rb +54 -0
- data/lib/mtk/events/timeline.rb +232 -0
- data/lib/mtk/groups/chord.rb +56 -0
- data/lib/mtk/groups/collection.rb +196 -0
- data/lib/mtk/groups/melody.rb +96 -0
- data/lib/mtk/groups/pitch_class_set.rb +163 -0
- data/lib/mtk/groups/pitch_collection.rb +23 -0
- data/lib/mtk/io/dls_synth_device.rb +146 -0
- data/lib/mtk/io/dls_synth_output.rb +62 -0
- data/lib/mtk/io/jsound_input.rb +87 -0
- data/lib/mtk/io/jsound_output.rb +82 -0
- data/lib/mtk/io/midi_file.rb +209 -0
- data/lib/mtk/io/midi_input.rb +97 -0
- data/lib/mtk/io/midi_output.rb +195 -0
- data/lib/mtk/io/notation.rb +162 -0
- data/lib/mtk/io/unimidi_input.rb +117 -0
- data/lib/mtk/io/unimidi_output.rb +140 -0
- data/lib/mtk/lang/durations.rb +57 -0
- data/lib/mtk/lang/intensities.rb +61 -0
- data/lib/mtk/lang/intervals.rb +73 -0
- data/lib/mtk/lang/mtk_grammar.citrus +237 -0
- data/lib/mtk/lang/parser.rb +29 -0
- data/lib/mtk/lang/pitch_classes.rb +29 -0
- data/lib/mtk/lang/pitches.rb +52 -0
- data/lib/mtk/lang/pseudo_constants.rb +26 -0
- data/lib/mtk/lang/variable.rb +32 -0
- data/lib/mtk/numeric_extensions.rb +66 -0
- data/lib/mtk/patterns/chain.rb +49 -0
- data/lib/mtk/patterns/choice.rb +43 -0
- data/lib/mtk/patterns/cycle.rb +18 -0
- data/lib/mtk/patterns/for_each.rb +71 -0
- data/lib/mtk/patterns/function.rb +39 -0
- data/lib/mtk/patterns/lines.rb +54 -0
- data/lib/mtk/patterns/palindrome.rb +45 -0
- data/lib/mtk/patterns/pattern.rb +171 -0
- data/lib/mtk/patterns/sequence.rb +20 -0
- data/lib/mtk/sequencers/event_builder.rb +132 -0
- data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
- data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
- data/lib/mtk/sequencers/sequencer.rb +111 -0
- data/lib/mtk/sequencers/step_sequencer.rb +26 -0
- data/spec/mtk/core/duration_spec.rb +372 -0
- data/spec/mtk/core/intensity_spec.rb +289 -0
- data/spec/mtk/core/interval_spec.rb +265 -0
- data/spec/mtk/core/pitch_class_spec.rb +343 -0
- data/spec/mtk/core/pitch_spec.rb +297 -0
- data/spec/mtk/events/event_spec.rb +234 -0
- data/spec/mtk/events/note_spec.rb +174 -0
- data/spec/mtk/events/parameter_spec.rb +220 -0
- data/spec/mtk/events/timeline_spec.rb +430 -0
- data/spec/mtk/groups/chord_spec.rb +85 -0
- data/spec/mtk/groups/collection_spec.rb +374 -0
- data/spec/mtk/groups/melody_spec.rb +225 -0
- data/spec/mtk/groups/pitch_class_set_spec.rb +340 -0
- data/spec/mtk/io/midi_file_spec.rb +243 -0
- data/spec/mtk/io/midi_output_spec.rb +102 -0
- data/spec/mtk/lang/durations_spec.rb +89 -0
- data/spec/mtk/lang/intensities_spec.rb +101 -0
- data/spec/mtk/lang/intervals_spec.rb +143 -0
- data/spec/mtk/lang/parser_spec.rb +603 -0
- data/spec/mtk/lang/pitch_classes_spec.rb +62 -0
- data/spec/mtk/lang/pitches_spec.rb +56 -0
- data/spec/mtk/lang/pseudo_constants_spec.rb +20 -0
- data/spec/mtk/lang/variable_spec.rb +52 -0
- data/spec/mtk/numeric_extensions_spec.rb +83 -0
- data/spec/mtk/patterns/chain_spec.rb +110 -0
- data/spec/mtk/patterns/choice_spec.rb +97 -0
- data/spec/mtk/patterns/cycle_spec.rb +123 -0
- data/spec/mtk/patterns/for_each_spec.rb +136 -0
- data/spec/mtk/patterns/function_spec.rb +120 -0
- data/spec/mtk/patterns/lines_spec.rb +77 -0
- data/spec/mtk/patterns/palindrome_spec.rb +108 -0
- data/spec/mtk/patterns/pattern_spec.rb +132 -0
- data/spec/mtk/patterns/sequence_spec.rb +203 -0
- data/spec/mtk/sequencers/event_builder_spec.rb +245 -0
- data/spec/mtk/sequencers/legato_sequencer_spec.rb +45 -0
- data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +84 -0
- data/spec/mtk/sequencers/sequencer_spec.rb +215 -0
- data/spec/mtk/sequencers/step_sequencer_spec.rb +93 -0
- data/spec/spec_coverage.rb +2 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/test.mid +0 -0
- metadata +226 -0
@@ -0,0 +1,289 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Core::Intensity do
|
4
|
+
|
5
|
+
let(:half_intensity) { Intensity[0.5] }
|
6
|
+
|
7
|
+
|
8
|
+
describe 'NAMES' do
|
9
|
+
it "is the list of base intensity names available" do
|
10
|
+
Intensity::NAMES.should =~ %w( ppp pp p mp mf o ff fff )
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is immutable" do
|
14
|
+
lambda{ Intensity::NAMES << 'z' }.should raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe 'VALUES_BY_NAME' do
|
20
|
+
it 'maps names to values' do
|
21
|
+
Intensity::VALUES_BY_NAME.each do |name,value|
|
22
|
+
Intensity.from_s(name).value.should == value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'is immutable' do
|
27
|
+
lambda{ Intensity::VALUES_BY_NAME << 'z' }.should raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
describe '.new' do
|
33
|
+
it "constructs a Intensity with whatever value is given" do
|
34
|
+
float = 0.5
|
35
|
+
value = Intensity.new(float).value
|
36
|
+
value.should be_equal float
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
describe '.[]' do
|
42
|
+
it "constructs and caches a intensity from a Numeric" do
|
43
|
+
Intensity[1].should be_equal Intensity[1]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "retains the new() method's ability to construct uncached objects" do
|
47
|
+
Intensity.new(1).should_not be_equal Intensity[1]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "converts the value to floating point" do
|
51
|
+
value = Intensity[Rational(1,2)].value
|
52
|
+
value.should be_a Float
|
53
|
+
value.should == 0.5
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
describe '.from_i' do
|
60
|
+
it "acts like .[]" do
|
61
|
+
Intensity.from_i(0).value.should == 0.0
|
62
|
+
Intensity.from_i(4).value.should == 4.0
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '.from_f' do
|
67
|
+
it "acts like .[]" do
|
68
|
+
value = Intensity.from_f(Rational(1,2)).value
|
69
|
+
value.should be_a Float
|
70
|
+
value.should == 0.5
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '.from_s' do
|
75
|
+
it "converts any of the intensity NAMES into a Intensity with the value from the VALUES_BY_NAME mapping" do
|
76
|
+
for name in Intensity::NAMES
|
77
|
+
Intensity.from_s(name).value.should == Intensity::VALUES_BY_NAME[name]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "adds 1.0/24 when the name ends with '+', except for 'fff+' which is 1.0 like 'fff'" do
|
82
|
+
for name in Intensity::NAMES
|
83
|
+
if name == 'fff'
|
84
|
+
Intensity.from_s("#{name}+").should == Intensity[1.0]
|
85
|
+
else
|
86
|
+
Intensity.from_s("#{name}+").should == Intensity[ Intensity::VALUES_BY_NAME[name] +1.0/24 ]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "subtracts 1.0/24 when the name ends with '-'" do
|
92
|
+
for name in Intensity::NAMES
|
93
|
+
Intensity.from_s("#{name}-").should == Intensity[ Intensity::VALUES_BY_NAME[name] - 1.0/24 ]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '.from_name' do
|
99
|
+
it "acts like .from_s" do
|
100
|
+
for name in Intensity::NAMES
|
101
|
+
Intensity.from_name(name).value.should == Intensity::VALUES_BY_NAME[name]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
describe '#value' do
|
108
|
+
it "is the value used to construct the Intensity" do
|
109
|
+
Intensity.new(1.111).value.should == 1.111
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
describe '#to_f' do
|
115
|
+
it "is the value as a floating point number" do
|
116
|
+
f = Intensity.new(Rational(1,2)).to_f
|
117
|
+
f.should be_a Float
|
118
|
+
f.should == 0.5
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#to_i' do
|
123
|
+
it "is the value rounded to the nearest integer" do
|
124
|
+
i = Intensity.new(0.5).to_i
|
125
|
+
i.should be_a Fixnum
|
126
|
+
i.should == 1
|
127
|
+
Intensity.new(0.49).to_i.should == 0
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#to_percentage' do
|
132
|
+
it 'is the value*100 rounded to the nearest integer' do
|
133
|
+
Intensity.new(0).to_percent.should == 0
|
134
|
+
Intensity.new(0.5).to_percent.should == 50
|
135
|
+
Intensity.new(1).to_percent.should == 100
|
136
|
+
Intensity.new(2).to_percent.should == 200
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#to_s' do
|
141
|
+
it "is to_percentage suffixed with '% intensity'" do
|
142
|
+
Intensity.new(0).to_s.should == '0% intensity'
|
143
|
+
Intensity.new(0.5).to_s.should == '50% intensity'
|
144
|
+
Intensity.new(1).to_s.should == '100% intensity'
|
145
|
+
Intensity.new(2).to_s.should == '200% intensity'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe '#inspect' do
|
150
|
+
it 'is "#<MTK::Core::Intensity:{object_id} @value={value}>"' do
|
151
|
+
for value in [0, 60, 60.5, 127]
|
152
|
+
intensity = Intensity.new(value)
|
153
|
+
intensity.inspect.should == "#<MTK::Core::Intensity:#{intensity.object_id} @value=#{value}>"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#==' do
|
159
|
+
it "compares two intensity values for equality" do
|
160
|
+
Intensity.new(Rational(1,2)).should == Intensity.new(0.5)
|
161
|
+
Intensity.new(4).should == Intensity.new(4)
|
162
|
+
Intensity.new(1.1).should_not == Intensity.new(1)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "#<=>" do
|
167
|
+
it "orders intensitys based on their underlying value" do
|
168
|
+
( Intensity.new(1) <=> Intensity.new(1.1) ).should < 0
|
169
|
+
( Intensity.new(2) <=> Intensity.new(1) ).should > 0
|
170
|
+
( Intensity.new(1.0) <=> Intensity.new(1) ).should == 0
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
describe '#+' do
|
177
|
+
it 'adds #value to the Numeric argument' do
|
178
|
+
(half_intensity + 0.25).should == Intensity[0.75]
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'works with an Intensity argument' do
|
182
|
+
(half_intensity + Intensity[0.25]).should == Intensity[0.75]
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'returns a new intensity (Intensity is immutable)' do
|
186
|
+
original = half_intensity
|
187
|
+
modified = half_intensity + 0.25
|
188
|
+
original.should_not == modified
|
189
|
+
original.should == Intensity[0.5]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#-' do
|
194
|
+
it 'subtract the Numeric argument from #value' do
|
195
|
+
(half_intensity - 0.25).should == Intensity[0.25]
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'works with a Intensity argument' do
|
199
|
+
(half_intensity - Intensity[0.25]).should == Intensity[0.25]
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'returns a new intensity (Intensity is immutable)' do
|
203
|
+
original = half_intensity
|
204
|
+
modified = half_intensity - 0.25
|
205
|
+
original.should_not == modified
|
206
|
+
original.should == Intensity[0.5]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
describe '#*' do
|
212
|
+
it 'multiplies #value to the Numeric argument' do
|
213
|
+
(half_intensity * 0.1).should == Intensity[0.05]
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'works with a Intensity argument' do
|
217
|
+
(half_intensity * Intensity[0.1]).should == Intensity[0.05]
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'returns a new intensity (Intensity is immutable)' do
|
221
|
+
original = half_intensity
|
222
|
+
modified = half_intensity * 2
|
223
|
+
original.should_not == modified
|
224
|
+
original.should == Intensity[0.5]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '#/' do
|
229
|
+
it 'divides #value by the Numeric argument' do
|
230
|
+
(half_intensity / 2).should == Intensity[0.25]
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'works with a Intensity argument' do
|
234
|
+
(half_intensity / Intensity[0.5]).should == Intensity[1]
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'returns a new intensity (Intensity is immutable)' do
|
238
|
+
original = half_intensity
|
239
|
+
modified = half_intensity / 2
|
240
|
+
original.should_not == modified
|
241
|
+
original.should == Intensity[0.5]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe '#coerce' do
|
246
|
+
it 'allows a Intensity to be added to a Numeric' do
|
247
|
+
(0.25 + half_intensity).should == Intensity[0.75]
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'allows a Intensity to be subtracted from a Numeric' do
|
251
|
+
(0.9 - half_intensity).should == Intensity[0.4]
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'allows a Intensity to be multiplied to a Numeric' do
|
255
|
+
(0.5 * half_intensity).should == Intensity[0.25]
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'allows a Numeric to be divided by a Intensity' do
|
259
|
+
(0.1 / half_intensity).should == Intensity[0.2]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
describe MTK do
|
266
|
+
|
267
|
+
describe '#Intensity' do
|
268
|
+
it "acts like .from_s if the argument is a String" do
|
269
|
+
Intensity('ppp').should == Intensity.from_s('ppp')
|
270
|
+
end
|
271
|
+
|
272
|
+
it "acts like .from_s if the argument is a Symbol" do
|
273
|
+
Intensity(:ppp).should == Intensity.from_s('ppp')
|
274
|
+
end
|
275
|
+
|
276
|
+
it "acts like .[] if the argument is a Numeric" do
|
277
|
+
Intensity(0.5).should be_equal Intensity[0.5]
|
278
|
+
end
|
279
|
+
|
280
|
+
it "returns the argument if it's already a Intensity" do
|
281
|
+
Intensity(Intensity[1]).should be_equal Intensity[1]
|
282
|
+
end
|
283
|
+
|
284
|
+
it "raises an error for types it doesn't understand" do
|
285
|
+
lambda{ Intensity({:not => :compatible}) }.should raise_error
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Core::Interval do
|
4
|
+
|
5
|
+
let(:minor_second) { Interval[1] }
|
6
|
+
|
7
|
+
|
8
|
+
describe 'NAMES' do
|
9
|
+
it "is the list of base interval names available" do
|
10
|
+
Interval::NAMES.should =~ %w( P1 m2 M2 m3 M3 P4 TT P5 m6 M6 m7 M7 P8 )
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is immutable" do
|
14
|
+
lambda{ Interval::NAMES << 'z' }.should raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe 'VALUES_BY_NAME' do
|
20
|
+
it 'maps names to values' do
|
21
|
+
Interval::VALUES_BY_NAME.each do |name,value|
|
22
|
+
Interval.from_s(name).value.should == value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'is immutable' do
|
27
|
+
lambda{ Interval::VALUES_BY_NAME << 'z' }.should raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
describe 'ALL_NAMES' do
|
33
|
+
it 'contains all NAMES' do
|
34
|
+
Interval::NAMES.each{|name| Interval::ALL_NAMES.should include name }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
describe '.new' do
|
40
|
+
it "constructs a Interval with whatever value is given" do
|
41
|
+
float = 0.5
|
42
|
+
value = Interval.new(float).value
|
43
|
+
value.should be_equal float
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe '.[]' do
|
49
|
+
it "constructs and caches a interval from a Numeric" do
|
50
|
+
Interval[1].should be_equal Interval[1]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "retains the new() method's ability to construct uncached objects" do
|
54
|
+
Interval.new(1).should_not be_equal Interval[1]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "converts the value to floating point" do
|
58
|
+
value = Interval[Rational(1,2)].value
|
59
|
+
value.should be_a Float
|
60
|
+
value.should == 0.5
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
describe '.from_i' do
|
67
|
+
it "acts like .[]" do
|
68
|
+
Interval.from_i(0).value.should == 0.0
|
69
|
+
Interval.from_i(4).value.should == 4.0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '.from_f' do
|
74
|
+
it "acts like .[]" do
|
75
|
+
value = Interval.from_f(Rational(1,2)).value
|
76
|
+
value.should be_a Float
|
77
|
+
value.should == 0.5
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '.from_s' do
|
82
|
+
it "converts any of the interval NAMES into a Interval with the value from the VALUES_BY_NAME mapping" do
|
83
|
+
for name in Interval::ALL_NAMES
|
84
|
+
Interval.from_s(name).value.should == Interval::VALUES_BY_NAME[name]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '.from_name' do
|
90
|
+
it "acts like .from_s" do
|
91
|
+
for name in Interval::NAMES
|
92
|
+
Interval.from_name(name).value.should == Interval::VALUES_BY_NAME[name]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
describe '#value' do
|
99
|
+
it "is the value used to construct the Interval" do
|
100
|
+
Interval.new(1.111).value.should == 1.111
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
describe '#to_f' do
|
106
|
+
it "is the value as a floating point number" do
|
107
|
+
f = Interval.new(Rational(1,2)).to_f
|
108
|
+
f.should be_a Float
|
109
|
+
f.should == 0.5
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#to_i' do
|
114
|
+
it "is the value rounded to the nearest integer" do
|
115
|
+
i = Interval.new(0.5).to_i
|
116
|
+
i.should be_a Fixnum
|
117
|
+
i.should == 1
|
118
|
+
Interval.new(0.49).to_i.should == 0
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#to_s' do
|
123
|
+
it "should be value.to_s" do
|
124
|
+
for value in [1, Rational(1,2), 0.25]
|
125
|
+
Interval.new(value).to_s.should == value.to_s
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#==' do
|
131
|
+
it "compares two interval values for equality" do
|
132
|
+
Interval.new(Rational(1,2)).should == Interval.new(0.5)
|
133
|
+
Interval.new(4).should == Interval.new(4)
|
134
|
+
Interval.new(1.1).should_not == Interval.new(1)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#<=>" do
|
139
|
+
it "orders intervals based on their underlying value" do
|
140
|
+
( Interval.new(1) <=> Interval.new(1.1) ).should < 0
|
141
|
+
( Interval.new(2) <=> Interval.new(1) ).should > 0
|
142
|
+
( Interval.new(1.0) <=> Interval.new(1) ).should == 0
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
describe '#+' do
|
149
|
+
it 'adds #value to the Numeric argument' do
|
150
|
+
(minor_second + 0.25).should == Interval[1.25]
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'works with an Interval argument' do
|
154
|
+
(minor_second + Interval[0.25]).should == Interval[1.25]
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'returns a new interval (Interval is immutable)' do
|
158
|
+
original = minor_second
|
159
|
+
modified = minor_second + 0.25
|
160
|
+
original.should_not == modified
|
161
|
+
original.should == Interval[1]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#-' do
|
166
|
+
it 'subtract the Numeric argument from #value' do
|
167
|
+
(minor_second - 0.25).should == Interval[0.75]
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'works with a Interval argument' do
|
171
|
+
(minor_second - Interval[0.25]).should == Interval[0.75]
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns a new interval (Interval is immutable)' do
|
175
|
+
original = minor_second
|
176
|
+
modified = minor_second - 0.25
|
177
|
+
original.should_not == modified
|
178
|
+
original.should == Interval[1]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
describe '#*' do
|
184
|
+
it 'multiplies #value to the Numeric argument' do
|
185
|
+
(minor_second * 3).should == Interval[3]
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'works with a Interval argument' do
|
189
|
+
(minor_second * Interval[3]).should == Interval[3]
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'returns a new interval (Interval is immutable)' do
|
193
|
+
original = minor_second
|
194
|
+
modified = minor_second * 2
|
195
|
+
original.should_not == modified
|
196
|
+
original.should == Interval[1]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe '#/' do
|
201
|
+
it 'divides #value by the Numeric argument' do
|
202
|
+
(minor_second / 2).should == Interval[0.5]
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'works with a Interval argument' do
|
206
|
+
(minor_second / Interval[2]).should == Interval[0.5]
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'returns a new interval (Interval is immutable)' do
|
210
|
+
original = minor_second
|
211
|
+
modified = minor_second / 2
|
212
|
+
original.should_not == modified
|
213
|
+
original.should == Interval[1]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#coerce' do
|
218
|
+
it 'allows a Interval to be added to a Numeric' do
|
219
|
+
(0.25 + minor_second).should == Interval[1.25]
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'allows a Interval to be subtracted from a Numeric' do
|
223
|
+
(3 - minor_second).should == Interval[2]
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'allows a Interval to be multiplied to a Numeric' do
|
227
|
+
(3 * minor_second).should == Interval[3]
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'allows a Numeric to be divided by a Interval' do
|
231
|
+
(4 / minor_second).should == Interval[4]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
describe MTK do
|
238
|
+
|
239
|
+
describe '#Interval' do
|
240
|
+
it "acts like .from_s if the argument is a String" do
|
241
|
+
for name in Interval::ALL_NAMES
|
242
|
+
Interval(name).should == Interval.from_s(name)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
it "acts like .from_s if the argument is a Symbol" do
|
247
|
+
for name in Interval::ALL_NAMES
|
248
|
+
Interval(name.to_sym).should == Interval.from_s(name)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
it "acts like .[] if the argument is a Numeric" do
|
253
|
+
Interval(0.5).should be_equal Interval[0.5]
|
254
|
+
end
|
255
|
+
|
256
|
+
it "returns the argument if it's already a Interval" do
|
257
|
+
Interval(Interval[1]).should be_equal Interval[1]
|
258
|
+
end
|
259
|
+
|
260
|
+
it "raises an error for types it doesn't understand" do
|
261
|
+
lambda{ Interval({:not => :compatible}) }.should raise_error
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|