mtk 0.0.3.3 → 0.4
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 +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
|