mtk 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -2
- data/DEVELOPMENT_NOTES.md +114 -0
- data/INTRO.md +64 -8
- data/LICENSE.txt +1 -1
- data/README.md +31 -102
- data/Rakefile +56 -18
- data/bin/mtk +215 -0
- data/examples/crescendo.rb +5 -5
- data/examples/drum_pattern1.rb +23 -0
- data/examples/dynamic_pattern.rb +8 -11
- data/examples/gets_and_play.rb +26 -0
- data/examples/notation.rb +22 -0
- data/examples/play_midi.rb +8 -10
- data/examples/random_tone_row.rb +2 -2
- data/examples/syntax_to_midi.rb +28 -0
- data/examples/test_output.rb +8 -0
- data/examples/tone_row_melody.rb +6 -6
- data/lib/mtk.rb +52 -40
- data/lib/mtk/chord.rb +55 -0
- data/lib/mtk/constants/durations.rb +57 -0
- data/lib/mtk/constants/intensities.rb +61 -0
- data/lib/mtk/constants/intervals.rb +73 -0
- data/lib/mtk/constants/pitch_classes.rb +29 -0
- data/lib/mtk/constants/pitches.rb +52 -0
- data/lib/mtk/duration.rb +211 -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/helpers/collection.rb +164 -0
- data/lib/mtk/helpers/convert.rb +36 -0
- data/lib/mtk/helpers/lilypond.rb +162 -0
- data/lib/mtk/helpers/output_selector.rb +67 -0
- data/lib/mtk/helpers/pitch_collection.rb +23 -0
- data/lib/mtk/helpers/pseudo_constants.rb +26 -0
- data/lib/mtk/intensity.rb +156 -0
- data/lib/mtk/interval.rb +155 -0
- data/lib/mtk/lang/mtk_grammar.citrus +190 -13
- data/lib/mtk/lang/parser.rb +29 -0
- data/lib/mtk/melody.rb +94 -0
- data/lib/mtk/midi/dls_synth_device.rb +144 -0
- data/lib/mtk/midi/dls_synth_output.rb +62 -0
- data/lib/mtk/midi/file.rb +67 -32
- data/lib/mtk/midi/input.rb +97 -0
- data/lib/mtk/midi/jsound_input.rb +36 -17
- data/lib/mtk/midi/jsound_output.rb +48 -46
- data/lib/mtk/midi/output.rb +195 -0
- data/lib/mtk/midi/unimidi_input.rb +117 -0
- data/lib/mtk/midi/unimidi_output.rb +121 -0
- data/lib/mtk/{_numeric_extensions.rb → numeric_extensions.rb} +12 -0
- data/lib/mtk/patterns/chain.rb +49 -0
- data/lib/mtk/{pattern → patterns}/choice.rb +14 -8
- 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/{pattern → patterns}/lines.rb +11 -17
- data/lib/mtk/{pattern → patterns}/palindrome.rb +11 -8
- data/lib/mtk/patterns/pattern.rb +171 -0
- data/lib/mtk/patterns/sequence.rb +20 -0
- data/lib/mtk/pitch.rb +7 -6
- data/lib/mtk/pitch_class.rb +124 -46
- data/lib/mtk/pitch_class_set.rb +58 -35
- data/lib/mtk/sequencers/event_builder.rb +131 -0
- data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
- data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
- data/lib/mtk/{sequencer/abstract_sequencer.rb → sequencers/sequencer.rb} +37 -11
- data/lib/mtk/{sequencer → sequencers}/step_sequencer.rb +4 -4
- data/lib/mtk/timeline.rb +39 -22
- data/lib/mtk/variable.rb +32 -0
- data/spec/mtk/chord_spec.rb +83 -0
- data/spec/mtk/{_constants → constants}/durations_spec.rb +12 -41
- data/spec/mtk/{_constants → constants}/intensities_spec.rb +13 -37
- data/spec/mtk/{_constants → constants}/intervals_spec.rb +14 -32
- data/spec/mtk/{_constants → constants}/pitch_classes_spec.rb +8 -4
- data/spec/mtk/{_constants → constants}/pitches_spec.rb +5 -1
- data/spec/mtk/duration_spec.rb +372 -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/{helper → helpers}/collection_spec.rb +86 -3
- data/spec/mtk/{helper → helpers}/pseudo_constants_spec.rb +2 -2
- data/spec/mtk/intensity_spec.rb +289 -0
- data/spec/mtk/interval_spec.rb +265 -0
- data/spec/mtk/lang/parser_spec.rb +597 -0
- data/spec/mtk/melody_spec.rb +223 -0
- data/spec/mtk/midi/file_spec.rb +16 -16
- data/spec/mtk/midi/jsound_input_spec.rb +11 -0
- data/spec/mtk/midi/jsound_output_spec.rb +11 -0
- data/spec/mtk/midi/output_spec.rb +102 -0
- data/spec/mtk/midi/unimidi_input_spec.rb +11 -0
- data/spec/mtk/midi/unimidi_output_spec.rb +11 -0
- data/spec/mtk/{_numeric_extensions_spec.rb → numeric_extensions_spec.rb} +1 -0
- data/spec/mtk/patterns/chain_spec.rb +110 -0
- data/spec/mtk/{pattern → patterns}/choice_spec.rb +20 -30
- data/spec/mtk/{pattern → patterns}/cycle_spec.rb +25 -35
- data/spec/mtk/patterns/for_each_spec.rb +136 -0
- data/spec/mtk/{pattern → patterns}/function_spec.rb +17 -30
- data/spec/mtk/{pattern → patterns}/lines_spec.rb +11 -27
- data/spec/mtk/{pattern → patterns}/palindrome_spec.rb +13 -29
- data/spec/mtk/patterns/pattern_spec.rb +132 -0
- data/spec/mtk/patterns/sequence_spec.rb +203 -0
- data/spec/mtk/pitch_class_set_spec.rb +23 -21
- data/spec/mtk/pitch_class_spec.rb +151 -39
- data/spec/mtk/pitch_spec.rb +22 -1
- 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/{sequencer → sequencers}/step_sequencer_spec.rb +35 -13
- data/spec/mtk/timeline_spec.rb +109 -16
- data/spec/mtk/variable_spec.rb +52 -0
- data/spec/spec_coverage.rb +2 -0
- data/spec/spec_helper.rb +3 -0
- metadata +188 -91
- data/lib/mtk/_constants/durations.rb +0 -80
- data/lib/mtk/_constants/intensities.rb +0 -81
- data/lib/mtk/_constants/intervals.rb +0 -85
- data/lib/mtk/_constants/pitch_classes.rb +0 -35
- data/lib/mtk/_constants/pitches.rb +0 -49
- data/lib/mtk/event.rb +0 -70
- data/lib/mtk/helper/collection.rb +0 -114
- data/lib/mtk/helper/event_builder.rb +0 -85
- data/lib/mtk/helper/pseudo_constants.rb +0 -26
- data/lib/mtk/lang/grammar.rb +0 -17
- data/lib/mtk/note.rb +0 -63
- data/lib/mtk/pattern/abstract_pattern.rb +0 -132
- data/lib/mtk/pattern/cycle.rb +0 -51
- data/lib/mtk/pattern/enumerator.rb +0 -26
- data/lib/mtk/pattern/function.rb +0 -46
- data/lib/mtk/pattern/sequence.rb +0 -30
- data/lib/mtk/pitch_set.rb +0 -84
- data/lib/mtk/sequencer/rhythmic_sequencer.rb +0 -29
- data/lib/mtk/transform/invertible.rb +0 -15
- data/lib/mtk/transform/mappable.rb +0 -18
- data/lib/mtk/transform/set_theory_operations.rb +0 -34
- data/lib/mtk/transform/transposable.rb +0 -14
- data/spec/mtk/event_spec.rb +0 -139
- data/spec/mtk/helper/event_builder_spec.rb +0 -92
- data/spec/mtk/lang/grammar_spec.rb +0 -100
- data/spec/mtk/note_spec.rb +0 -115
- data/spec/mtk/pattern/abstract_pattern_spec.rb +0 -45
- data/spec/mtk/pattern/note_cycle_spec.rb.bak +0 -116
- data/spec/mtk/pattern/pitch_cycle_spec.rb.bak +0 -47
- data/spec/mtk/pattern/pitch_sequence_spec.rb.bak +0 -37
- data/spec/mtk/pattern/sequence_spec.rb +0 -151
- data/spec/mtk/pitch_set_spec.rb +0 -198
- data/spec/mtk/sequencer/abstract_sequencer_spec.rb +0 -159
- data/spec/mtk/sequencer/rhythmic_sequencer_spec.rb +0 -49
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::
|
3
|
+
describe MTK::Patterns::Function do
|
4
4
|
|
5
|
-
FUNCTION = MTK::
|
5
|
+
FUNCTION = MTK::Patterns::Function
|
6
6
|
|
7
7
|
describe "#next" do
|
8
8
|
it "calls a lambda to produce elements" do
|
@@ -35,7 +35,7 @@ describe MTK::Pattern::Function do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it "calls a 3-arg lambda with the previous value, function call count (starting from 0), and element count (starting from 0)" do
|
38
|
-
function = FUNCTION.new lambda{|prev,call_index,elem_index| prev.nil? ? MTK::
|
38
|
+
function = FUNCTION.new lambda{|prev,call_index,elem_index| prev.nil? ? MTK::Patterns.Sequence(1,2,3,4) : [call_index,elem_index] }
|
39
39
|
function.next.should == 1
|
40
40
|
function.next.should == 2
|
41
41
|
function.next.should == 3
|
@@ -44,7 +44,7 @@ describe MTK::Pattern::Function do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "can generate other Patterns, which will be iterated over before re-calling the function" do
|
47
|
-
function = FUNCTION.new lambda{|prev,index| MTK::
|
47
|
+
function = FUNCTION.new lambda{|prev,index| MTK::Patterns.Sequence(index,2,3) }
|
48
48
|
function.next.should == 0
|
49
49
|
function.next.should == 2
|
50
50
|
function.next.should == 3
|
@@ -67,66 +67,53 @@ describe MTK::Pattern::Function do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
|
70
|
-
describe MTK::
|
70
|
+
describe MTK::Patterns do
|
71
|
+
|
72
|
+
let(:mock_lambda) { lambda{|_|:mock_value} }
|
71
73
|
|
72
74
|
describe "#Function" do
|
73
75
|
it "creates a Function" do
|
74
|
-
MTK::
|
76
|
+
MTK::Patterns.Function(nil).should be_a MTK::Patterns::Function
|
75
77
|
end
|
76
78
|
|
77
79
|
it "sets #elements from the varargs" do
|
78
|
-
MTK::
|
79
|
-
end
|
80
|
-
|
81
|
-
it "does not set a type" do
|
82
|
-
MTK::Pattern.Function(:mock_lambda).type.should be_nil
|
80
|
+
MTK::Patterns.Function(:mock_lambda).function.should == :mock_lambda
|
83
81
|
end
|
84
82
|
|
85
83
|
it "doesn't wrap a lambda in the varargs Array" do
|
86
|
-
function = MTK::
|
84
|
+
function = MTK::Patterns.Function( lambda{ 1 + 1 } )
|
87
85
|
function.next.should == 2
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
91
89
|
describe "#PitchFunction" do
|
92
90
|
it "creates a Function" do
|
93
|
-
MTK::
|
91
|
+
MTK::Patterns.PitchFunction(mock_lambda).should be_a MTK::Patterns::Function
|
94
92
|
end
|
95
93
|
|
96
94
|
it "sets #elements from the varargs" do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
it "sets #type to :pitch" do
|
101
|
-
MTK::Pattern.PitchFunction([]).type.should == :pitch
|
95
|
+
func = mock_lambda
|
96
|
+
MTK::Patterns.PitchFunction(func).function.should == func
|
102
97
|
end
|
103
98
|
end
|
104
99
|
|
105
100
|
describe "#IntensityFunction" do
|
106
101
|
it "creates a Function" do
|
107
|
-
MTK::
|
102
|
+
MTK::Patterns.IntensityFunction(mock_lambda).should be_a MTK::Patterns::Function
|
108
103
|
end
|
109
104
|
|
110
105
|
it "sets #elements from the varargs" do
|
111
|
-
MTK::
|
112
|
-
end
|
113
|
-
|
114
|
-
it "sets #type to :pitch" do
|
115
|
-
MTK::Pattern.IntensityFunction([]).type.should == :intensity
|
106
|
+
MTK::Patterns.IntensityFunction(mock_lambda).function.should == mock_lambda
|
116
107
|
end
|
117
108
|
end
|
118
109
|
|
119
110
|
describe "#DurationFunction" do
|
120
111
|
it "creates a Function" do
|
121
|
-
MTK::
|
112
|
+
MTK::Patterns.DurationFunction(mock_lambda).should be_a MTK::Patterns::Function
|
122
113
|
end
|
123
114
|
|
124
115
|
it "sets #elements from the varargs" do
|
125
|
-
MTK::
|
126
|
-
end
|
127
|
-
|
128
|
-
it "sets #type to :pitch" do
|
129
|
-
MTK::Pattern.DurationFunction([]).type.should == :duration
|
116
|
+
MTK::Patterns.DurationFunction(mock_lambda).function.should == mock_lambda
|
130
117
|
end
|
131
118
|
end
|
132
119
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::
|
3
|
+
describe MTK::Patterns::Lines do
|
4
4
|
|
5
|
-
LINES = MTK::
|
5
|
+
LINES = MTK::Patterns::Lines
|
6
6
|
|
7
7
|
let(:elements) { [0, [10,5], [5,10]] }
|
8
8
|
let(:lines) { LINES.new elements }
|
@@ -32,61 +32,45 @@ describe MTK::Pattern::Lines do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
|
35
|
-
describe MTK::
|
35
|
+
describe MTK::Patterns do
|
36
36
|
|
37
37
|
describe "#Lines" do
|
38
38
|
it "creates a Lines" do
|
39
|
-
MTK::
|
39
|
+
MTK::Patterns.Lines(1,2,3).should be_a MTK::Patterns::Lines
|
40
40
|
end
|
41
41
|
|
42
42
|
it "sets #elements from the varargs" do
|
43
|
-
MTK::
|
44
|
-
end
|
45
|
-
|
46
|
-
it "does not set a type" do
|
47
|
-
MTK::Pattern.Lines(1,2,3).type.should be_nil
|
43
|
+
MTK::Patterns.Lines(1,2,3).elements.should == [1,2,3]
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
51
47
|
describe "#PitchLines" do
|
52
48
|
it "creates a Lines" do
|
53
|
-
MTK::
|
49
|
+
MTK::Patterns.PitchLines(1,2,3).should be_a MTK::Patterns::Lines
|
54
50
|
end
|
55
51
|
|
56
52
|
it "sets #elements from the varargs" do
|
57
|
-
MTK::
|
58
|
-
end
|
59
|
-
|
60
|
-
it "sets #type to :pitch" do
|
61
|
-
MTK::Pattern.PitchLines([]).type.should == :pitch
|
53
|
+
MTK::Patterns.PitchLines(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
|
62
54
|
end
|
63
55
|
end
|
64
56
|
|
65
57
|
describe "#IntensityLines" do
|
66
58
|
it "creates a Lines" do
|
67
|
-
MTK::
|
59
|
+
MTK::Patterns.IntensityLines(1,2,3).should be_a MTK::Patterns::Lines
|
68
60
|
end
|
69
61
|
|
70
62
|
it "sets #elements from the varargs" do
|
71
|
-
MTK::
|
72
|
-
end
|
73
|
-
|
74
|
-
it "sets #type to :pitch" do
|
75
|
-
MTK::Pattern.IntensityLines([]).type.should == :intensity
|
63
|
+
MTK::Patterns.IntensityLines(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
|
76
64
|
end
|
77
65
|
end
|
78
66
|
|
79
67
|
describe "#DurationLines" do
|
80
68
|
it "creates a Lines" do
|
81
|
-
MTK::
|
69
|
+
MTK::Patterns.DurationLines(1,2,3).should be_a MTK::Patterns::Lines
|
82
70
|
end
|
83
71
|
|
84
72
|
it "sets #elements from the varargs" do
|
85
|
-
MTK::
|
86
|
-
end
|
87
|
-
|
88
|
-
it "sets #type to :pitch" do
|
89
|
-
MTK::Pattern.DurationLines([]).type.should == :duration
|
73
|
+
MTK::Patterns.DurationLines(1,2,3).elements.should == [Duration(1),Duration(2),Duration(3)]
|
90
74
|
end
|
91
75
|
end
|
92
76
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::
|
3
|
+
describe MTK::Patterns::Palindrome do
|
4
4
|
|
5
|
-
PALINDROME = MTK::
|
5
|
+
PALINDROME = MTK::Patterns::Palindrome
|
6
6
|
|
7
7
|
describe "#next" do
|
8
8
|
it "reverses direction when the ends of the list are reached" do
|
@@ -20,14 +20,14 @@ describe MTK::Pattern::Palindrome do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "enumerates nested sequences" do
|
23
|
-
palindrome = PALINDROME.new [1, MTK::
|
23
|
+
palindrome = PALINDROME.new [1, MTK::Patterns.Sequence(2,3), 4]
|
24
24
|
nexts = []
|
25
25
|
10.times { nexts << palindrome.next }
|
26
26
|
nexts.should == [1,2,3,4, 2,3,1, 2,3,4] # note sequence goes forward in both directions!
|
27
27
|
end
|
28
28
|
|
29
29
|
it "enumerates nested sequences, and repeats the last element" do
|
30
|
-
palindrome = PALINDROME.new [1, MTK::
|
30
|
+
palindrome = PALINDROME.new [1, MTK::Patterns.Sequence(2,3), 4], :repeat_ends => true
|
31
31
|
nexts = []
|
32
32
|
9.times { nexts << palindrome.next }
|
33
33
|
nexts.should == [1,2,3,4, 4,2,3,1, 1] # note sequence goes forward in both directions!
|
@@ -63,61 +63,45 @@ describe MTK::Pattern::Palindrome do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
|
66
|
-
describe MTK::
|
66
|
+
describe MTK::Patterns do
|
67
67
|
|
68
68
|
describe "#Palindrome" do
|
69
69
|
it "creates a Palindrome" do
|
70
|
-
MTK::
|
70
|
+
MTK::Patterns.Palindrome(1,2,3).should be_a MTK::Patterns::Palindrome
|
71
71
|
end
|
72
72
|
|
73
73
|
it "sets #elements from the varargs" do
|
74
|
-
MTK::
|
75
|
-
end
|
76
|
-
|
77
|
-
it "does not set a type" do
|
78
|
-
MTK::Pattern.Palindrome(1,2,3).type.should be_nil
|
74
|
+
MTK::Patterns.Palindrome(1,2,3).elements.should == [1,2,3]
|
79
75
|
end
|
80
76
|
end
|
81
77
|
|
82
78
|
describe "#PitchPalindrome" do
|
83
79
|
it "creates a Palindrome" do
|
84
|
-
MTK::
|
80
|
+
MTK::Patterns.PitchPalindrome(1,2,3).should be_a MTK::Patterns::Palindrome
|
85
81
|
end
|
86
82
|
|
87
83
|
it "sets #elements from the varargs" do
|
88
|
-
MTK::
|
89
|
-
end
|
90
|
-
|
91
|
-
it "sets #type to :pitch" do
|
92
|
-
MTK::Pattern.PitchPalindrome([]).type.should == :pitch
|
84
|
+
MTK::Patterns.PitchPalindrome(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
|
93
85
|
end
|
94
86
|
end
|
95
87
|
|
96
88
|
describe "#IntensityPalindrome" do
|
97
89
|
it "creates a Palindrome" do
|
98
|
-
MTK::
|
90
|
+
MTK::Patterns.IntensityPalindrome(1,2,3).should be_a MTK::Patterns::Palindrome
|
99
91
|
end
|
100
92
|
|
101
93
|
it "sets #elements from the varargs" do
|
102
|
-
MTK::
|
103
|
-
end
|
104
|
-
|
105
|
-
it "sets #type to :pitch" do
|
106
|
-
MTK::Pattern.IntensityPalindrome([]).type.should == :intensity
|
94
|
+
MTK::Patterns.IntensityPalindrome(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
|
107
95
|
end
|
108
96
|
end
|
109
97
|
|
110
98
|
describe "#DurationPalindrome" do
|
111
99
|
it "creates a Palindrome" do
|
112
|
-
MTK::
|
100
|
+
MTK::Patterns.DurationPalindrome(1,2,3).should be_a MTK::Patterns::Palindrome
|
113
101
|
end
|
114
102
|
|
115
103
|
it "sets #elements from the varargs" do
|
116
|
-
MTK::
|
117
|
-
end
|
118
|
-
|
119
|
-
it "sets #type to :pitch" do
|
120
|
-
MTK::Pattern.DurationPalindrome([]).type.should == :duration
|
104
|
+
MTK::Patterns.DurationPalindrome(1,2,3).elements.should == [Duration(1),Duration(2),Duration(3)]
|
121
105
|
end
|
122
106
|
end
|
123
107
|
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Patterns::Pattern do
|
4
|
+
|
5
|
+
PATTERN = MTK::Patterns::Pattern
|
6
|
+
|
7
|
+
let(:elements) { [1,2,3] }
|
8
|
+
|
9
|
+
|
10
|
+
describe "@min_elements" do
|
11
|
+
it "is the :min_elements option the pattern was constructed with" do
|
12
|
+
PATTERN.new([], min_elements: 1).min_elements.should == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it "is nil by default" do
|
16
|
+
PATTERN.new([]).min_elements.should be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "prevents a StopIteration error until min_elements have been emitted (overriding max_elements if necessary)" do
|
20
|
+
pattern = PATTERN.new([1,2,3], min_elements: 5, max_elements: 3)
|
21
|
+
5.times{ pattern.next }
|
22
|
+
lambda{ pattern.next }.should raise_error StopIteration
|
23
|
+
end
|
24
|
+
|
25
|
+
it "sets exactly how many elements will be emitted when set to the same values as max_elements" do
|
26
|
+
pattern = PATTERN.new([1,2,3], min_elements: 5, max_elements: 5)
|
27
|
+
5.times{ pattern.next }
|
28
|
+
lambda{ pattern.next }.should raise_error StopIteration
|
29
|
+
end
|
30
|
+
|
31
|
+
it "is maintained when applying Collection operations" do
|
32
|
+
PATTERN.new(elements, min_elements: 2).reverse.min_elements.should == 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#min_elements_unmet?' do
|
37
|
+
it "is true until min_elements have been emitted" do
|
38
|
+
pattern = PATTERN.new([:anything], min_elements: 5)
|
39
|
+
5.times { pattern.min_elements_unmet?.should be_true and pattern.next }
|
40
|
+
pattern.min_elements_unmet?.should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is always false if min_elements is not set" do
|
44
|
+
pattern = PATTERN.new([:anything], min_elements: nil)
|
45
|
+
5.times { pattern.min_elements_unmet?.should be_false and pattern.next }
|
46
|
+
end
|
47
|
+
|
48
|
+
it "is always false if min_elements is 0" do
|
49
|
+
pattern = PATTERN.new([:anything], min_elements: 0)
|
50
|
+
5.times { pattern.min_elements_unmet?.should be_false and pattern.next }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
describe "@max_elements" do
|
56
|
+
it "is the :max_elements option the pattern was constructed with" do
|
57
|
+
PATTERN.new([], max_elements: 1).max_elements.should == 1
|
58
|
+
end
|
59
|
+
|
60
|
+
it "is nil by default" do
|
61
|
+
PATTERN.new([]).max_elements.should be_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
it "causes a StopIteration exception once max_elements have been emitted" do
|
65
|
+
pattern = PATTERN.new([:anything], max_elements: 5)
|
66
|
+
5.times { pattern.next }
|
67
|
+
lambda { pattern.next }.should raise_error
|
68
|
+
end
|
69
|
+
|
70
|
+
it "raises a StopIteration error when a nested pattern has emitted more than max_elements" do
|
71
|
+
pattern = PATTERN.new([Patterns.Cycle(1,2)], max_elements: 5)
|
72
|
+
5.times{ pattern.next }
|
73
|
+
lambda{ pattern.next }.should raise_error StopIteration
|
74
|
+
end
|
75
|
+
|
76
|
+
it "is maintained when applying Collection operations" do
|
77
|
+
PATTERN.new(elements, max_elements: 2).reverse.max_elements.should == 2
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
describe '#max_elements_exceeded?' do
|
83
|
+
it "is false until max_elements have been emitted" do
|
84
|
+
pattern = PATTERN.new([:anything], max_elements: 5)
|
85
|
+
5.times { pattern.max_elements_exceeded?.should be_false and pattern.next }
|
86
|
+
pattern.max_elements_exceeded?.should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "is always false when max_elements is not set" do
|
90
|
+
pattern = PATTERN.new([:anything], max_elements: nil)
|
91
|
+
5.times { pattern.max_elements_exceeded?.should be_false and pattern.next }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
describe "@max_cycles" do
|
97
|
+
it "is the :max_cycles option the pattern was constructed with" do
|
98
|
+
PATTERN.new([], max_cycles: 2).max_cycles.should == 2
|
99
|
+
end
|
100
|
+
|
101
|
+
it "is 1 by default" do
|
102
|
+
PATTERN.new([]).max_cycles.should == 1
|
103
|
+
end
|
104
|
+
|
105
|
+
it "is maintained when applying Collection operations" do
|
106
|
+
PATTERN.new(elements, max_cycles: 2).reverse.max_cycles.should == 2
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
describe "#next" do
|
112
|
+
it "raises StopIteration if elements is empty" do
|
113
|
+
lambda{ PATTERN.new([]).next }.should raise_error StopIteration
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
describe "#==" do
|
119
|
+
it "is true if the elements and types are equal" do
|
120
|
+
PATTERN.new(elements, :type => :some_type).should == PATTERN.new(elements, :type => :some_type)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "is false if the elements are not equal" do
|
124
|
+
PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements + [4], :type => :some_type)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "is false if the types are not equal" do
|
128
|
+
PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements, :type => :another_type)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Patterns::Sequence do
|
4
|
+
|
5
|
+
SEQUENCE = MTK::Patterns::Sequence
|
6
|
+
|
7
|
+
let(:elements) { [1,2,3] }
|
8
|
+
let(:sequence) { SEQUENCE.new(elements) }
|
9
|
+
|
10
|
+
it "is a MTK::Collection" do
|
11
|
+
sequence.should be_a MTK::Helpers::Collection
|
12
|
+
# and now we won't test any other collection features here... see collection_spec
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ".from_a" do
|
16
|
+
it "acts like .new" do
|
17
|
+
SEQUENCE.from_a(elements).should == sequence
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#elements" do
|
22
|
+
it "is the array the sequence was constructed with" do
|
23
|
+
sequence.elements.should == elements
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#next" do
|
28
|
+
it "enumerates the elements" do
|
29
|
+
nexts = []
|
30
|
+
elements.length.times do
|
31
|
+
nexts << sequence.next
|
32
|
+
end
|
33
|
+
nexts.should == elements
|
34
|
+
end
|
35
|
+
|
36
|
+
it "raises StopIteration when the end of the Sequence is reached" do
|
37
|
+
elements.length.times{ sequence.next }
|
38
|
+
lambda{ sequence.next }.should raise_error(StopIteration)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should automatically break out of Kernel#loop" do
|
42
|
+
nexts = []
|
43
|
+
loop do # loop rescues StopIteration and exits the loop
|
44
|
+
nexts << sequence.next
|
45
|
+
end
|
46
|
+
nexts.should == elements
|
47
|
+
end
|
48
|
+
|
49
|
+
it "enumerates the elements in sub-sequences" do
|
50
|
+
sub_sequence = SEQUENCE.new [2,3]
|
51
|
+
sequence = SEQUENCE.new [1,sub_sequence,4]
|
52
|
+
nexts = []
|
53
|
+
loop { nexts << sequence.next }
|
54
|
+
nexts.should == [1,2,3,4]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "skips over empty sub-sequences" do
|
58
|
+
sub_sequence = SEQUENCE.new []
|
59
|
+
sequence = SEQUENCE.new [1,sub_sequence,4]
|
60
|
+
nexts = []
|
61
|
+
loop { nexts << sequence.next }
|
62
|
+
nexts.should == [1,4]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "@min_elements" do
|
68
|
+
it "prevents a StopIteration error until min_elements have been emitted" do
|
69
|
+
pattern = SEQUENCE.new([1,2,3], cycle_count: 1, min_elements: 5)
|
70
|
+
5.times{ pattern.next }
|
71
|
+
lambda{ pattern.next }.should raise_error StopIteration
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
describe "@max_cycles" do
|
77
|
+
it "is the :max_cycles option the pattern was constructed with" do
|
78
|
+
SEQUENCE.new( [], max_cycles: 2 ).max_cycles.should == 2
|
79
|
+
end
|
80
|
+
|
81
|
+
it "is 1 by default" do
|
82
|
+
SEQUENCE.new( [] ).max_cycles.should == 1
|
83
|
+
end
|
84
|
+
|
85
|
+
it "loops indefinitely when it's nil" do
|
86
|
+
sequence = SEQUENCE.new( [1], max_cycles: nil )
|
87
|
+
lambda { 100.times { sequence.next } }.should_not raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
it "causes a StopIteration exception after the number of cycles has completed" do
|
91
|
+
sequence = SEQUENCE.new( elements, max_cycles: 2 )
|
92
|
+
2.times do
|
93
|
+
elements.length.times { sequence.next } # one full cycle
|
94
|
+
end
|
95
|
+
lambda { sequence.next }.should raise_error StopIteration
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
describe "#max_cycles_exceeded?" do
|
101
|
+
it "is false until max_elements have been emitted" do
|
102
|
+
sequence = SEQUENCE.new( elements, max_cycles: 2 )
|
103
|
+
2.times do
|
104
|
+
sequence.max_cycles_exceeded?.should be_false
|
105
|
+
elements.length.times { sequence.next } # one full cycle
|
106
|
+
end
|
107
|
+
# unlike with element_count and max_elements_exceeded?, cycle_count doesn't get bumped until
|
108
|
+
# you ask for the next element and a StopIteration is thrown
|
109
|
+
lambda { sequence.next }.should raise_error StopIteration
|
110
|
+
sequence.max_cycles_exceeded?.should be_true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "is always false when max_cycles is not set" do
|
114
|
+
pattern = PATTERN.new([:anything], max_cycles: nil)
|
115
|
+
15.times { pattern.max_cycles_exceeded?.should be_false and pattern.next }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
it "has max_elements_exceeded once max_elements have been emitted (edge case, has same number of elements)" do
|
121
|
+
sequence = SEQUENCE.new([1,2,3,4,5], :max_elements => 5)
|
122
|
+
5.times { sequence.max_elements_exceeded?.should(be_false) and sequence.next }
|
123
|
+
sequence.max_elements_exceeded?.should be_true
|
124
|
+
lambda { sequence.next }.should raise_error StopIteration
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
it "raises a StopIteration error when a nested pattern has emitted more than max_elements" do
|
129
|
+
sequence = SEQUENCE.new([Patterns.Cycle(1,2)], :max_elements => 5)
|
130
|
+
5.times { sequence.next }
|
131
|
+
lambda{ sequence.next }.should raise_error StopIteration
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
describe "#rewind" do
|
136
|
+
it "restarts at the beginning of the sequence" do
|
137
|
+
loop { sequence.next }
|
138
|
+
sequence.rewind
|
139
|
+
sequence.next.should == elements.first
|
140
|
+
end
|
141
|
+
|
142
|
+
it "returns self, so it can be chained to #next" do
|
143
|
+
first = sequence.next
|
144
|
+
sequence.rewind.next.should == first
|
145
|
+
end
|
146
|
+
|
147
|
+
it "causes sub-sequences to start from the beginning when encountered again after #rewind" do
|
148
|
+
sub_sequence = SEQUENCE.new [2,3]
|
149
|
+
sequence = SEQUENCE.new [1,sub_sequence,4]
|
150
|
+
loop { sequence.next }
|
151
|
+
sequence.rewind
|
152
|
+
nexts = []
|
153
|
+
loop { nexts << sequence.next }
|
154
|
+
nexts.should == [1,2,3,4]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
describe MTK::Patterns do
|
162
|
+
|
163
|
+
describe "#Sequence" do
|
164
|
+
it "creates a Sequence" do
|
165
|
+
MTK::Patterns.Sequence(1,2,3).should be_a MTK::Patterns::Sequence
|
166
|
+
end
|
167
|
+
|
168
|
+
it "sets #elements from the varargs" do
|
169
|
+
MTK::Patterns.Sequence(1,2,3).elements.should == [1,2,3]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#PitchSequence" do
|
174
|
+
it "creates a Sequence" do
|
175
|
+
MTK::Patterns.PitchSequence(1,2,3).should be_a MTK::Patterns::Sequence
|
176
|
+
end
|
177
|
+
|
178
|
+
it "sets #elements from the varargs" do
|
179
|
+
MTK::Patterns.PitchSequence(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#IntensitySequence" do
|
184
|
+
it "creates a Sequence" do
|
185
|
+
MTK::Patterns.IntensitySequence(1,2,3).should be_a MTK::Patterns::Sequence
|
186
|
+
end
|
187
|
+
|
188
|
+
it "sets #elements from the varargs" do
|
189
|
+
MTK::Patterns.IntensitySequence(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "#DurationSequence" do
|
194
|
+
it "creates a Sequence" do
|
195
|
+
MTK::Patterns.DurationSequence(1,2,3).should be_a MTK::Patterns::Sequence
|
196
|
+
end
|
197
|
+
|
198
|
+
it "sets #elements from the varargs" do
|
199
|
+
MTK::Patterns.DurationSequence(1,2,3).elements.should == [Duration(1),Duration(2),Duration(3)]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|