mtk 0.0.2 → 0.0.3
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 +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
|