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
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Patterns::Chain do
|
4
|
+
|
5
|
+
CHAIN = MTK::Patterns::Chain
|
6
|
+
|
7
|
+
describe '#next' do
|
8
|
+
it 'combines 2 basic attributes together' do
|
9
|
+
chain = CHAIN.new [C,q]
|
10
|
+
chain.next.should == [C,q]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'combines 3 basic attributes together' do
|
14
|
+
chain = CHAIN.new [C,q,mp]
|
15
|
+
chain.next.should == [C,q,mp]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'combines many basic attributes together, including duplicate types' do
|
19
|
+
chain = CHAIN.new [C,q,D,h,s,mp,fff]
|
20
|
+
chain.next.should == [C,q,D,h,s,mp,fff]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'raises StopIteration after a basic-attribute-only chain has called #next more than once' do
|
24
|
+
chain = CHAIN.new [C,q]
|
25
|
+
chain.next
|
26
|
+
lambda{ chain.next }.should raise_error StopIteration
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'combines a basic attribute with a pattern' do
|
30
|
+
chain = CHAIN.new [Patterns.Sequence(C,D,E), q]
|
31
|
+
chain.next.should == [C,q]
|
32
|
+
chain.next.should == [D,q]
|
33
|
+
chain.next.should == [E,q]
|
34
|
+
lambda{ chain.next }.should raise_error StopIteration
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'combines 2 patterns' do
|
38
|
+
chain = CHAIN.new [Patterns.Sequence(C,D,E), Patterns.Sequence(w,h,q)]
|
39
|
+
chain.next.should == [C,w]
|
40
|
+
chain.next.should == [D,h]
|
41
|
+
chain.next.should == [E,q]
|
42
|
+
lambda{ chain.next }.should raise_error StopIteration
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'combines 2 patterns, and returns #next until the last StopIteration of a nested Pattern occurs' do
|
46
|
+
chain = CHAIN.new [Patterns.Sequence(C,D,E), Patterns.Sequence(w,h,q,i)]
|
47
|
+
chain.next.should == [C,w]
|
48
|
+
chain.next.should == [D,h]
|
49
|
+
chain.next.should == [E,q]
|
50
|
+
chain.next.should == [C,i]
|
51
|
+
lambda{ chain.next }.should raise_error StopIteration
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# TODO: more than 2 patterns, and more than 2 + basic attribute(s)
|
56
|
+
|
57
|
+
|
58
|
+
it 'combines Choice patterns with max_cycles' do
|
59
|
+
chain = CHAIN.new [Patterns.Choice(i,s), Patterns.Choice(C,D,E)], max_cycles:100
|
60
|
+
100.times do |time|
|
61
|
+
attrs = chain.next
|
62
|
+
attrs.length.should == 2
|
63
|
+
(attrs[0]==i or attrs[0]==s).should be_true
|
64
|
+
(attrs[1]==C or attrs[1]==D or attrs[1]==E).should be_true
|
65
|
+
end
|
66
|
+
lambda{ chain.next }.should raise_error StopIteration
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'combines Choice patterns and emits a only single combination of attributes by default' do
|
70
|
+
chain = CHAIN.new [Patterns.Choice(i,s), Patterns.Choice(C,D,E)]
|
71
|
+
chain.next
|
72
|
+
lambda{ chain.next }.should raise_error StopIteration
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'flattens attribute lists with nested chains' do
|
76
|
+
chain = CHAIN.new( [1, 2, CHAIN.new([3, CHAIN.new([4,5])])] )
|
77
|
+
chain.next.should == [1,2,3,4,5]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'throws StopIteration when any subpattern throws StopIteration with max_elements_exceeded' do
|
81
|
+
chain = CHAIN.new [Patterns.Sequence(C,D,E,F,G), Patterns.Sequence(w,h,q,i, max_elements:3)]
|
82
|
+
chain.next.should == [C,w]
|
83
|
+
chain.next.should == [D,h]
|
84
|
+
chain.next.should == [E,q]
|
85
|
+
lambda{ chain.next }.should raise_error StopIteration
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'throws StopIteration with max_elements_exceeded (edge case actual element length == max_elements)' do
|
89
|
+
chain = CHAIN.new [Patterns.Sequence(C,D,E,F,G), Patterns.Sequence(w,h,q, max_elements:3)]
|
90
|
+
chain.next.should == [C,w]
|
91
|
+
chain.next.should == [D,h]
|
92
|
+
chain.next.should == [E,q]
|
93
|
+
lambda{ chain.next }.should raise_error StopIteration
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#rewind' do
|
98
|
+
it 'resets the state of the Chain' do
|
99
|
+
# compare with the #next, raises StopIteration test above
|
100
|
+
chain = CHAIN.new [C,q]
|
101
|
+
chain.next
|
102
|
+
chain.rewind
|
103
|
+
lambda{ chain.next }.should_not raise_error StopIteration
|
104
|
+
lambda{ chain.next }.should raise_error StopIteration
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# TODO: test the chain builder method in Patterns module
|
109
|
+
|
110
|
+
end
|
@@ -1,14 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'set'
|
3
3
|
|
4
|
-
describe MTK::
|
4
|
+
describe MTK::Patterns::Choice do
|
5
5
|
|
6
|
-
CHOICE = MTK::
|
6
|
+
CHOICE = MTK::Patterns::Choice
|
7
7
|
|
8
8
|
let(:elements) { [1,2,3] }
|
9
|
-
let(:choice) { CHOICE.new elements }
|
9
|
+
let(:choice) { CHOICE.new elements, max_cycles:500 }
|
10
10
|
|
11
11
|
describe "#next" do
|
12
|
+
it "throws StopIteration on the second call to #next, by default" do
|
13
|
+
choice = CHOICE.new elements
|
14
|
+
choice.next
|
15
|
+
lambda{ choice.next }.should raise_error StopIteration
|
16
|
+
end
|
17
|
+
|
12
18
|
it "randomly chooses one of the elements" do
|
13
19
|
choosen = Set.new
|
14
20
|
100.times do
|
@@ -19,7 +25,7 @@ describe MTK::Pattern::Choice do
|
|
19
25
|
end
|
20
26
|
|
21
27
|
it "does a weighted random selection when a weights list is passed in via constructor options[:weights]" do
|
22
|
-
choice = CHOICE.new elements, :weights
|
28
|
+
choice = CHOICE.new elements, max_cycles:100, weights:[1,3,0] # only choose first 2 elements, and choose the second three times as often
|
23
29
|
choosen = Set.new
|
24
30
|
first_count, second_count = 0,0
|
25
31
|
100.times do
|
@@ -33,7 +39,7 @@ describe MTK::Pattern::Choice do
|
|
33
39
|
end
|
34
40
|
|
35
41
|
it "enumerates a choosen sub-sequence" do
|
36
|
-
choice = CHOICE.new [MTK::
|
42
|
+
choice = CHOICE.new [MTK::Patterns.Sequence(4,5,6)], max_cycles:10
|
37
43
|
choice.next.should == 4
|
38
44
|
choice.next.should == 5
|
39
45
|
choice.next.should == 6
|
@@ -46,61 +52,45 @@ describe MTK::Pattern::Choice do
|
|
46
52
|
end
|
47
53
|
|
48
54
|
|
49
|
-
describe MTK::
|
55
|
+
describe MTK::Patterns do
|
50
56
|
|
51
57
|
describe "#Choice" do
|
52
58
|
it "creates a Choice" do
|
53
|
-
MTK::
|
59
|
+
MTK::Patterns.Choice(1,2,3).should be_a MTK::Patterns::Choice
|
54
60
|
end
|
55
61
|
|
56
62
|
it "sets #elements from the varargs" do
|
57
|
-
MTK::
|
58
|
-
end
|
59
|
-
|
60
|
-
it "does not set a type" do
|
61
|
-
MTK::Pattern.Choice(1,2,3).type.should be_nil
|
63
|
+
MTK::Patterns.Choice(1,2,3).elements.should == [1,2,3]
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
67
|
describe "#PitchChoice" do
|
66
68
|
it "creates a Choice" do
|
67
|
-
MTK::
|
69
|
+
MTK::Patterns.PitchChoice(1,2,3).should be_a MTK::Patterns::Choice
|
68
70
|
end
|
69
71
|
|
70
72
|
it "sets #elements from the varargs" do
|
71
|
-
MTK::
|
72
|
-
end
|
73
|
-
|
74
|
-
it "sets #type to :pitch" do
|
75
|
-
MTK::Pattern.PitchChoice([]).type.should == :pitch
|
73
|
+
MTK::Patterns.PitchChoice(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
|
76
74
|
end
|
77
75
|
end
|
78
76
|
|
79
77
|
describe "#IntensityChoice" do
|
80
78
|
it "creates a Choice" do
|
81
|
-
MTK::
|
79
|
+
MTK::Patterns.IntensityChoice(1,2,3).should be_a MTK::Patterns::Choice
|
82
80
|
end
|
83
81
|
|
84
82
|
it "sets #elements from the varargs" do
|
85
|
-
MTK::
|
86
|
-
end
|
87
|
-
|
88
|
-
it "sets #type to :pitch" do
|
89
|
-
MTK::Pattern.IntensityChoice([]).type.should == :intensity
|
83
|
+
MTK::Patterns.IntensityChoice(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
|
90
84
|
end
|
91
85
|
end
|
92
86
|
|
93
87
|
describe "#DurationChoice" do
|
94
88
|
it "creates a Choice" do
|
95
|
-
MTK::
|
89
|
+
MTK::Patterns.DurationChoice(1,2,3).should be_a MTK::Patterns::Choice
|
96
90
|
end
|
97
91
|
|
98
92
|
it "sets #elements from the varargs" do
|
99
|
-
MTK::
|
100
|
-
end
|
101
|
-
|
102
|
-
it "sets #type to :pitch" do
|
103
|
-
MTK::Pattern.DurationChoice([]).type.should == :duration
|
93
|
+
MTK::Patterns.DurationChoice(1,2,3).elements.should == [q,h,h+q]
|
104
94
|
end
|
105
95
|
end
|
106
96
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::
|
3
|
+
describe MTK::Patterns::Cycle do
|
4
4
|
|
5
|
-
CYCLE = MTK::
|
5
|
+
CYCLE = MTK::Patterns::Cycle
|
6
6
|
|
7
7
|
let(:elements) { [1, 2, 3] }
|
8
8
|
let(:cycle) { CYCLE.new elements }
|
@@ -22,14 +22,14 @@ describe MTK::Pattern::Cycle do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "enumerates nested sequences" do
|
25
|
-
cycle = CYCLE.new [1, MTK::
|
25
|
+
cycle = CYCLE.new [1, MTK::Patterns.Sequence(2,3), 4]
|
26
26
|
nexts = []
|
27
27
|
6.times { nexts << cycle.next }
|
28
28
|
nexts.should == [1,2,3,4,1,2]
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe "
|
32
|
+
describe "@max_cycles" do
|
33
33
|
it "is the :max_cycles option the pattern was constructed with" do
|
34
34
|
CYCLE.new([], :max_cycles => 1).max_cycles.should == 1
|
35
35
|
end
|
@@ -38,6 +38,10 @@ describe MTK::Pattern::Cycle do
|
|
38
38
|
cycle.max_cycles.should be_nil
|
39
39
|
end
|
40
40
|
|
41
|
+
it "loops indefinitely when it's nil" do
|
42
|
+
lambda { 100.times { cycle.next } }.should_not raise_error
|
43
|
+
end
|
44
|
+
|
41
45
|
it "causes a StopIteration exception after the number of cycles has completed" do
|
42
46
|
cycle = CYCLE.new(elements, :max_cycles => 2)
|
43
47
|
2.times do
|
@@ -45,17 +49,19 @@ describe MTK::Pattern::Cycle do
|
|
45
49
|
end
|
46
50
|
lambda { cycle.next }.should raise_error
|
47
51
|
end
|
52
|
+
end
|
48
53
|
|
49
|
-
|
50
|
-
|
54
|
+
describe "@max_elements" do
|
55
|
+
it "causes a StopIteration exception after the number of elements have been emitted, with a higher max_cycles" do
|
56
|
+
cycle = CYCLE.new(elements, max_cycles:2, max_elements:5)
|
57
|
+
5.times { cycle.next }
|
58
|
+
lambda { cycle.next }.should raise_error StopIteration
|
51
59
|
end
|
52
|
-
end
|
53
60
|
|
54
|
-
describe "#max_elements" do
|
55
61
|
it "causes a StopIteration exception after the number of elements have been emitted" do
|
56
|
-
cycle = CYCLE.new(elements, :
|
62
|
+
cycle = CYCLE.new(elements, max_elements:5)
|
57
63
|
5.times { cycle.next }
|
58
|
-
lambda { cycle.next }.should raise_error
|
64
|
+
lambda { cycle.next }.should raise_error StopIteration
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
@@ -72,61 +78,45 @@ describe MTK::Pattern::Cycle do
|
|
72
78
|
end
|
73
79
|
|
74
80
|
|
75
|
-
describe MTK::
|
81
|
+
describe MTK::Patterns do
|
76
82
|
|
77
83
|
describe "#Cycle" do
|
78
84
|
it "creates a Cycle" do
|
79
|
-
MTK::
|
85
|
+
MTK::Patterns.Cycle(1,2,3).should be_a MTK::Patterns::Cycle
|
80
86
|
end
|
81
87
|
|
82
88
|
it "sets #elements from the varargs" do
|
83
|
-
MTK::
|
84
|
-
end
|
85
|
-
|
86
|
-
it "does not set a type" do
|
87
|
-
MTK::Pattern.Cycle(1,2,3).type.should be_nil
|
89
|
+
MTK::Patterns.Cycle(1,2,3).elements.should == [1,2,3]
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
91
93
|
describe "#PitchCycle" do
|
92
94
|
it "creates a Cycle" do
|
93
|
-
MTK::
|
95
|
+
MTK::Patterns.PitchCycle(1,2,3).should be_a MTK::Patterns::Cycle
|
94
96
|
end
|
95
97
|
|
96
98
|
it "sets #elements from the varargs" do
|
97
|
-
MTK::
|
98
|
-
end
|
99
|
-
|
100
|
-
it "sets #type to :pitch" do
|
101
|
-
MTK::Pattern.PitchCycle([]).type.should == :pitch
|
99
|
+
MTK::Patterns.PitchCycle(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
|
102
100
|
end
|
103
101
|
end
|
104
102
|
|
105
103
|
describe "#IntensityCycle" do
|
106
104
|
it "creates a Cycle" do
|
107
|
-
MTK::
|
105
|
+
MTK::Patterns.IntensityCycle(1,2,3).should be_a MTK::Patterns::Cycle
|
108
106
|
end
|
109
107
|
|
110
108
|
it "sets #elements from the varargs" do
|
111
|
-
MTK::
|
112
|
-
end
|
113
|
-
|
114
|
-
it "sets #type to :pitch" do
|
115
|
-
MTK::Pattern.IntensityCycle([]).type.should == :intensity
|
109
|
+
MTK::Patterns.IntensityCycle(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
|
116
110
|
end
|
117
111
|
end
|
118
112
|
|
119
113
|
describe "#DurationCycle" do
|
120
114
|
it "creates a Cycle" do
|
121
|
-
MTK::
|
115
|
+
MTK::Patterns.DurationCycle(1,2,3).should be_a MTK::Patterns::Cycle
|
122
116
|
end
|
123
117
|
|
124
118
|
it "sets #elements from the varargs" do
|
125
|
-
MTK::
|
126
|
-
end
|
127
|
-
|
128
|
-
it "sets #type to :pitch" do
|
129
|
-
MTK::Pattern.DurationCycle([]).type.should == :duration
|
119
|
+
MTK::Patterns.DurationCycle(1,2,3).elements.should == [Duration(1),Duration(2),Duration(3)]
|
130
120
|
end
|
131
121
|
end
|
132
122
|
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Patterns::ForEach do
|
4
|
+
|
5
|
+
FOREACH = ::MTK::Patterns::ForEach
|
6
|
+
|
7
|
+
def var(name)
|
8
|
+
::MTK::Variable.new(name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def seq(*args)
|
12
|
+
::MTK::Patterns.Sequence(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def chain(*args)
|
16
|
+
::MTK::Patterns.Chain(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe "#elements" do
|
21
|
+
it "is the array the sequence was constructed with" do
|
22
|
+
FOREACH.new([seq(1,2),seq(3,4)]).elements.should == [seq(1,2),seq(3,4)]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#next" do
|
27
|
+
it "enumerates each element in the second pattern for each element in the first, with variable '$' as the first pattern's current element" do
|
28
|
+
foreach = FOREACH.new [ seq(C,D,E), seq(var('$'),G,A) ]
|
29
|
+
vals = []
|
30
|
+
9.times{ vals << foreach.next }
|
31
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
32
|
+
vals.should == [C,G,A,D,G,A,E,G,A]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "enumerates the foreach construct with a variable in the middle of the second pattern" do
|
36
|
+
foreach = FOREACH.new [ seq(C,D,E), seq(G,var('$'),A) ]
|
37
|
+
vals = []
|
38
|
+
9.times{ vals << foreach.next }
|
39
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
40
|
+
vals.should == [G,C,A,G,D,A,G,E,A]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "enumerates the foreach construct with multiple variables" do
|
44
|
+
foreach = FOREACH.new [ seq(C,D,E), seq(G,var('$'),A,var('$')) ]
|
45
|
+
vals = []
|
46
|
+
12.times{ vals << foreach.next }
|
47
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
48
|
+
vals.should == [G,C,A,C,G,D,A,D,G,E,A,E]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "handles 3-level nesting" do
|
52
|
+
foreach = FOREACH.new [ seq(C,D), seq(var('$'),F), seq(G,var('$')) ]
|
53
|
+
vals = []
|
54
|
+
8.times{ vals << foreach.next }
|
55
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
56
|
+
vals.should == [G,C,G,F,G,D,G,F]
|
57
|
+
end
|
58
|
+
|
59
|
+
it "handles 4-level nesting" do
|
60
|
+
foreach = FOREACH.new [ seq(C,D), seq(var('$'),E), seq(F,var('$')), seq(var('$'),G) ]
|
61
|
+
vals = []
|
62
|
+
16.times{ vals << foreach.next }
|
63
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
64
|
+
vals.should == [F,G,C,G,F,G,E,G,F,G,D,G,F,G,E,G]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "evaluates the '$$' var by going back 2 levels in the variables stack" do
|
68
|
+
foreach = FOREACH.new [ seq(C,D), seq(E,F), seq(var('$$'),var('$')) ]
|
69
|
+
vals = []
|
70
|
+
8.times{ vals << foreach.next }
|
71
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
72
|
+
vals.should == [C,E,C,F,D,E,D,F]
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
it "evaluates the '$$$' var by going back 3 levels in the variables stack" do
|
77
|
+
foreach = FOREACH.new [ seq(C,D), seq(E,F), seq(G,A), seq(var('$$$'),var('$$'),var('$')) ]
|
78
|
+
vals = []
|
79
|
+
24.times{ vals << foreach.next }
|
80
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
81
|
+
vals.should == [C,E,G,C,E,A,C,F,G,C,F,A,D,E,G,D,E,A,D,F,G,D,F,A]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "evaluates nested variables" do
|
85
|
+
# (C4 Bb Ab G)@( (C D C $):(q i i)*4:(mp mf) )
|
86
|
+
foreach = FOREACH.new( [seq(G,A), chain(seq(C,D,var('$')),seq(q,i,s))] )
|
87
|
+
vals = []
|
88
|
+
6.times{ vals << foreach.next }
|
89
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
90
|
+
vals.should == [[C,q],[D,i],[G,s],[C,q],[D,i],[A,s]]
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
describe "#rewind" do
|
98
|
+
it "restarts at the beginning of the sequence" do
|
99
|
+
foreach = FOREACH.new [ seq(C,D,E), seq(var('$'),G,A) ]
|
100
|
+
6.times{ foreach.next }
|
101
|
+
foreach.next.should == E
|
102
|
+
foreach.rewind
|
103
|
+
vals = []
|
104
|
+
9.times{ vals << foreach.next }
|
105
|
+
lambda{ foreach.next }.should raise_error StopIteration
|
106
|
+
vals.should == [C,G,A,D,G,A,E,G,A]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "returns self, so it can be chained to #next" do
|
110
|
+
foreach = FOREACH.new [ seq(C,D,E), seq(var('$'),G,A) ]
|
111
|
+
first = foreach.next
|
112
|
+
foreach.rewind.next.should == first
|
113
|
+
foreach.rewind.next.should == first
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
describe MTK::Patterns do
|
121
|
+
|
122
|
+
def seq(*args)
|
123
|
+
::MTK::Patterns.Sequence(*args)
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#ForEach" do
|
127
|
+
it "creates a Sequence" do
|
128
|
+
MTK::Patterns.ForEach(seq(1,2),seq(3,4)).should be_a MTK::Patterns::ForEach
|
129
|
+
end
|
130
|
+
|
131
|
+
it "sets #elements from the varargs" do
|
132
|
+
MTK::Patterns.ForEach(seq(1,2),seq(3,4)).elements.should == [seq(1,2),seq(3,4)]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|