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.
Files changed (110) hide show
  1. data/.yardopts +10 -0
  2. data/DEVELOPMENT_NOTES.md +115 -0
  3. data/INTRO.md +129 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.md +50 -0
  6. data/Rakefile +102 -0
  7. data/bin/jmtk +250 -0
  8. data/bin/mtk +250 -0
  9. data/examples/crescendo.rb +20 -0
  10. data/examples/drum_pattern.rb +23 -0
  11. data/examples/dynamic_pattern.rb +36 -0
  12. data/examples/gets_and_play.rb +27 -0
  13. data/examples/notation.rb +22 -0
  14. data/examples/play_midi.rb +17 -0
  15. data/examples/print_midi.rb +13 -0
  16. data/examples/random_tone_row.rb +18 -0
  17. data/examples/syntax_to_midi.rb +28 -0
  18. data/examples/test_output.rb +7 -0
  19. data/examples/tone_row_melody.rb +23 -0
  20. data/lib/mtk.rb +76 -0
  21. data/lib/mtk/core/duration.rb +213 -0
  22. data/lib/mtk/core/intensity.rb +158 -0
  23. data/lib/mtk/core/interval.rb +157 -0
  24. data/lib/mtk/core/pitch.rb +154 -0
  25. data/lib/mtk/core/pitch_class.rb +194 -0
  26. data/lib/mtk/events/event.rb +119 -0
  27. data/lib/mtk/events/note.rb +112 -0
  28. data/lib/mtk/events/parameter.rb +54 -0
  29. data/lib/mtk/events/timeline.rb +232 -0
  30. data/lib/mtk/groups/chord.rb +56 -0
  31. data/lib/mtk/groups/collection.rb +196 -0
  32. data/lib/mtk/groups/melody.rb +96 -0
  33. data/lib/mtk/groups/pitch_class_set.rb +163 -0
  34. data/lib/mtk/groups/pitch_collection.rb +23 -0
  35. data/lib/mtk/io/dls_synth_device.rb +146 -0
  36. data/lib/mtk/io/dls_synth_output.rb +62 -0
  37. data/lib/mtk/io/jsound_input.rb +87 -0
  38. data/lib/mtk/io/jsound_output.rb +82 -0
  39. data/lib/mtk/io/midi_file.rb +209 -0
  40. data/lib/mtk/io/midi_input.rb +97 -0
  41. data/lib/mtk/io/midi_output.rb +195 -0
  42. data/lib/mtk/io/notation.rb +162 -0
  43. data/lib/mtk/io/unimidi_input.rb +117 -0
  44. data/lib/mtk/io/unimidi_output.rb +140 -0
  45. data/lib/mtk/lang/durations.rb +57 -0
  46. data/lib/mtk/lang/intensities.rb +61 -0
  47. data/lib/mtk/lang/intervals.rb +73 -0
  48. data/lib/mtk/lang/mtk_grammar.citrus +237 -0
  49. data/lib/mtk/lang/parser.rb +29 -0
  50. data/lib/mtk/lang/pitch_classes.rb +29 -0
  51. data/lib/mtk/lang/pitches.rb +52 -0
  52. data/lib/mtk/lang/pseudo_constants.rb +26 -0
  53. data/lib/mtk/lang/variable.rb +32 -0
  54. data/lib/mtk/numeric_extensions.rb +66 -0
  55. data/lib/mtk/patterns/chain.rb +49 -0
  56. data/lib/mtk/patterns/choice.rb +43 -0
  57. data/lib/mtk/patterns/cycle.rb +18 -0
  58. data/lib/mtk/patterns/for_each.rb +71 -0
  59. data/lib/mtk/patterns/function.rb +39 -0
  60. data/lib/mtk/patterns/lines.rb +54 -0
  61. data/lib/mtk/patterns/palindrome.rb +45 -0
  62. data/lib/mtk/patterns/pattern.rb +171 -0
  63. data/lib/mtk/patterns/sequence.rb +20 -0
  64. data/lib/mtk/sequencers/event_builder.rb +132 -0
  65. data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
  66. data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
  67. data/lib/mtk/sequencers/sequencer.rb +111 -0
  68. data/lib/mtk/sequencers/step_sequencer.rb +26 -0
  69. data/spec/mtk/core/duration_spec.rb +372 -0
  70. data/spec/mtk/core/intensity_spec.rb +289 -0
  71. data/spec/mtk/core/interval_spec.rb +265 -0
  72. data/spec/mtk/core/pitch_class_spec.rb +343 -0
  73. data/spec/mtk/core/pitch_spec.rb +297 -0
  74. data/spec/mtk/events/event_spec.rb +234 -0
  75. data/spec/mtk/events/note_spec.rb +174 -0
  76. data/spec/mtk/events/parameter_spec.rb +220 -0
  77. data/spec/mtk/events/timeline_spec.rb +430 -0
  78. data/spec/mtk/groups/chord_spec.rb +85 -0
  79. data/spec/mtk/groups/collection_spec.rb +374 -0
  80. data/spec/mtk/groups/melody_spec.rb +225 -0
  81. data/spec/mtk/groups/pitch_class_set_spec.rb +340 -0
  82. data/spec/mtk/io/midi_file_spec.rb +243 -0
  83. data/spec/mtk/io/midi_output_spec.rb +102 -0
  84. data/spec/mtk/lang/durations_spec.rb +89 -0
  85. data/spec/mtk/lang/intensities_spec.rb +101 -0
  86. data/spec/mtk/lang/intervals_spec.rb +143 -0
  87. data/spec/mtk/lang/parser_spec.rb +603 -0
  88. data/spec/mtk/lang/pitch_classes_spec.rb +62 -0
  89. data/spec/mtk/lang/pitches_spec.rb +56 -0
  90. data/spec/mtk/lang/pseudo_constants_spec.rb +20 -0
  91. data/spec/mtk/lang/variable_spec.rb +52 -0
  92. data/spec/mtk/numeric_extensions_spec.rb +83 -0
  93. data/spec/mtk/patterns/chain_spec.rb +110 -0
  94. data/spec/mtk/patterns/choice_spec.rb +97 -0
  95. data/spec/mtk/patterns/cycle_spec.rb +123 -0
  96. data/spec/mtk/patterns/for_each_spec.rb +136 -0
  97. data/spec/mtk/patterns/function_spec.rb +120 -0
  98. data/spec/mtk/patterns/lines_spec.rb +77 -0
  99. data/spec/mtk/patterns/palindrome_spec.rb +108 -0
  100. data/spec/mtk/patterns/pattern_spec.rb +132 -0
  101. data/spec/mtk/patterns/sequence_spec.rb +203 -0
  102. data/spec/mtk/sequencers/event_builder_spec.rb +245 -0
  103. data/spec/mtk/sequencers/legato_sequencer_spec.rb +45 -0
  104. data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +84 -0
  105. data/spec/mtk/sequencers/sequencer_spec.rb +215 -0
  106. data/spec/mtk/sequencers/step_sequencer_spec.rb +93 -0
  107. data/spec/spec_coverage.rb +2 -0
  108. data/spec/spec_helper.rb +12 -0
  109. data/spec/test.mid +0 -0
  110. 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