mtk 0.0.3.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/INTRO.md +63 -31
- data/Rakefile +3 -1
- data/bin/mtk +75 -32
- data/examples/drum_pattern.rb +2 -2
- data/examples/dynamic_pattern.rb +1 -1
- data/examples/helpers/output_selector.rb +71 -0
- data/examples/notation.rb +5 -1
- data/examples/tone_row_melody.rb +1 -1
- data/lib/mtk.rb +1 -0
- data/lib/mtk/core/duration.rb +18 -3
- data/lib/mtk/core/intensity.rb +5 -3
- data/lib/mtk/core/interval.rb +21 -14
- data/lib/mtk/core/pitch.rb +2 -0
- data/lib/mtk/core/pitch_class.rb +6 -3
- data/lib/mtk/events/event.rb +2 -1
- data/lib/mtk/events/note.rb +1 -1
- data/lib/mtk/events/parameter.rb +1 -0
- data/lib/mtk/events/rest.rb +85 -0
- data/lib/mtk/events/timeline.rb +6 -2
- data/lib/mtk/io/jsound_input.rb +9 -3
- data/lib/mtk/io/midi_file.rb +38 -2
- data/lib/mtk/io/midi_input.rb +1 -1
- data/lib/mtk/io/midi_output.rb +95 -4
- data/lib/mtk/io/unimidi_input.rb +7 -3
- data/lib/mtk/lang/durations.rb +31 -26
- data/lib/mtk/lang/intensities.rb +29 -30
- data/lib/mtk/lang/intervals.rb +108 -41
- data/lib/mtk/lang/mtk_grammar.citrus +14 -4
- data/lib/mtk/lang/parser.rb +10 -5
- data/lib/mtk/lang/pitch_classes.rb +45 -17
- data/lib/mtk/lang/pitches.rb +169 -32
- data/lib/mtk/lang/tutorial.rb +279 -0
- data/lib/mtk/lang/tutorial_lesson.rb +87 -0
- data/lib/mtk/sequencers/event_builder.rb +29 -8
- data/spec/mtk/core/duration_spec.rb +14 -1
- data/spec/mtk/core/intensity_spec.rb +1 -1
- data/spec/mtk/events/event_spec.rb +10 -16
- data/spec/mtk/events/note_spec.rb +3 -3
- data/spec/mtk/events/rest_spec.rb +184 -0
- data/spec/mtk/events/timeline_spec.rb +5 -1
- data/spec/mtk/io/midi_file_spec.rb +13 -2
- data/spec/mtk/io/midi_output_spec.rb +42 -9
- data/spec/mtk/lang/durations_spec.rb +5 -5
- data/spec/mtk/lang/intensities_spec.rb +5 -5
- data/spec/mtk/lang/intervals_spec.rb +139 -13
- data/spec/mtk/lang/parser_spec.rb +65 -25
- data/spec/mtk/lang/pitch_classes_spec.rb +0 -11
- data/spec/mtk/lang/pitches_spec.rb +0 -15
- data/spec/mtk/patterns/chain_spec.rb +7 -7
- data/spec/mtk/patterns/for_each_spec.rb +2 -2
- data/spec/mtk/sequencers/event_builder_spec.rb +49 -17
- metadata +12 -22
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe MTK::Events::Timeline do
|
4
4
|
|
5
5
|
let(:note1) { Note(C4, p, 1) }
|
6
|
-
let(:note2) { Note(G4,
|
6
|
+
let(:note2) { Note(G4, f, 2) }
|
7
7
|
let(:timeline_raw_data) { { 0.0 => note1, 1.0 => [note1, note2] } }
|
8
8
|
let(:timeline_hash) { { 0.0 => [note1], 1.0 => [note1, note2] } }
|
9
9
|
let(:timeline) { MTK::Events::Timeline.from_h(timeline_raw_data) }
|
@@ -425,6 +425,10 @@ describe MTK::Events::Timeline do
|
|
425
425
|
(line =~ /=>/).should == arrow_position
|
426
426
|
end
|
427
427
|
end
|
428
|
+
|
429
|
+
it "returns empty string for empty timelines" do
|
430
|
+
MTK::Events::Timeline.new.to_s.should == ''
|
431
|
+
end
|
428
432
|
end
|
429
433
|
end
|
430
434
|
|
@@ -42,7 +42,7 @@ describe MTK::IO::MIDIFile do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
describe "#write_timeline" do
|
45
|
-
it 'writes monophonic Notes in a Timeline to a MIDI file' do
|
45
|
+
it 'writes monophonic Notes in a Timeline to a MIDI format 0 file' do
|
46
46
|
MIDIFile(tempfile).write_timeline(
|
47
47
|
MTK::Events::Timeline.from_h({
|
48
48
|
0 => Note(C4, q, 0.7),
|
@@ -56,6 +56,7 @@ describe MTK::IO::MIDIFile do
|
|
56
56
|
seq = MIDI::Sequence.new
|
57
57
|
seq.read(file)
|
58
58
|
seq.tracks.size.should == 1
|
59
|
+
seq.format.should == 0
|
59
60
|
|
60
61
|
track = seq.tracks[0]
|
61
62
|
note_ons, note_offs = note_ons_and_offs(track)
|
@@ -82,6 +83,15 @@ describe MTK::IO::MIDIFile do
|
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
86
|
+
it 'writes a timeline that can be read in as an identical Timeline' do
|
87
|
+
timeline = MTK::Events::Timeline.from_h({
|
88
|
+
0 => Note(C4, q, 1)
|
89
|
+
})
|
90
|
+
MIDIFile(tempfile).write_timeline(timeline)
|
91
|
+
read_timeline = MIDIFile(tempfile).to_timelines.first
|
92
|
+
read_timeline.should == timeline
|
93
|
+
end
|
94
|
+
|
85
95
|
it 'writes polyphonic (simultaneous) Notes in a Timeline to a MIDI file' do
|
86
96
|
MIDIFile(tempfile).write_timeline(
|
87
97
|
MTK::Events::Timeline.from_h({
|
@@ -169,7 +179,7 @@ describe MTK::IO::MIDIFile do
|
|
169
179
|
end
|
170
180
|
|
171
181
|
describe "#write_timelines" do
|
172
|
-
it "writes a multitrack MIDI file" do
|
182
|
+
it "writes a multitrack format 1 MIDI file" do
|
173
183
|
MIDIFile(tempfile).write_timelines([
|
174
184
|
MTK::Events::Timeline.from_h({
|
175
185
|
0 => Note(C4, q, 0.7),
|
@@ -186,6 +196,7 @@ describe MTK::IO::MIDIFile do
|
|
186
196
|
seq = MIDI::Sequence.new
|
187
197
|
seq.read(file)
|
188
198
|
seq.tracks.size.should == 2
|
199
|
+
seq.format.should == 1
|
189
200
|
|
190
201
|
track = seq.tracks[0]
|
191
202
|
note_ons, note_offs = note_ons_and_offs(track)
|
@@ -10,14 +10,15 @@ describe MTK::IO::MIDIOutput do
|
|
10
10
|
let(:subject) { MockOuput.new(mock_device) }
|
11
11
|
|
12
12
|
let(:mock_device) do
|
13
|
-
mock_device =
|
13
|
+
mock_device = double(:device)
|
14
14
|
mock_device.stub(:open)
|
15
15
|
mock_device
|
16
16
|
end
|
17
17
|
|
18
18
|
let(:scheduler) do
|
19
|
-
scheduler =
|
19
|
+
scheduler = double(:scheduler)
|
20
20
|
Gamelan::Scheduler.stub(:new).and_return scheduler
|
21
|
+
scheduler.stub(:stop).and_return :stop_scheduler
|
21
22
|
scheduler
|
22
23
|
end
|
23
24
|
|
@@ -28,14 +29,16 @@ describe MTK::IO::MIDIOutput do
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def should_be_scheduled timed_data
|
32
|
+
explicitly_expected_stop_scheduler = false
|
31
33
|
timed_data.each do |time,data|
|
34
|
+
explicitly_expected_stop_scheduler = true if data == :stop_scheduler
|
32
35
|
scheduler.should_receive(:at) do |scheduled_time,&callback|
|
33
36
|
scheduled_time.should == time
|
34
37
|
callback.yield.should == data
|
35
38
|
end
|
36
39
|
end
|
37
|
-
scheduler.should_receive(:at)
|
38
|
-
scheduler.should_receive(:run).and_return
|
40
|
+
scheduler.should_receive(:at) unless explicitly_expected_stop_scheduler # auto-handle stop_schedulerer if needed
|
41
|
+
scheduler.should_receive(:run).and_return double(:thread,:join=>nil)
|
39
42
|
end
|
40
43
|
|
41
44
|
|
@@ -50,7 +53,8 @@ describe MTK::IO::MIDIOutput do
|
|
50
53
|
|
51
54
|
it "handles note events" do
|
52
55
|
should_be_scheduled 0 => [:note_on, 60, 127, 0],
|
53
|
-
1 => [:
|
56
|
+
1 => [:note_on, 60, 0, 0]
|
57
|
+
# 1 => [:note_off, 60, 127, 0] # for when we have proper note off support
|
54
58
|
subject.play MTK::Events::Timeline.from_h( 0 => Note(C4,fff,1) )
|
55
59
|
end
|
56
60
|
|
@@ -82,21 +86,50 @@ describe MTK::IO::MIDIOutput do
|
|
82
86
|
it "handles simultaneous events" do
|
83
87
|
should_be_scheduled [
|
84
88
|
[0, [:note_on, 60, 127, 0]],
|
85
|
-
[1, [:
|
89
|
+
[1, [:note_on, 60, 0, 0]],
|
90
|
+
# [1, [:note_off, 60, 127, 0]], # for when we have proper note off support
|
86
91
|
[0, [:note_on, 67, 127, 0]],
|
87
|
-
[1, [:
|
92
|
+
[1, [:note_on, 67, 0, 0]],
|
93
|
+
# [1, [:note_off, 67, 127, 0]] # for when we have proper note off support
|
88
94
|
]
|
89
95
|
subject.play [Note(C4,fff,1),Note(G4,fff,1)]
|
90
96
|
end
|
91
97
|
|
92
98
|
it "handles a list of timelines" do
|
93
99
|
should_be_scheduled 0 => [:note_on, 60, 127, 0],
|
94
|
-
1 => [:
|
100
|
+
1 => [:note_on, 60, 0, 0],
|
101
|
+
#1 => [:note_off, 60, 127, 0], # for when we have proper note off support
|
95
102
|
2 => [:note_on, 67, 127, 0],
|
96
|
-
3 => [:
|
103
|
+
3 => [:note_on, 67, 0, 0]
|
104
|
+
#3 => [:note_off, 67, 127, 0] # for when we have proper note off support
|
97
105
|
subject.play [ MTK::Events::Timeline.from_h( 0 => Note(C4,fff,1) ), MTK::Events::Timeline.from_h( 2 => Note(G4,fff,1) )]
|
98
106
|
end
|
99
107
|
|
108
|
+
|
109
|
+
it "stops the scheduler 2 beats after the last event" do
|
110
|
+
should_be_scheduled 0 => [:note_on, 60, 127, 0],
|
111
|
+
1 => [:note_on, 60, 0, 0],
|
112
|
+
#1 => [:note_off, 60, 127, 0], # for when we have proper note off support
|
113
|
+
3 => :stop_scheduler
|
114
|
+
subject.play MTK::Events::Timeline.from_h( 0 => Note(C4,fff,1) )
|
115
|
+
end
|
116
|
+
|
117
|
+
it "stops the scheduler 2 beats after the longest of simultaneous final events" do
|
118
|
+
should_be_scheduled [
|
119
|
+
[0, [:note_on, 60, 127, 0]],
|
120
|
+
[1, [:note_on, 60, 0, 0]],
|
121
|
+
#[1, [:note_off, 60, 127, 0]], # for when we have proper note off support
|
122
|
+
[0, [:note_on, 62, 127, 0]],
|
123
|
+
[3.5,[:note_on, 62, 0, 0]],
|
124
|
+
#[3.5,[:note_off, 62, 127, 0]], # for when we have proper note off support
|
125
|
+
[0, [:note_on, 64, 127, 0]],
|
126
|
+
[2, [:note_on, 64, 0, 0]],
|
127
|
+
#[2, [:note_off, 64, 127, 0]], # for when we have proper note off support
|
128
|
+
[5.5, :stop_scheduler]
|
129
|
+
]
|
130
|
+
subject.play MTK::Events::Timeline.from_h( 0 => [Note(C4,fff,1), Note(D4,fff,3.5), Note(E4,fff,2)] )
|
131
|
+
end
|
132
|
+
|
100
133
|
end
|
101
134
|
|
102
135
|
end
|
@@ -29,12 +29,12 @@ describe MTK::Lang::Durations do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe '
|
32
|
+
describe 'e' do
|
33
33
|
it 'is 1/2 of a beat' do
|
34
|
-
|
34
|
+
e.value.should == 1.0/2
|
35
35
|
end
|
36
36
|
it 'is available via a module property and via mixin' do
|
37
|
-
Durations::
|
37
|
+
Durations::e.should == e
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -67,7 +67,7 @@ describe MTK::Lang::Durations do
|
|
67
67
|
|
68
68
|
describe "DURATIONS" do
|
69
69
|
it "contains all Durations pseudo-constants" do
|
70
|
-
Durations::DURATIONS.should =~ [w, h, q,
|
70
|
+
Durations::DURATIONS.should =~ [w, h, q, e, s, r, x]
|
71
71
|
end
|
72
72
|
|
73
73
|
it "is immutable" do
|
@@ -77,7 +77,7 @@ describe MTK::Lang::Durations do
|
|
77
77
|
|
78
78
|
describe "DURATION_NAMES" do
|
79
79
|
it "contains all Durations pseudo-constants names as strings" do
|
80
|
-
Durations::DURATION_NAMES.should =~ ['w', 'h', 'q', '
|
80
|
+
Durations::DURATION_NAMES.should =~ ['w', 'h', 'q', 'e', 's', 'r', 'x']
|
81
81
|
end
|
82
82
|
|
83
83
|
it "is immutable" do
|
@@ -47,12 +47,12 @@ describe MTK::Lang::Intensities do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
describe '
|
50
|
+
describe 'f' do # AKA forte
|
51
51
|
it 'is equivalent to MIDI velocity 95' do
|
52
|
-
(
|
52
|
+
(f.value * 127).round.should == 95
|
53
53
|
end
|
54
54
|
it 'is available via a module property and via mixin' do
|
55
|
-
Intensities::
|
55
|
+
Intensities::f.should == f
|
56
56
|
end
|
57
57
|
it "does not overwrite the PitchClass constant 'F'" do
|
58
58
|
F.should be_a PitchClass
|
@@ -79,7 +79,7 @@ describe MTK::Lang::Intensities do
|
|
79
79
|
|
80
80
|
describe "INTENSITIES" do
|
81
81
|
it "contains all Intensities pseudo-constants" do
|
82
|
-
Intensities::INTENSITIES.should =~ [ppp, pp, p, mp, mf,
|
82
|
+
Intensities::INTENSITIES.should =~ [ppp, pp, p, mp, mf, f, ff, fff]
|
83
83
|
end
|
84
84
|
|
85
85
|
it "is immutable" do
|
@@ -89,7 +89,7 @@ describe MTK::Lang::Intensities do
|
|
89
89
|
|
90
90
|
describe "INTENSITY_NAMES" do
|
91
91
|
it "contains all Intensities pseudo-constants names as strings" do
|
92
|
-
Intensities::INTENSITY_NAMES.should =~ ['ppp', 'pp', 'p', 'mp', 'mf', '
|
92
|
+
Intensities::INTENSITY_NAMES.should =~ ['ppp', 'pp', 'p', 'mp', 'mf', 'f', 'ff', 'fff']
|
93
93
|
end
|
94
94
|
|
95
95
|
it "is immutable" do
|
@@ -11,12 +11,30 @@ describe MTK::Lang::Intervals do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
describe 'd2' do
|
15
|
+
it 'is 0 semitones' do
|
16
|
+
d2.should == Interval[0]
|
17
|
+
end
|
18
|
+
it 'is available via a module property and via mixin' do
|
19
|
+
Intervals::d2.should == d2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
14
23
|
describe 'm2' do
|
15
24
|
it 'is 1 semitone' do
|
16
25
|
m2.should == Interval[1]
|
17
26
|
end
|
18
27
|
it 'is available via a module property and via mixin' do
|
19
|
-
Intervals::
|
28
|
+
Intervals::m2.should == m2
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'a1' do
|
33
|
+
it 'is 1 semitone' do
|
34
|
+
a1.should == Interval[1]
|
35
|
+
end
|
36
|
+
it 'is available via a module property and via mixin' do
|
37
|
+
Intervals::a1.should == a1
|
20
38
|
end
|
21
39
|
end
|
22
40
|
|
@@ -25,7 +43,16 @@ describe MTK::Lang::Intervals do
|
|
25
43
|
M2.should == Interval[2]
|
26
44
|
end
|
27
45
|
it 'is available via a module property and via mixin' do
|
28
|
-
Intervals::
|
46
|
+
Intervals::M2.should == M2
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'd3' do
|
51
|
+
it 'is 2 semitones' do
|
52
|
+
d3.should == Interval[2]
|
53
|
+
end
|
54
|
+
it 'is available via a module property and via mixin' do
|
55
|
+
Intervals::d3.should == d3
|
29
56
|
end
|
30
57
|
end
|
31
58
|
|
@@ -34,7 +61,16 @@ describe MTK::Lang::Intervals do
|
|
34
61
|
m3.should == Interval[3]
|
35
62
|
end
|
36
63
|
it 'is available via a module property and via mixin' do
|
37
|
-
Intervals::
|
64
|
+
Intervals::m3.should == m3
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'a2' do
|
69
|
+
it 'is 3 semitones' do
|
70
|
+
a2.should == Interval[3]
|
71
|
+
end
|
72
|
+
it 'is available via a module property and via mixin' do
|
73
|
+
Intervals::a2.should == a2
|
38
74
|
end
|
39
75
|
end
|
40
76
|
|
@@ -43,7 +79,16 @@ describe MTK::Lang::Intervals do
|
|
43
79
|
M3.should == Interval[4]
|
44
80
|
end
|
45
81
|
it 'is available via a module property and via mixin' do
|
46
|
-
Intervals::
|
82
|
+
Intervals::M3.should == M3
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'd4' do
|
87
|
+
it 'is 4 semitones' do
|
88
|
+
d4.should == Interval[4]
|
89
|
+
end
|
90
|
+
it 'is available via a module property and via mixin' do
|
91
|
+
Intervals::d4.should == d4
|
47
92
|
end
|
48
93
|
end
|
49
94
|
|
@@ -52,7 +97,16 @@ describe MTK::Lang::Intervals do
|
|
52
97
|
P4.should == Interval[5]
|
53
98
|
end
|
54
99
|
it 'is available via a module property and via mixin' do
|
55
|
-
Intervals::
|
100
|
+
Intervals::P4.should == P4
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'a3' do
|
105
|
+
it 'is 5 semitones' do
|
106
|
+
a3.should == Interval[5]
|
107
|
+
end
|
108
|
+
it 'is available via a module property and via mixin' do
|
109
|
+
Intervals::a3.should == a3
|
56
110
|
end
|
57
111
|
end
|
58
112
|
|
@@ -61,7 +115,25 @@ describe MTK::Lang::Intervals do
|
|
61
115
|
TT.should == Interval[6]
|
62
116
|
end
|
63
117
|
it 'is available via a module property and via mixin' do
|
64
|
-
Intervals::
|
118
|
+
Intervals::TT.should == TT
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'a4' do
|
123
|
+
it 'is 6 semitones' do
|
124
|
+
a4.should == Interval[6]
|
125
|
+
end
|
126
|
+
it 'is available via a module property and via mixin' do
|
127
|
+
Intervals::a4.should == a4
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'd5' do
|
132
|
+
it 'is 6 semitones' do
|
133
|
+
d5.should == Interval[6]
|
134
|
+
end
|
135
|
+
it 'is available via a module property and via mixin' do
|
136
|
+
Intervals::d5.should == d5
|
65
137
|
end
|
66
138
|
end
|
67
139
|
|
@@ -70,7 +142,16 @@ describe MTK::Lang::Intervals do
|
|
70
142
|
P5.should == Interval[7]
|
71
143
|
end
|
72
144
|
it 'is available via a module property and via mixin' do
|
73
|
-
Intervals::
|
145
|
+
Intervals::P5.should == P5
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'd6' do
|
150
|
+
it 'is 7 semitones' do
|
151
|
+
d6.should == Interval[7]
|
152
|
+
end
|
153
|
+
it 'is available via a module property and via mixin' do
|
154
|
+
Intervals::d6.should == d6
|
74
155
|
end
|
75
156
|
end
|
76
157
|
|
@@ -83,12 +164,30 @@ describe MTK::Lang::Intervals do
|
|
83
164
|
end
|
84
165
|
end
|
85
166
|
|
167
|
+
describe 'a5' do
|
168
|
+
it 'is 8 semitones' do
|
169
|
+
a5.should == Interval[8]
|
170
|
+
end
|
171
|
+
it 'is available via a module property and via mixin' do
|
172
|
+
Intervals::a5.should == a5
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
86
176
|
describe 'M6' do
|
87
177
|
it 'is 9 semitones' do
|
88
178
|
M6.should == Interval[9]
|
89
179
|
end
|
90
180
|
it 'is available via a module property and via mixin' do
|
91
|
-
Intervals::
|
181
|
+
Intervals::M6.should == M6
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'd7' do
|
186
|
+
it 'is 9 semitones' do
|
187
|
+
d7.should == Interval[9]
|
188
|
+
end
|
189
|
+
it 'is available via a module property and via mixin' do
|
190
|
+
Intervals::d7.should == d7
|
92
191
|
end
|
93
192
|
end
|
94
193
|
|
@@ -97,7 +196,16 @@ describe MTK::Lang::Intervals do
|
|
97
196
|
m7.should == Interval[10]
|
98
197
|
end
|
99
198
|
it 'is available via a module property and via mixin' do
|
100
|
-
Intervals::
|
199
|
+
Intervals::m7.should == m7
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe 'a6' do
|
204
|
+
it 'is 10 semitones' do
|
205
|
+
a6.should == Interval[10]
|
206
|
+
end
|
207
|
+
it 'is available via a module property and via mixin' do
|
208
|
+
Intervals::a6.should == a6
|
101
209
|
end
|
102
210
|
end
|
103
211
|
|
@@ -106,7 +214,16 @@ describe MTK::Lang::Intervals do
|
|
106
214
|
M7.should == Interval[11]
|
107
215
|
end
|
108
216
|
it 'is available via a module property and via mixin' do
|
109
|
-
Intervals::
|
217
|
+
Intervals::M7.should == M7
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe 'd8' do
|
222
|
+
it 'is 11 semitones' do
|
223
|
+
d8.should == Interval[11]
|
224
|
+
end
|
225
|
+
it 'is available via a module property and via mixin' do
|
226
|
+
Intervals::d8.should == d8
|
110
227
|
end
|
111
228
|
end
|
112
229
|
|
@@ -115,14 +232,23 @@ describe MTK::Lang::Intervals do
|
|
115
232
|
P8.should == Interval[12]
|
116
233
|
end
|
117
234
|
it 'is available via a module property and via mixin' do
|
118
|
-
Intervals::
|
235
|
+
Intervals::P8.should == P8
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'a7' do
|
240
|
+
it 'is 12 semitones' do
|
241
|
+
a7.should == Interval[12]
|
242
|
+
end
|
243
|
+
it 'is available via a module property and via mixin' do
|
244
|
+
Intervals::a7.should == a7
|
119
245
|
end
|
120
246
|
end
|
121
247
|
|
122
248
|
|
123
249
|
describe "INTERVALS" do
|
124
250
|
it "contains all intervals constants/pseudo-constants" do
|
125
|
-
Intervals::INTERVALS.should =~
|
251
|
+
Intervals::INTERVALS.should =~ MTK::Core::Interval::ALL_NAMES.map{|name| MTK::Core::Interval.from_name(name) }
|
126
252
|
end
|
127
253
|
|
128
254
|
it "is immutable" do
|
@@ -132,7 +258,7 @@ describe MTK::Lang::Intervals do
|
|
132
258
|
|
133
259
|
describe "INTERVAL_NAMES" do
|
134
260
|
it "contains all intervals constants/pseudo-constant names" do
|
135
|
-
Intervals::INTERVAL_NAMES.should =~
|
261
|
+
Intervals::INTERVAL_NAMES.should =~ MTK::Core::Interval::ALL_NAMES
|
136
262
|
end
|
137
263
|
|
138
264
|
it "is immutable" do
|