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.
Files changed (147) hide show
  1. data/.yardopts +3 -2
  2. data/DEVELOPMENT_NOTES.md +114 -0
  3. data/INTRO.md +64 -8
  4. data/LICENSE.txt +1 -1
  5. data/README.md +31 -102
  6. data/Rakefile +56 -18
  7. data/bin/mtk +215 -0
  8. data/examples/crescendo.rb +5 -5
  9. data/examples/drum_pattern1.rb +23 -0
  10. data/examples/dynamic_pattern.rb +8 -11
  11. data/examples/gets_and_play.rb +26 -0
  12. data/examples/notation.rb +22 -0
  13. data/examples/play_midi.rb +8 -10
  14. data/examples/random_tone_row.rb +2 -2
  15. data/examples/syntax_to_midi.rb +28 -0
  16. data/examples/test_output.rb +8 -0
  17. data/examples/tone_row_melody.rb +6 -6
  18. data/lib/mtk.rb +52 -40
  19. data/lib/mtk/chord.rb +55 -0
  20. data/lib/mtk/constants/durations.rb +57 -0
  21. data/lib/mtk/constants/intensities.rb +61 -0
  22. data/lib/mtk/constants/intervals.rb +73 -0
  23. data/lib/mtk/constants/pitch_classes.rb +29 -0
  24. data/lib/mtk/constants/pitches.rb +52 -0
  25. data/lib/mtk/duration.rb +211 -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/helpers/collection.rb +164 -0
  30. data/lib/mtk/helpers/convert.rb +36 -0
  31. data/lib/mtk/helpers/lilypond.rb +162 -0
  32. data/lib/mtk/helpers/output_selector.rb +67 -0
  33. data/lib/mtk/helpers/pitch_collection.rb +23 -0
  34. data/lib/mtk/helpers/pseudo_constants.rb +26 -0
  35. data/lib/mtk/intensity.rb +156 -0
  36. data/lib/mtk/interval.rb +155 -0
  37. data/lib/mtk/lang/mtk_grammar.citrus +190 -13
  38. data/lib/mtk/lang/parser.rb +29 -0
  39. data/lib/mtk/melody.rb +94 -0
  40. data/lib/mtk/midi/dls_synth_device.rb +144 -0
  41. data/lib/mtk/midi/dls_synth_output.rb +62 -0
  42. data/lib/mtk/midi/file.rb +67 -32
  43. data/lib/mtk/midi/input.rb +97 -0
  44. data/lib/mtk/midi/jsound_input.rb +36 -17
  45. data/lib/mtk/midi/jsound_output.rb +48 -46
  46. data/lib/mtk/midi/output.rb +195 -0
  47. data/lib/mtk/midi/unimidi_input.rb +117 -0
  48. data/lib/mtk/midi/unimidi_output.rb +121 -0
  49. data/lib/mtk/{_numeric_extensions.rb → numeric_extensions.rb} +12 -0
  50. data/lib/mtk/patterns/chain.rb +49 -0
  51. data/lib/mtk/{pattern → patterns}/choice.rb +14 -8
  52. data/lib/mtk/patterns/cycle.rb +18 -0
  53. data/lib/mtk/patterns/for_each.rb +71 -0
  54. data/lib/mtk/patterns/function.rb +39 -0
  55. data/lib/mtk/{pattern → patterns}/lines.rb +11 -17
  56. data/lib/mtk/{pattern → patterns}/palindrome.rb +11 -8
  57. data/lib/mtk/patterns/pattern.rb +171 -0
  58. data/lib/mtk/patterns/sequence.rb +20 -0
  59. data/lib/mtk/pitch.rb +7 -6
  60. data/lib/mtk/pitch_class.rb +124 -46
  61. data/lib/mtk/pitch_class_set.rb +58 -35
  62. data/lib/mtk/sequencers/event_builder.rb +131 -0
  63. data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
  64. data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
  65. data/lib/mtk/{sequencer/abstract_sequencer.rb → sequencers/sequencer.rb} +37 -11
  66. data/lib/mtk/{sequencer → sequencers}/step_sequencer.rb +4 -4
  67. data/lib/mtk/timeline.rb +39 -22
  68. data/lib/mtk/variable.rb +32 -0
  69. data/spec/mtk/chord_spec.rb +83 -0
  70. data/spec/mtk/{_constants → constants}/durations_spec.rb +12 -41
  71. data/spec/mtk/{_constants → constants}/intensities_spec.rb +13 -37
  72. data/spec/mtk/{_constants → constants}/intervals_spec.rb +14 -32
  73. data/spec/mtk/{_constants → constants}/pitch_classes_spec.rb +8 -4
  74. data/spec/mtk/{_constants → constants}/pitches_spec.rb +5 -1
  75. data/spec/mtk/duration_spec.rb +372 -0
  76. data/spec/mtk/events/event_spec.rb +234 -0
  77. data/spec/mtk/events/note_spec.rb +174 -0
  78. data/spec/mtk/events/parameter_spec.rb +220 -0
  79. data/spec/mtk/{helper → helpers}/collection_spec.rb +86 -3
  80. data/spec/mtk/{helper → helpers}/pseudo_constants_spec.rb +2 -2
  81. data/spec/mtk/intensity_spec.rb +289 -0
  82. data/spec/mtk/interval_spec.rb +265 -0
  83. data/spec/mtk/lang/parser_spec.rb +597 -0
  84. data/spec/mtk/melody_spec.rb +223 -0
  85. data/spec/mtk/midi/file_spec.rb +16 -16
  86. data/spec/mtk/midi/jsound_input_spec.rb +11 -0
  87. data/spec/mtk/midi/jsound_output_spec.rb +11 -0
  88. data/spec/mtk/midi/output_spec.rb +102 -0
  89. data/spec/mtk/midi/unimidi_input_spec.rb +11 -0
  90. data/spec/mtk/midi/unimidi_output_spec.rb +11 -0
  91. data/spec/mtk/{_numeric_extensions_spec.rb → numeric_extensions_spec.rb} +1 -0
  92. data/spec/mtk/patterns/chain_spec.rb +110 -0
  93. data/spec/mtk/{pattern → patterns}/choice_spec.rb +20 -30
  94. data/spec/mtk/{pattern → patterns}/cycle_spec.rb +25 -35
  95. data/spec/mtk/patterns/for_each_spec.rb +136 -0
  96. data/spec/mtk/{pattern → patterns}/function_spec.rb +17 -30
  97. data/spec/mtk/{pattern → patterns}/lines_spec.rb +11 -27
  98. data/spec/mtk/{pattern → patterns}/palindrome_spec.rb +13 -29
  99. data/spec/mtk/patterns/pattern_spec.rb +132 -0
  100. data/spec/mtk/patterns/sequence_spec.rb +203 -0
  101. data/spec/mtk/pitch_class_set_spec.rb +23 -21
  102. data/spec/mtk/pitch_class_spec.rb +151 -39
  103. data/spec/mtk/pitch_spec.rb +22 -1
  104. data/spec/mtk/sequencers/event_builder_spec.rb +245 -0
  105. data/spec/mtk/sequencers/legato_sequencer_spec.rb +45 -0
  106. data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +84 -0
  107. data/spec/mtk/sequencers/sequencer_spec.rb +215 -0
  108. data/spec/mtk/{sequencer → sequencers}/step_sequencer_spec.rb +35 -13
  109. data/spec/mtk/timeline_spec.rb +109 -16
  110. data/spec/mtk/variable_spec.rb +52 -0
  111. data/spec/spec_coverage.rb +2 -0
  112. data/spec/spec_helper.rb +3 -0
  113. metadata +188 -91
  114. data/lib/mtk/_constants/durations.rb +0 -80
  115. data/lib/mtk/_constants/intensities.rb +0 -81
  116. data/lib/mtk/_constants/intervals.rb +0 -85
  117. data/lib/mtk/_constants/pitch_classes.rb +0 -35
  118. data/lib/mtk/_constants/pitches.rb +0 -49
  119. data/lib/mtk/event.rb +0 -70
  120. data/lib/mtk/helper/collection.rb +0 -114
  121. data/lib/mtk/helper/event_builder.rb +0 -85
  122. data/lib/mtk/helper/pseudo_constants.rb +0 -26
  123. data/lib/mtk/lang/grammar.rb +0 -17
  124. data/lib/mtk/note.rb +0 -63
  125. data/lib/mtk/pattern/abstract_pattern.rb +0 -132
  126. data/lib/mtk/pattern/cycle.rb +0 -51
  127. data/lib/mtk/pattern/enumerator.rb +0 -26
  128. data/lib/mtk/pattern/function.rb +0 -46
  129. data/lib/mtk/pattern/sequence.rb +0 -30
  130. data/lib/mtk/pitch_set.rb +0 -84
  131. data/lib/mtk/sequencer/rhythmic_sequencer.rb +0 -29
  132. data/lib/mtk/transform/invertible.rb +0 -15
  133. data/lib/mtk/transform/mappable.rb +0 -18
  134. data/lib/mtk/transform/set_theory_operations.rb +0 -34
  135. data/lib/mtk/transform/transposable.rb +0 -14
  136. data/spec/mtk/event_spec.rb +0 -139
  137. data/spec/mtk/helper/event_builder_spec.rb +0 -92
  138. data/spec/mtk/lang/grammar_spec.rb +0 -100
  139. data/spec/mtk/note_spec.rb +0 -115
  140. data/spec/mtk/pattern/abstract_pattern_spec.rb +0 -45
  141. data/spec/mtk/pattern/note_cycle_spec.rb.bak +0 -116
  142. data/spec/mtk/pattern/pitch_cycle_spec.rb.bak +0 -47
  143. data/spec/mtk/pattern/pitch_sequence_spec.rb.bak +0 -37
  144. data/spec/mtk/pattern/sequence_spec.rb +0 -151
  145. data/spec/mtk/pitch_set_spec.rb +0 -198
  146. data/spec/mtk/sequencer/abstract_sequencer_spec.rb +0 -159
  147. data/spec/mtk/sequencer/rhythmic_sequencer_spec.rb +0 -49
