mtk 0.0.1 → 0.0.2
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 +9 -0
- data/INTRO.md +73 -0
- data/LICENSE.txt +27 -0
- data/README.md +93 -18
- data/Rakefile +13 -1
- data/examples/crescendo.rb +20 -0
- data/examples/dynamic_pattern.rb +39 -0
- data/examples/play_midi.rb +19 -0
- data/examples/print_midi.rb +13 -0
- data/examples/random_tone_row.rb +18 -0
- data/examples/tone_row_melody.rb +21 -0
- data/lib/mtk/_constants/durations.rb +80 -0
- data/lib/mtk/_constants/intensities.rb +81 -0
- data/lib/mtk/{constants → _constants}/intervals.rb +10 -1
- data/lib/mtk/_constants/pitch_classes.rb +35 -0
- data/lib/mtk/_constants/pitches.rb +49 -0
- data/lib/mtk/{numeric_extensions.rb → _numeric_extensions.rb} +0 -0
- data/lib/mtk/event.rb +14 -5
- data/lib/mtk/helper/collection.rb +114 -0
- data/lib/mtk/helper/event_builder.rb +85 -0
- data/lib/mtk/{constants → helper}/pseudo_constants.rb +7 -6
- data/lib/mtk/lang/grammar.rb +17 -0
- data/lib/mtk/lang/mtk_grammar.citrus +60 -0
- data/lib/mtk/midi/file.rb +10 -15
- data/lib/mtk/midi/jsound_input.rb +68 -0
- data/lib/mtk/midi/jsound_output.rb +80 -0
- data/lib/mtk/note.rb +22 -3
- data/lib/mtk/pattern/abstract_pattern.rb +132 -0
- data/lib/mtk/pattern/choice.rb +25 -9
- data/lib/mtk/pattern/cycle.rb +51 -0
- data/lib/mtk/pattern/enumerator.rb +26 -0
- data/lib/mtk/pattern/function.rb +46 -0
- data/lib/mtk/pattern/lines.rb +60 -0
- data/lib/mtk/pattern/palindrome.rb +42 -0
- data/lib/mtk/pattern/sequence.rb +15 -50
- data/lib/mtk/pitch.rb +45 -6
- data/lib/mtk/pitch_class.rb +36 -35
- data/lib/mtk/pitch_class_set.rb +46 -14
- data/lib/mtk/pitch_set.rb +20 -31
- data/lib/mtk/sequencer/abstract_sequencer.rb +85 -0
- data/lib/mtk/sequencer/rhythmic_sequencer.rb +29 -0
- data/lib/mtk/sequencer/step_sequencer.rb +26 -0
- data/lib/mtk/timeline.rb +75 -22
- data/lib/mtk/transform/invertible.rb +15 -0
- data/lib/mtk/{util → transform}/mappable.rb +6 -2
- data/lib/mtk/transform/set_theory_operations.rb +34 -0
- data/lib/mtk/transform/transposable.rb +14 -0
- data/lib/mtk.rb +56 -22
- data/spec/mtk/_constants/durations_spec.rb +118 -0
- data/spec/mtk/{constants/dynamics_spec.rb → _constants/intensities_spec.rb} +48 -17
- data/spec/mtk/{constants → _constants}/intervals_spec.rb +21 -0
- data/spec/mtk/_constants/pitch_classes_spec.rb +58 -0
- data/spec/mtk/_constants/pitches_spec.rb +52 -0
- data/spec/mtk/{numeric_extensions_spec.rb → _numeric_extensions_spec.rb} +0 -0
- data/spec/mtk/event_spec.rb +19 -0
- data/spec/mtk/helper/collection_spec.rb +291 -0
- data/spec/mtk/helper/event_builder_spec.rb +92 -0
- data/spec/mtk/helper/pseudo_constants_spec.rb +20 -0
- data/spec/mtk/lang/grammar_spec.rb +100 -0
- data/spec/mtk/midi/file_spec.rb +41 -6
- data/spec/mtk/note_spec.rb +53 -3
- data/spec/mtk/pattern/abstract_pattern_spec.rb +45 -0
- data/spec/mtk/pattern/choice_spec.rb +89 -3
- data/spec/mtk/pattern/cycle_spec.rb +133 -0
- data/spec/mtk/pattern/function_spec.rb +133 -0
- data/spec/mtk/pattern/lines_spec.rb +93 -0
- data/spec/mtk/pattern/note_cycle_spec.rb.bak +116 -0
- data/spec/mtk/pattern/palindrome_spec.rb +124 -0
- data/spec/mtk/pattern/pitch_cycle_spec.rb.bak +47 -0
- data/spec/mtk/pattern/pitch_sequence_spec.rb.bak +37 -0
- data/spec/mtk/pattern/sequence_spec.rb +128 -31
- data/spec/mtk/pitch_class_set_spec.rb +240 -7
- data/spec/mtk/pitch_class_spec.rb +84 -18
- data/spec/mtk/pitch_set_spec.rb +45 -10
- data/spec/mtk/pitch_spec.rb +59 -0
- data/spec/mtk/sequencer/abstract_sequencer_spec.rb +159 -0
- data/spec/mtk/sequencer/rhythmic_sequencer_spec.rb +49 -0
- data/spec/mtk/sequencer/step_sequencer_spec.rb +71 -0
- data/spec/mtk/timeline_spec.rb +118 -15
- data/spec/spec_helper.rb +4 -3
- metadata +59 -22
- data/lib/mtk/chord.rb +0 -47
- data/lib/mtk/constants/dynamics.rb +0 -56
- data/lib/mtk/constants/pitch_classes.rb +0 -18
- data/lib/mtk/constants/pitches.rb +0 -24
- data/lib/mtk/pattern/note_sequence.rb +0 -60
- data/lib/mtk/pattern/pitch_sequence.rb +0 -22
- data/lib/mtk/patterns.rb +0 -4
- data/spec/mtk/chord_spec.rb +0 -74
- data/spec/mtk/constants/pitch_classes_spec.rb +0 -35
- data/spec/mtk/constants/pitches_spec.rb +0 -23
- data/spec/mtk/pattern/note_sequence_spec.rb +0 -121
- data/spec/mtk/pattern/pitch_sequence_spec.rb +0 -47
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Durations do
|
4
|
+
|
5
|
+
describe 'w' do
|
6
|
+
it 'is 4 beats' do
|
7
|
+
w.should == 4
|
8
|
+
end
|
9
|
+
it 'is available via a module property and via mixin' do
|
10
|
+
Durations::w.should == w
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'h' do
|
15
|
+
it 'is 2 beats' do
|
16
|
+
h.should == 2
|
17
|
+
end
|
18
|
+
it 'is available via a module property and via mixin' do
|
19
|
+
Durations::h.should == h
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'q' do
|
24
|
+
it 'is 1 beat' do
|
25
|
+
q.round.should == 1
|
26
|
+
end
|
27
|
+
it 'is available via a module property and via mixin' do
|
28
|
+
Durations::q.should == q
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'e' do
|
33
|
+
it 'is 1/2 of a beat' do
|
34
|
+
e.should == 1.0/2
|
35
|
+
end
|
36
|
+
it 'is available via a module property and via mixin' do
|
37
|
+
Durations::e.should == e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 's' do
|
42
|
+
it 'is 1/4 of a beat' do
|
43
|
+
s.should == 1.0/4
|
44
|
+
end
|
45
|
+
it 'is available via a module property and via mixin' do
|
46
|
+
Durations::s.should == s
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'r' do
|
51
|
+
it 'is 1/8 of a beat' do
|
52
|
+
r.should == 1.0/8
|
53
|
+
end
|
54
|
+
it 'is available via a module property and via mixin' do
|
55
|
+
Durations::r.should == r
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'x' do
|
60
|
+
it 'is 1/16 of a beat' do
|
61
|
+
x.should == 1.0/16
|
62
|
+
end
|
63
|
+
it 'is available via a module property and via mixin' do
|
64
|
+
Durations::x.should == x
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "DURATIONS" do
|
69
|
+
it "contains all Durations pseudo-constants" do
|
70
|
+
Durations::DURATIONS.should =~ [w, h, q, e, s, r, x]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "is immutable" do
|
74
|
+
lambda{ Durations::DURATIONS << :something }.should raise_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "DURATION_NAMES" do
|
79
|
+
it "contains all Durations pseudo-constants names as strings" do
|
80
|
+
Durations::DURATION_NAMES.should =~ ['w', 'h', 'q', 'e', 's', 'r', 'x']
|
81
|
+
end
|
82
|
+
|
83
|
+
it "is immutable" do
|
84
|
+
lambda{ Durations::DURATION_NAMES << :something }.should raise_error
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".[]" do
|
89
|
+
it "looks up the constant by name" do
|
90
|
+
for duration in Durations::DURATION_NAMES
|
91
|
+
Durations[duration].should == Durations.send(duration)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "supports a '.' suffix, which multiples the value by 1.5" do
|
96
|
+
for duration in Durations::DURATION_NAMES
|
97
|
+
Durations["#{duration}."].should == Durations.send(duration) * 1.5
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "supports a 't' suffix, which multiples the value by 2/3" do
|
102
|
+
for duration in Durations::DURATION_NAMES
|
103
|
+
Durations["#{duration}t"].should == Durations.send(duration) * 2/3.0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it "supports '.' and 't' suffixes in any combination" do
|
108
|
+
for duration in Durations::DURATION_NAMES
|
109
|
+
Durations["#{duration}.t"].should == Durations.send(duration) * 1.5 * 2/3.0
|
110
|
+
Durations["#{duration}t."].should == Durations.send(duration) * 1.5 * 2/3.0
|
111
|
+
Durations["#{duration}.."].should == Durations.send(duration) * 1.5 * 1.5
|
112
|
+
Durations["#{duration}..t.t."].should == Durations.send(duration) * 1.5**4 * (2/3.0)**2
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::
|
3
|
+
describe MTK::Intensities do
|
4
4
|
|
5
5
|
describe 'ppp' do
|
6
6
|
it 'is equivalent to MIDI velocity 16' do
|
7
7
|
(ppp * 127).round.should == 16
|
8
8
|
end
|
9
9
|
it 'is available via a module property and via mixin' do
|
10
|
-
|
10
|
+
Intensities::ppp.should == ppp
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -16,7 +16,7 @@ describe MTK::Dynamics do
|
|
16
16
|
(pp * 127).round.should == 32
|
17
17
|
end
|
18
18
|
it 'is available via a module property and via mixin' do
|
19
|
-
|
19
|
+
Intensities::pp.should == pp
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -25,7 +25,7 @@ describe MTK::Dynamics do
|
|
25
25
|
(p * 127).round.should == 48
|
26
26
|
end
|
27
27
|
it 'is available via a module property and via mixin' do
|
28
|
-
|
28
|
+
Intensities::p.should == p
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -34,7 +34,7 @@ describe MTK::Dynamics do
|
|
34
34
|
(mp * 127).round.should == 64
|
35
35
|
end
|
36
36
|
it 'is available via a module property and via mixin' do
|
37
|
-
|
37
|
+
Intensities::mp.should == mp
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ describe MTK::Dynamics do
|
|
43
43
|
(mf * 127).round.should == 79
|
44
44
|
end
|
45
45
|
it 'is available via a module property and via mixin' do
|
46
|
-
|
46
|
+
Intensities::mf.should == mf
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -52,7 +52,7 @@ describe MTK::Dynamics do
|
|
52
52
|
(f * 127).round.should == 95
|
53
53
|
end
|
54
54
|
it 'is available via a module property and via mixin' do
|
55
|
-
|
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
|
@@ -64,7 +64,7 @@ describe MTK::Dynamics do
|
|
64
64
|
(ff * 127).round.should == 111
|
65
65
|
end
|
66
66
|
it 'is available via a module property and via mixin' do
|
67
|
-
|
67
|
+
Intensities::ff.should == ff
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -73,20 +73,51 @@ describe MTK::Dynamics do
|
|
73
73
|
(fff * 127).round.should == 127
|
74
74
|
end
|
75
75
|
it 'is available via a module property and via mixin' do
|
76
|
-
|
76
|
+
Intensities::fff.should == fff
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "INTENSITIES" do
|
81
|
+
it "contains all Intensities pseudo-constants" do
|
82
|
+
Intensities::INTENSITIES.should =~ [ppp, pp, p, mp, mf, f, ff, fff]
|
83
|
+
end
|
84
|
+
|
85
|
+
it "is immutable" do
|
86
|
+
lambda{ Intensities::INTENSITIES << :something }.should raise_error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "INTENSITY_NAMES" do
|
91
|
+
it "contains all Intensities pseudo-constants names as strings" do
|
92
|
+
Intensities::INTENSITY_NAMES.should =~ ['ppp', 'pp', 'p', 'mp', 'mf', 'f', 'ff', 'fff']
|
93
|
+
end
|
94
|
+
|
95
|
+
it "is immutable" do
|
96
|
+
lambda{ Intensities::INTENSITY_NAMES << :something }.should raise_error
|
77
97
|
end
|
78
98
|
end
|
79
99
|
|
80
100
|
describe ".[]" do
|
81
101
|
it "looks up the constant by name" do
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
102
|
+
for name in INTENSITY_NAMES
|
103
|
+
Intensities[name].should == Intensities.send(name)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it "adds 1.0/24 when the name ends with '+', except for 'fff+' which is 1.0 like 'fff'" do
|
108
|
+
for name in INTENSITY_NAMES
|
109
|
+
if name == 'fff'
|
110
|
+
Intensities["#{name}+"].should == 1.0
|
111
|
+
else
|
112
|
+
Intensities["#{name}+"].should == Intensities.send(name)+1.0/24
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "subtracts 1.0/24 when the name ends with '-'" do
|
118
|
+
for name in INTENSITY_NAMES
|
119
|
+
Intensities["#{name}-"].should == Intensities.send(name)-1.0/24
|
120
|
+
end
|
90
121
|
end
|
91
122
|
end
|
92
123
|
|
@@ -119,6 +119,27 @@ describe MTK::Intervals do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
|
123
|
+
describe "INTERVALS" do
|
124
|
+
it "contains all intervals constants/pseudo-constants" do
|
125
|
+
Intervals::INTERVALS.should =~ [P1, m2, M2, m3, M3, P4, TT, P5, m6, M6, m7, M7, P8]
|
126
|
+
end
|
127
|
+
|
128
|
+
it "is immutable" do
|
129
|
+
lambda{ Intervals::INTERVALS << :something }.should raise_error
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "INTERVAL_NAMES" do
|
134
|
+
it "contains all intervals constants/pseudo-constant names" do
|
135
|
+
Intervals::INTERVAL_NAMES.should =~ ['P1', 'm2', 'M2', 'm3', 'M3', 'P4', 'TT', 'P5', 'm6', 'M6', 'm7', 'M7', 'P8']
|
136
|
+
end
|
137
|
+
|
138
|
+
it "is immutable" do
|
139
|
+
lambda{ Intervals::INTERVAL_NAMES << :something }.should raise_error
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
122
143
|
describe ".[]" do
|
123
144
|
it "looks up the constant by name" do
|
124
145
|
Intervals['P1'].should == P1
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::PitchClasses do
|
4
|
+
let(:cases) {
|
5
|
+
[
|
6
|
+
[PitchClass['C'], 'C', 0],
|
7
|
+
[PitchClass['Db'], 'Db', 1],
|
8
|
+
[PitchClass['D'], 'D', 2],
|
9
|
+
[PitchClass['Eb'], 'Eb', 3],
|
10
|
+
[PitchClass['E'], 'E', 4],
|
11
|
+
[PitchClass['F'], 'F', 5],
|
12
|
+
[PitchClass['Gb'], 'Gb', 6],
|
13
|
+
[PitchClass['G'], 'G', 7],
|
14
|
+
[PitchClass['Ab'], 'Ab', 8],
|
15
|
+
[PitchClass['A'], 'A', 9],
|
16
|
+
[PitchClass['Bb'], 'Bb', 10],
|
17
|
+
[PitchClass['B'], 'B', 11],
|
18
|
+
]
|
19
|
+
}
|
20
|
+
|
21
|
+
it "defines constants for the 12 pitch classes in the twelve-tone octave" do
|
22
|
+
cases.length.should == 12
|
23
|
+
cases.each do |const, name, int_value|
|
24
|
+
const.name.should == name
|
25
|
+
const.to_i.should == int_value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "PITCH_CLASSES" do
|
30
|
+
it "contains the 12 pitch class constants" do
|
31
|
+
PitchClasses::PITCH_CLASSES.length.should == 12
|
32
|
+
PitchClasses::PITCH_CLASSES.should == cases.map{ |const,_,__| const }
|
33
|
+
end
|
34
|
+
|
35
|
+
it "is immutable" do
|
36
|
+
lambda{ PitchClasses::PITCH_CLASSES << :something }.should raise_error
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "PITCH_CLASS_NAMES" do
|
41
|
+
it "contains the names of the 12 pitch class constants" do
|
42
|
+
PitchClasses::PITCH_CLASS_NAMES.length.should == 12
|
43
|
+
PitchClasses::PITCH_CLASS_NAMES.should == cases.map{ |_,name,__| name }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "is immutable" do
|
47
|
+
lambda{ PitchClasses::PITCH_CLASS_NAMES << :something }.should raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".[]" do
|
52
|
+
it "acts like PitchClas.[]" do
|
53
|
+
for name in PitchClasses::PITCH_CLASS_NAMES
|
54
|
+
PitchClasses[name].should == PitchClass[name]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Pitches do
|
4
|
+
|
5
|
+
it "defines constants for the 128 notes in MIDI" do
|
6
|
+
Pitches.constants.length.should == 130 # there's also the PITCHES and PITCH_NAMES constants
|
7
|
+
Pitches::C_1.should == Pitch.from_s('C-1')
|
8
|
+
Pitches::D0.should == Pitch.from_s('D0')
|
9
|
+
Pitches::Eb1.should == Pitch.from_s('Eb1')
|
10
|
+
Pitches::G9.should == Pitch.from_s('g9')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "PITCHES" do
|
14
|
+
it "contains all 128 pitch constants" do
|
15
|
+
Pitches::PITCHES.length.should == 128
|
16
|
+
Pitches::PITCHES.should include Pitches::C_1
|
17
|
+
Pitches::PITCHES.should include Pitches::D0
|
18
|
+
Pitches::PITCHES.should include Pitches::Eb1
|
19
|
+
Pitches::PITCHES.should include Pitches::G9
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is immutable" do
|
23
|
+
lambda{ Pitches::PITCHES << :something }.should raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "PITCH_NAMES" do
|
28
|
+
it "contains all 128 pitch constants" do
|
29
|
+
Pitches::PITCH_NAMES.length.should == 128
|
30
|
+
Pitches::PITCH_NAMES.should include 'C_1'
|
31
|
+
Pitches::PITCH_NAMES.should include 'D0'
|
32
|
+
Pitches::PITCH_NAMES.should include 'Eb1'
|
33
|
+
Pitches::PITCH_NAMES.should include 'G9'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "is immutable" do
|
37
|
+
lambda{ Pitches::PITCH_NAMES << :something }.should raise_error
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".[]" do
|
42
|
+
it "acts like Pitch.from_s for the names in PITCH_NAMES, and also treats '_' like '-'" do
|
43
|
+
for name in Pitches::PITCH_NAMES
|
44
|
+
Pitches[name].should == Pitch.from_s(name.sub('_','-')) # the constant names need to use underscores, but Pitch.from_s doesn't understand that
|
45
|
+
if name =~ /_/
|
46
|
+
Pitches[name.sub('_','-')].should == Pitch.from_s(name.sub('_','-')) # make sure '-' works too
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
File without changes
|
data/spec/mtk/event_spec.rb
CHANGED
@@ -24,6 +24,20 @@ describe MTK::Event do
|
|
24
24
|
it "is a read-only attribute" do
|
25
25
|
lambda{ event.duration = 0 }.should raise_error
|
26
26
|
end
|
27
|
+
|
28
|
+
it "is always positive (absolute value of the duration used to construct the Event)" do
|
29
|
+
Event.new(intensity, -duration).duration.should == duration
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#rest?" do
|
34
|
+
it "is true when the duration used to create the Event was negative" do
|
35
|
+
Event.new(intensity, -duration).rest?.should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "is false when the duration used to create the Event was positive" do
|
39
|
+
event.rest?.should be_false
|
40
|
+
end
|
27
41
|
end
|
28
42
|
|
29
43
|
describe "from_hash" do
|
@@ -88,9 +102,14 @@ describe MTK::Event do
|
|
88
102
|
it "converts beats to pulses, given pulses_per_beat" do
|
89
103
|
Event.new(0,1).duration_in_pulses(60).should == 60
|
90
104
|
end
|
105
|
+
|
91
106
|
it "rounds to the nearest pulse" do
|
92
107
|
Event.new(0,1.5).duration_in_pulses(59).should == 89
|
93
108
|
end
|
109
|
+
|
110
|
+
it "is always positive (uses absolute value of the duration used to construct the Event)" do
|
111
|
+
Event.new(intensity, -1).duration_in_pulses(60).should == 60
|
112
|
+
end
|
94
113
|
end
|
95
114
|
|
96
115
|
describe "#==" do
|