jmtk 0.0.3.3-java

Sign up to get free protection for your applications and to get access to all the features.
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