@@ -1,100 +0,0 @@
1
- require 'spec_helper'
2
- require 'mtk/lang/grammar'
3
-
4
- describe MTK::Lang::Grammar do
5
-
6
- def parse syntax, root
7
- MTK::Lang::Grammar.parse(syntax, root)
8
- end
9
-
10
- describe ".parse" do
11
-
12
- it "should parse pitch sequences" do
13
- parse("C4 D4 E4", :pitch_sequence).should == Pattern.PitchSequence(C4, D4, E4)
14
- end
15
-
16
- it "should parse pitches" do
17
- for pitch_class_name in PitchClass::VALID_NAMES
18
- for octave in -1..9
19
- parse("#{pitch_class_name}#{octave}", :pitch).should == Pitch[PitchClass[pitch_class_name],octave]
20
- end
21
- end
22
- end
23
-
24
- it "should parse pitch classes" do
25
- for pitch_class_name in PitchClass::VALID_NAMES
26
- parse(pitch_class_name, :pitch_class).should == PitchClass[pitch_class_name]
27
- end
28
- end
29
-
30
- it "should parse intervals" do
31
- for interval_name in Intervals::INTERVAL_NAMES
32
- parse(interval_name, :interval).should == Intervals[interval_name]
33
- end
34
- end
35
-
36
- it "should parse intensities" do
37
- for intensity_name in Intensities::INTENSITY_NAMES
38
- parse(intensity_name, :intensity).should == Intensities[intensity_name]
39
- end
40
- end
41
-
42
- it "should parse intensities with + and - modifiers" do
43
- for intensity_name in Intensities::INTENSITY_NAMES
44
- name = "#{intensity_name}+"
45
- parse(name, :intensity).should == Intensities[name]
46
- name = "#{intensity_name}-"
47
- parse(name, :intensity).should == Intensities[name]
48
- end
49
- end
50
-
51
- it "should parse durations" do
52
- for duration in Durations::DURATION_NAMES
53
- parse(duration, :duration).should == Durations[duration]
54
- end
55
- end
56
-
57
- it "should parse durations with . and t modifiers" do
58
- for duration in Durations::DURATION_NAMES
59
- name = "#{duration}."
60
- parse(name, :duration).should == Durations[name]
61
- name = "#{duration}t"
62
- parse(name, :duration).should == Durations[name]
63
- name = "#{duration}..t.t"
64
- parse(name, :duration).should == Durations[name]
65
- end
66
- end
67
-
68
- it "should parse ints as numbers" do
69
- parse("123", :number).should == 123
70
- end
71
-
72
- it "should parse floats as numbers" do
73
- parse("1.23", :number).should == 1.23
74
- end
75
-
76
- it "should parse floats" do
77
- parse("1.23", :float).should == 1.23
78
- end
79
-
80
- it "should parse negative floats" do
81
- parse("-1.23", :float).should == -1.23
82
- end
83
-
84
- it "should parse ints" do
85
- parse("123", :int).should == 123
86
- end
87
-
88
- it "should parse negative ints" do
89
- parse("-123", :int).should == -123
90
- end
91
-
92
- it "should parse negative ints" do
93
- parse("-123", :int).should == -123
94
- end
95
-
96
- it "should give nil as the value for whitespace" do
97
- parse(" \t\n", :space).should == nil
98
- end
99
- end
100
- end
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Note do
4
-
5
- let(:pitch) { C4 }
6
- let(:intensity) { mf }
7
- let(:duration) { 2.5 }
8
- let(:note) { Note.new(pitch, intensity, duration) }
9
-
10
- describe "#pitch" do
11
- it "is the pitch used to create the Note" do
12
- note.pitch.should == pitch
13
- end
14
-
15
- it "is a read-only attribute" do
16
- lambda{ note.pitch = D4 }.should raise_error
17
- end
18
- end
19
-
20
- describe ".from_hash" do
21
- it "constructs a Note using a hash" do
22
- Note.from_hash({ :pitch => C4, :intensity => intensity, :duration => duration }).should == note
23
- end
24
- end
25
-
26
- describe '.from_midi' do
27
- it "constructs a Note using a MIDI pitch and velocity" do
28
- Note.from_midi(C4.to_i, mf*127, 2.5).should == note
29
- end
30
- end
31
-
32
- describe "#to_midi" do
33
- it "converts the Note to an Array of MIDI values: [pitch, velocity, duration]" do
34
- note.to_midi.should == [60, (mf*127).round, duration]
35
- end
36
- end
37
-
38
- describe "#to_hash" do
39
- it "is a hash containing all the attributes of the Note" do
40
- note.to_hash.should == { :pitch => pitch, :intensity => intensity, :duration => duration }
41
- end
42
- end
43
-
44
- describe '#transpose' do
45
- it 'adds the given interval to the @pitch' do
46
- (note.transpose 2.semitones).should == Note.new(D4, intensity, duration)
47
- end
48
- it 'does not affect the immutability of the Note' do
49
- (note.transpose 2.semitones).should_not == note
50
- end
51
- end
52
-
53
- describe "#invert" do
54
- context 'higher center pitch' do
55
- it 'inverts the pitch around the given center pitch' do
56
- note.invert(Pitch 66).should == Note.new(Pitch(72), intensity, duration)
57
- end
58
- end
59
-
60
- context 'lower center pitch' do
61
- it 'inverts the pitch around the given center pitch' do
62
- note.invert(Pitch 54).should == Note.new(Pitch(48), intensity, duration)
63
- end
64
- end
65
-
66
- it "returns the an equal note when given it's pitch as an argument" do
67
- note.invert(note.pitch).should == note
68
- end
69
- end
70
-
71
- describe "#==" do
72
- it "is true when the pitches, intensities, and durations are equal" do
73
- note.should == Note.new(pitch, intensity, duration)
74
- end
75
-
76
- it "is false when the pitches are not equal" do
77
- note.should_not == Note.new(pitch + 1, intensity, duration)
78
- end
79
-
80
- it "is false when the intensities are not equal" do
81
- note.should_not == Note.new(pitch, intensity * 0.5, duration)
82
- end
83
-
84
- it "is false when the durations are not equal" do
85
- note.should_not == Note.new(pitch, intensity, duration * 2)
86
- end
87
- end
88
-
89
- end
90
-
91
- describe MTK do
92
-
93
- describe '#Note' do
94
-
95
- it "acts like new for multiple arguments" do
96
- Note(C4,mf,1).should == Note.new(C4,mf,1)
97
- end
98
-
99
- it "acts like new for an Array of arguments by unpacking (splatting) them" do
100
- Note([C4,mf,1]).should == Note.new(C4,mf,1)
101
- end
102
-
103
- it "returns the argument if it's already a Note" do
104
- note = Note.new(C4,mf,1)
105
- Note(note).should be_equal note
106
- end
107
-
108
- it "raises an error for types it doesn't understand" do
109
- lambda{ Note({:not => :compatible}) }.should raise_error
110
- end
111
-
112
- end
113
-
114
- end
115
-
@@ -1,45 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Pattern::AbstractPattern do
4
-
5
- PATTERN = MTK::Pattern::AbstractPattern
6
-
7
- let(:elements) { [1,2,3] }
8
-
9
- describe "#type" do
10
- it "is the :type value from the constuctor's options hash" do
11
- PATTERN.new([], :type => :my_type).type.should == :my_type
12
- end
13
- end
14
-
15
- describe "#max_elements" do
16
- it "is the :max_elements option the pattern was constructed with" do
17
- PATTERN.new([], :max_elements => 1).max_elements.should == 1
18
- end
19
-
20
- it "is nil by default" do
21
- PATTERN.new([]).max_elements.should be_nil
22
- end
23
-
24
- it "causes a StopIteration exception after the number of elements have been emitted" do
25
- cycle = PATTERN.new([:anything], :max_elements => 5)
26
- 5.times { cycle.next }
27
- lambda { cycle.next }.should raise_error
28
- end
29
- end
30
-
31
- describe "#==" do
32
- it "is true if the elements and types are equal" do
33
- PATTERN.new(elements, :type => :some_type).should == PATTERN.new(elements, :type => :some_type)
34
- end
35
-
36
- it "is false if the elements are not equal" do
37
- PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements + [4], :type => :some_type)
38
- end
39
-
40
- it "is false if the types are not equal" do
41
- PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements, :type => :another_type)
42
- end
43
- end
44
-
45
- end
@@ -1,116 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Pattern::NoteCycle do
4
-
5
- def note(pitch, intensity=mf, duration=1)
6
- Note(pitch, intensity, duration)
7
- end
8
-
9
- describe "#new" do
10
- it "allows default pitch to be specified" do
11
- cycle = Pattern::NoteCycle.new [], [p], [1], :pitch => Gb4
12
- cycle.next.should == Note(Gb4, p, 1)
13
- end
14
- it "allows default intensity to be specified" do
15
- cycle = Pattern::NoteCycle.new [C4], [], [1], :intensity => ppp
16
- cycle.next.should == Note(C4, ppp, 1)
17
- end
18
- it "allows default duration to be specified" do
19
- cycle = Pattern::NoteCycle.new [C4], [mf], [], :duration => 12
20
- cycle.next.should == Note(C4, mf, 12)
21
- end
22
- end
23
-
24
- describe "#next" do
25
- it "iterates through the pitch, intensity, and duration list in parallel to emit Notes" do
26
- cycle = Pattern::NoteCycle.new [C4, D4, E4], [p, f], [1,2,3,4]
27
- cycle.next.should == Note(C4, p, 1)
28
- cycle.next.should == Note(D4, f, 2)
29
- cycle.next.should == Note(E4, p, 3)
30
- cycle.next.should == Note(C4, f, 4)
31
- cycle.next.should == Note(D4, p, 1)
32
- cycle.next.should == Note(E4, f, 2)
33
- end
34
-
35
- it "defaults to Pitch 'C4' when no pitches are given" do
36
- cycle = Pattern::NoteCycle.new [], [p,f], [1,2,3]
37
- cycle.next.should == Note(C4, p, 1)
38
- cycle.next.should == Note(C4, f, 2)
39
- cycle.next.should == Note(C4, p, 3)
40
- end
41
-
42
- it "defaults to intensity 'mf' when no intensities are given" do
43
- cycle = Pattern::NoteCycle.new [C4, D4, E4], nil, [2]
44
- cycle.next.should == Note(C4, mf, 2)
45
- cycle.next.should == Note(D4, mf, 2)
46
- cycle.next.should == Note(E4, mf, 2)
47
- end
48
-
49
- it "defaults to duration 1 when no durations are given" do
50
- cycle = Pattern::NoteCycle.new [C4, D4, E4], [p, f]
51
- cycle.next.should == Note(C4, p, 1)
52
- cycle.next.should == Note(D4, f, 1)
53
- cycle.next.should == Note(E4, p, 1)
54
- end
55
-
56
- it "uses the previous pitch/intensity/duration when it encounters a nil value" do
57
- cycle = Pattern::NoteCycle.new [C4, D4, E4, F4, nil], [mp, mf, f, nil], [1, 2, nil]
58
- cycle.next.should == Note(C4, mp, 1)
59
- cycle.next.should == Note(D4, mf, 2)
60
- cycle.next.should == Note(E4, f, 2)
61
- cycle.next.should == Note(F4, f, 1)
62
- cycle.next.should == Note(F4, mp, 2)
63
- cycle.next.should == Note(C4, mf, 2)
64
- end
65
-
66
- it "adds Numeric intervals in the pitch list to the previous pitch" do
67
- cycle = Pattern::NoteCycle.new [C4, 1, 2, 3]
68
- cycle.next.should == note(C4)
69
- cycle.next.should == note(C4+1)
70
- cycle.next.should == note(C4+1+2)
71
- cycle.next.should == note(C4+1+2+3)
72
- cycle.next.should == note(C4)
73
- end
74
-
75
- it "goes to the nearest Pitch for any PitchClasses in the pitch list" do
76
- cycle = Pattern::NoteCycle.new [C4, F, C, G, C]
77
- cycle.next.should == note(C4)
78
- cycle.next.should == note(F4)
79
- cycle.next.should == note(C4)
80
- cycle.next.should == note(G3)
81
- cycle.next.should == note(C4)
82
- end
83
-
84
- it "does not endlessly ascend or descend when alternating between two pitch classes a tritone apart" do
85
- cycle = Pattern::NoteCycle.new [C4, Gb, C, Gb, C]
86
- cycle.next.should == note(C4)
87
- cycle.next.should == note(Gb4)
88
- cycle.next.should == note(C4)
89
- cycle.next.should == note(Gb4)
90
- cycle.next.should == note(C4)
91
- end
92
-
93
- it "cycles Note Arrays for pitch list items that are PitchSets" do
94
- cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), C4, PitchSet.new([D4, F4, A4])]
95
- cycle.next.should == [note(C4), note(E4), note(G4)]
96
- cycle.next.should == note(C4)
97
- cycle.next.should == [note(D4), note(F4), note(A4)]
98
- end
99
-
100
- it "adds numeric intervals to PitchSets" do
101
- cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), 2]
102
- cycle.next.should == [note(C4), note(E4), note(G4)]
103
- cycle.next.should == [note(D4), note(Gb4), note(A4)]
104
- end
105
-
106
- it "goes to the nearest Pitch relative to the lowest note in the PitchSet for any PitchClasses in the pitch list" do
107
- cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), F, D, Bb]
108
- cycle.next.should == [note(C4), note(E4), note(G4)]
109
- cycle.next.should == [note(F4), note(A4), note(C5)]
110
- cycle.next.should == [note(D4), note(Gb4), note(A4)]
111
- cycle.next.should == [note(Bb3), note(D4), note(F4)]
112
- end
113
- end
114
-
115
-
116
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Pattern::PitchCycle do
4
-
5
- describe "#next" do
6
- it "enumerates Pitches" do
7
- cycle = Pattern::PitchCycle.new [C4, D4, E4]
8
- cycle.next.should == C4
9
- cycle.next.should == D4
10
- cycle.next.should == E4
11
- end
12
-
13
- it "adds Numeric elements (intervals) to the previous pitch" do
14
- cycle = Pattern::PitchCycle.new [C4, 1, 2, 3]
15
- cycle.next.should == C4
16
- cycle.next.should == C4+1
17
- cycle.next.should == C4+1+2
18
- cycle.next.should == C4+1+2+3
19
- end
20
-
21
- it "returns a Pitch when encountering a Pitch after another type" do
22
- cycle = Pattern::PitchCycle.new [C4, 1, C4]
23
- cycle.next
24
- cycle.next
25
- cycle.next.should == C4
26
- end
27
-
28
- it "goes to the nearest Pitch for any PitchClasses in the pitch list" do
29
- cycle = Pattern::PitchCycle.new [C4, F, C, G, C]
30
- cycle.next.should == C4
31
- cycle.next.should == F4
32
- cycle.next.should == C4
33
- cycle.next.should == G3
34
- cycle.next.should == C4
35
- end
36
-
37
- it "does not endlessly ascend or descend when alternating between two pitch classes a tritone apart" do
38
- cycler = Pattern::PitchCycle.new [C4, Gb, C, Gb, C]
39
- cycler.next.should == C4
40
- cycler.next.should == Gb4
41
- cycler.next.should == C4
42
- cycler.next.should == Gb4
43
- cycler.next.should == C4
44
- end
45
-
46
- end
47
- end
@@ -1,37 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Pattern::PitchSequence do
4
-
5
- let(:pitches) { [C4,D4,E4] }
6
- let(:pitch_sequence) { Pattern::PitchSequence.new(pitches) }
7
-
8
-
9
- describe ".from_pitch_classes" do
10
- it "creates a pitch sequence from a list of pitch classes and starting point, selecting the nearest pitch to each pitch class" do
11
- Pattern::PitchSequence.from_pitch_classes([C,G,B,Eb,D,C], D3).should == [C3,G2,B2,Eb3,D3,C3]
12
- end
13
-
14
- it "defaults to a starting point of C4 (middle C)" do
15
- Pattern::PitchSequence.from_pitch_classes([C]).should == [C4]
16
- end
17
-
18
- it "doesn't travel within an octave above or below the starting point by default" do
19
- Pattern::PitchSequence.from_pitch_classes([C,F,Bb,D,A,E,B]).should == [C4,F4,Bb4,D4,A3,E3,B3]
20
- end
21
-
22
- it "allows max distance above or below the starting point to be set via the third argument" do
23
- Pattern::PitchSequence.from_pitch_classes([C,F,Bb,D,A,E,B], C4, 6).should == [C4,F4,Bb3,D4,A3,E4,B3]
24
- end
25
- end
26
-
27
-
28
- end
29
-
30
- describe MTK::Pattern do
31
-
32
- it "converts the arguments to Pitches when possible" do
33
- Pattern.PitchSequence(:C4,:D4,:E4).elements.should == [C4,D4,E4]
34
- end
35
- end
36
-
37
- end