jmtk 0.0.3.3-java

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.
Files changed (110) hide show
  1. data/.yardopts +10 -0
  2. data/DEVELOPMENT_NOTES.md +115 -0
  3. data/INTRO.md +129 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.md +50 -0
  6. data/Rakefile +102 -0
  7. data/bin/jmtk +250 -0
  8. data/bin/mtk +250 -0
  9. data/examples/crescendo.rb +20 -0
  10. data/examples/drum_pattern.rb +23 -0
  11. data/examples/dynamic_pattern.rb +36 -0
  12. data/examples/gets_and_play.rb +27 -0
  13. data/examples/notation.rb +22 -0
  14. data/examples/play_midi.rb +17 -0
  15. data/examples/print_midi.rb +13 -0
  16. data/examples/random_tone_row.rb +18 -0
  17. data/examples/syntax_to_midi.rb +28 -0
  18. data/examples/test_output.rb +7 -0
  19. data/examples/tone_row_melody.rb +23 -0
  20. data/lib/mtk.rb +76 -0
  21. data/lib/mtk/core/duration.rb +213 -0
  22. data/lib/mtk/core/intensity.rb +158 -0
  23. data/lib/mtk/core/interval.rb +157 -0
  24. data/lib/mtk/core/pitch.rb +154 -0
  25. data/lib/mtk/core/pitch_class.rb +194 -0
  26. data/lib/mtk/events/event.rb +119 -0
  27. data/lib/mtk/events/note.rb +112 -0
  28. data/lib/mtk/events/parameter.rb +54 -0
  29. data/lib/mtk/events/timeline.rb +232 -0
  30. data/lib/mtk/groups/chord.rb +56 -0
  31. data/lib/mtk/groups/collection.rb +196 -0
  32. data/lib/mtk/groups/melody.rb +96 -0
  33. data/lib/mtk/groups/pitch_class_set.rb +163 -0
  34. data/lib/mtk/groups/pitch_collection.rb +23 -0
  35. data/lib/mtk/io/dls_synth_device.rb +146 -0
  36. data/lib/mtk/io/dls_synth_output.rb +62 -0
  37. data/lib/mtk/io/jsound_input.rb +87 -0
  38. data/lib/mtk/io/jsound_output.rb +82 -0
  39. data/lib/mtk/io/midi_file.rb +209 -0
  40. data/lib/mtk/io/midi_input.rb +97 -0
  41. data/lib/mtk/io/midi_output.rb +195 -0
  42. data/lib/mtk/io/notation.rb +162 -0
  43. data/lib/mtk/io/unimidi_input.rb +117 -0
  44. data/lib/mtk/io/unimidi_output.rb +140 -0
  45. data/lib/mtk/lang/durations.rb +57 -0
  46. data/lib/mtk/lang/intensities.rb +61 -0
  47. data/lib/mtk/lang/intervals.rb +73 -0
  48. data/lib/mtk/lang/mtk_grammar.citrus +237 -0
  49. data/lib/mtk/lang/parser.rb +29 -0
  50. data/lib/mtk/lang/pitch_classes.rb +29 -0
  51. data/lib/mtk/lang/pitches.rb +52 -0
  52. data/lib/mtk/lang/pseudo_constants.rb +26 -0
  53. data/lib/mtk/lang/variable.rb +32 -0
  54. data/lib/mtk/numeric_extensions.rb +66 -0
  55. data/lib/mtk/patterns/chain.rb +49 -0
  56. data/lib/mtk/patterns/choice.rb +43 -0
  57. data/lib/mtk/patterns/cycle.rb +18 -0
  58. data/lib/mtk/patterns/for_each.rb +71 -0
  59. data/lib/mtk/patterns/function.rb +39 -0
  60. data/lib/mtk/patterns/lines.rb +54 -0
  61. data/lib/mtk/patterns/palindrome.rb +45 -0
  62. data/lib/mtk/patterns/pattern.rb +171 -0
  63. data/lib/mtk/patterns/sequence.rb +20 -0
  64. data/lib/mtk/sequencers/event_builder.rb +132 -0
  65. data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
  66. data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
  67. data/lib/mtk/sequencers/sequencer.rb +111 -0
  68. data/lib/mtk/sequencers/step_sequencer.rb +26 -0
  69. data/spec/mtk/core/duration_spec.rb +372 -0
  70. data/spec/mtk/core/intensity_spec.rb +289 -0
  71. data/spec/mtk/core/interval_spec.rb +265 -0
  72. data/spec/mtk/core/pitch_class_spec.rb +343 -0
  73. data/spec/mtk/core/pitch_spec.rb +297 -0
  74. data/spec/mtk/events/event_spec.rb +234 -0
  75. data/spec/mtk/events/note_spec.rb +174 -0
  76. data/spec/mtk/events/parameter_spec.rb +220 -0
  77. data/spec/mtk/events/timeline_spec.rb +430 -0
  78. data/spec/mtk/groups/chord_spec.rb +85 -0
  79. data/spec/mtk/groups/collection_spec.rb +374 -0
  80. data/spec/mtk/groups/melody_spec.rb +225 -0
  81. data/spec/mtk/groups/pitch_class_set_spec.rb +340 -0
  82. data/spec/mtk/io/midi_file_spec.rb +243 -0
  83. data/spec/mtk/io/midi_output_spec.rb +102 -0
  84. data/spec/mtk/lang/durations_spec.rb +89 -0
  85. data/spec/mtk/lang/intensities_spec.rb +101 -0
  86. data/spec/mtk/lang/intervals_spec.rb +143 -0
  87. data/spec/mtk/lang/parser_spec.rb +603 -0
  88. data/spec/mtk/lang/pitch_classes_spec.rb +62 -0
  89. data/spec/mtk/lang/pitches_spec.rb +56 -0
  90. data/spec/mtk/lang/pseudo_constants_spec.rb +20 -0
  91. data/spec/mtk/lang/variable_spec.rb +52 -0
  92. data/spec/mtk/numeric_extensions_spec.rb +83 -0
  93. data/spec/mtk/patterns/chain_spec.rb +110 -0
  94. data/spec/mtk/patterns/choice_spec.rb +97 -0
  95. data/spec/mtk/patterns/cycle_spec.rb +123 -0
  96. data/spec/mtk/patterns/for_each_spec.rb +136 -0
  97. data/spec/mtk/patterns/function_spec.rb +120 -0
  98. data/spec/mtk/patterns/lines_spec.rb +77 -0
  99. data/spec/mtk/patterns/palindrome_spec.rb +108 -0
  100. data/spec/mtk/patterns/pattern_spec.rb +132 -0
  101. data/spec/mtk/patterns/sequence_spec.rb +203 -0
  102. data/spec/mtk/sequencers/event_builder_spec.rb +245 -0
  103. data/spec/mtk/sequencers/legato_sequencer_spec.rb +45 -0
  104. data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +84 -0
  105. data/spec/mtk/sequencers/sequencer_spec.rb +215 -0
  106. data/spec/mtk/sequencers/step_sequencer_spec.rb +93 -0
  107. data/spec/spec_coverage.rb +2 -0
  108. data/spec/spec_helper.rb +12 -0
  109. data/spec/test.mid +0 -0
  110. metadata +226 -0
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe MTK::Lang::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, value|
24
+ const.name.should == name
25
+ const.value.should == 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 PitchClass.[]" do
53
+ for name in PitchClasses::PITCH_CLASS_NAMES
54
+ PitchClasses[name].should == PitchClass[name]
55
+ end
56
+ end
57
+
58
+ it "returns nil for arguments it doesn't understand" do
59
+ PitchClasses[:invalid].should be_nil
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe MTK::Lang::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
+
51
+ it "returns nil for arguments it doesn't understand" do
52
+ Pitches[:invalid].should be_nil
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe MTK::Lang::PseudoConstants do
4
+
5
+ module MockConstants
6
+ extend MTK::Lang::PseudoConstants
7
+ define_constant 'constant', :value
8
+ end
9
+
10
+ describe "define_constant" do
11
+ it "defines a method method in the module" do
12
+ MockConstants::constant.should == :value
13
+ end
14
+
15
+ it "defines a 'module_function'" do
16
+ MockConstants.constant.should == :value
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe MTK::Lang::Variable do
4
+
5
+ def var(*args)
6
+ ::MTK::Lang::Variable.new(*args)
7
+ end
8
+
9
+ describe '#name' do
10
+ it 'is the name the variable was constructed with' do
11
+ var('$').name.should == '$'
12
+ var('$$').name.should == '$$'
13
+ end
14
+
15
+ it 'cannot be changed after the variable is created' do
16
+ lambda{ var('$').name = '$$$' }.should raise_error
17
+ end
18
+ end
19
+
20
+ describe '#value' do
21
+ it 'is the value the variable was constructed with' do
22
+ var(:name, :value).value.should == :value
23
+ end
24
+
25
+ it 'can be changed after the variable is created' do
26
+ v = var(:name, :value)
27
+ v.value = 'foo'
28
+ v.value.should == 'foo'
29
+ end
30
+ end
31
+
32
+ describe '#==' do
33
+ it "is true when two variables' names are equal" do
34
+ var('$').should == var('$')
35
+ end
36
+
37
+ it "is false when two variables' names are not equal" do
38
+ var('$').should_not == var('$$')
39
+ end
40
+ end
41
+
42
+ describe '#to_s' do
43
+ it "includes just the variable name when there's no value" do
44
+ var('$').to_s.should == 'MTK::Lang::Variable<$>'
45
+ end
46
+
47
+ it "includes just the variable name and value when there's a value" do
48
+ var('x',1).to_s.should == 'MTK::Lang::Variable<x=1>'
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'mtk/numeric_extensions'
3
+
4
+ describe Numeric do
5
+
6
+ describe "#to_pitch" do
7
+ it "acts like Pitch.from_f applied to the Numeric value" do
8
+ 12.3.to_pitch.should == MTK::Core::Pitch.from_f(12.3)
9
+ end
10
+ end
11
+
12
+
13
+ describe "#to_pitch_class" do
14
+ it "acts like PitchClass.from_f applied to the Numeric value" do
15
+ 6.to_pitch_class.should == MTK::Core::PitchClass.from_f(6)
16
+ end
17
+ end
18
+
19
+
20
+ describe "#to_duration" do
21
+ it "acts like Duration.from_f applied to the Numeric value" do
22
+ 1.5.to_duration.should == MTK::Core::Duration.from_f(1.5)
23
+ end
24
+ end
25
+
26
+ describe "#beat" do
27
+ it "acts like #to_duration" do
28
+ 1.beat.should == 1.to_duration
29
+ end
30
+ end
31
+
32
+ describe "#beats" do
33
+ it "acts like #to_duration" do
34
+ 2.beats.should == 2.to_duration
35
+ end
36
+ end
37
+
38
+
39
+ describe "#to_intensity" do
40
+ it "acts like Intensity.from_f applied to the Numeric value" do
41
+ 0.75.to_intensity.should == MTK::Core::Intensity.from_f(0.75)
42
+ end
43
+ end
44
+
45
+ describe "#percent_intensity" do
46
+ it "acts like Intensity.from_f applied to 1/100 of the Numeric value" do
47
+ 75.percent_intensity.should == MTK::Core::Intensity.from_f(0.75)
48
+ end
49
+ end
50
+
51
+
52
+ describe "#to_interval" do
53
+ it "acts like Interval.from_f applied to the Numeric value" do
54
+ 3.5.to_interval.should == MTK::Core::Interval.from_f(3.5)
55
+ end
56
+ end
57
+
58
+ describe '#semitone' do
59
+ it "acts like #to_interval" do
60
+ 1.semitone.should == 1.to_interval
61
+ end
62
+ end
63
+
64
+ describe '#semitones' do
65
+ it "acts like #to_interval" do
66
+ 2.semitones.should == 2.to_interval
67
+ end
68
+ end
69
+
70
+ describe "#cents" do
71
+ it "acts like Interval.from_f applied to 1/100 of the Numeric value" do
72
+ 50.cents.should == MTK::Core::Interval.from_f(0.5)
73
+ end
74
+ end
75
+
76
+ describe "#octaves" do
77
+ it "acts like Interval.from_f applied to 12 times the Numeric value" do
78
+ 2.octaves.should == MTK::Core::Interval.from_f(24)
79
+ end
80
+ end
81
+
82
+ end
83
+
@@ -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
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+ require 'set'
3
+
4
+ describe MTK::Patterns::Choice do
5
+
6
+ CHOICE = MTK::Patterns::Choice
7
+
8
+ let(:elements) { [1,2,3] }
9
+ let(:choice) { CHOICE.new elements, max_cycles:500 }
10
+
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
+
18
+ it "randomly chooses one of the elements" do
19
+ choosen = Set.new
20
+ 100.times do
21
+ element = choice.next
22
+ choosen << element
23
+ end
24
+ choosen.to_a.should =~ elements
25
+ end
26
+
27
+ it "does a weighted random selection when a weights list is passed in via constructor options[:weights]" do
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
29
+ choosen = Set.new
30
+ first_count, second_count = 0,0
31
+ 100.times do
32
+ element = choice.next
33
+ choosen << element
34
+ first_count += 1 if element == elements[0]
35
+ second_count += 1 if element == elements[1]
36
+ end
37
+ choosen.to_a.should =~ elements[0..1]
38
+ (first_count + 10).should < second_count # this may occasional fail, but it seems unlikely
39
+ end
40
+
41
+ it "enumerates a choosen sub-sequence" do
42
+ choice = CHOICE.new [MTK::Patterns.Sequence(4,5,6)], max_cycles:10
43
+ choice.next.should == 4
44
+ choice.next.should == 5
45
+ choice.next.should == 6
46
+ choice.next.should == 4 # now it will select a new choice, but there's only one, so it will be the same
47
+ choice.next.should == 5
48
+ choice.next.should == 6
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+
55
+ describe MTK::Patterns do
56
+
57
+ describe "#Choice" do
58
+ it "creates a Choice" do
59
+ MTK::Patterns.Choice(1,2,3).should be_a MTK::Patterns::Choice
60
+ end
61
+
62
+ it "sets #elements from the varargs" do
63
+ MTK::Patterns.Choice(1,2,3).elements.should == [1,2,3]
64
+ end
65
+ end
66
+
67
+ describe "#PitchChoice" do
68
+ it "creates a Choice" do
69
+ MTK::Patterns.PitchChoice(1,2,3).should be_a MTK::Patterns::Choice
70
+ end
71
+
72
+ it "sets #elements from the varargs" do
73
+ MTK::Patterns.PitchChoice(1,2,3).elements.should == [Pitch(1),Pitch(2),Pitch(3)]
74
+ end
75
+ end
76
+
77
+ describe "#IntensityChoice" do
78
+ it "creates a Choice" do
79
+ MTK::Patterns.IntensityChoice(1,2,3).should be_a MTK::Patterns::Choice
80
+ end
81
+
82
+ it "sets #elements from the varargs" do
83
+ MTK::Patterns.IntensityChoice(1,2,3).elements.should == [Intensity(1),Intensity(2),Intensity(3)]
84
+ end
85
+ end
86
+
87
+ describe "#DurationChoice" do
88
+ it "creates a Choice" do
89
+ MTK::Patterns.DurationChoice(1,2,3).should be_a MTK::Patterns::Choice
90
+ end
91
+
92
+ it "sets #elements from the varargs" do
93
+ MTK::Patterns.DurationChoice(1,2,3).elements.should == [q,h,h+q]
94
+ end
95
+ end
96
+
97
+ end