mtk 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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,30 +0,0 @@
1
- module MTK
2
- module Pattern
3
-
4
- # A finite list of elements, which can be enumerated one at a time.
5
- class Sequence < AbstractPattern
6
-
7
- # Reset the sequence to the beginning
8
- def rewind
9
- @index = -1
10
- super
11
- end
12
-
13
- ###################
14
- protected
15
-
16
- # (see AbstractPattern#advance!)
17
- def advance!
18
- super
19
- @index += 1
20
- raise StopIteration if @index >= @elements.length
21
- end
22
-
23
- # (see AbstractPattern#current)
24
- def current
25
- @elements[@index]
26
- end
27
- end
28
-
29
- end
30
- end
data/lib/mtk/pitch_set.rb DELETED
@@ -1,84 +0,0 @@
1
- module MTK
2
-
3
- # A set of {Pitch}es
4
- #
5
- class PitchSet
6
-
7
- include Helper::Collection
8
- include Transform::Mappable
9
- include Transform::Transposable
10
- include Transform::Invertible
11
-
12
- attr_reader :pitches
13
-
14
- def initialize(pitches)
15
- @pitches = pitches.to_a.uniq.sort.freeze
16
- end
17
-
18
- def elements
19
- @pitches
20
- end
21
-
22
- def self.from_a enumerable
23
- new enumerable
24
- end
25
-
26
- def to_pitch_class_set
27
- PitchClassSet.new @pitches.map{|p| p.pitch_class }
28
- end
29
-
30
- def pitch_classes
31
- @pitch_classes ||= @pitches.map{|p| p.pitch_class }.uniq
32
- end
33
-
34
- # generate a chord inversion (positive numbers move the lowest notes up an octave, negative moves the highest notes down)
35
- def inversion(number)
36
- number = number.to_i
37
- pitch_set = Array.new(@pitches)
38
- if number > 0
39
- number.times do |count|
40
- index = count % pitch_set.length
41
- pitch_set[index] += 12
42
- end
43
- else
44
- number.abs.times do |count|
45
- index = -(count + 1) % pitch_set.length # count from -1 downward to go backwards through the list starting at the end
46
- pitch_set[index] -= 12
47
- end
48
- end
49
- self.class.new pitch_set
50
- end
51
-
52
- def nearest(pitch_class)
53
- self.transpose @pitches.first.pitch_class.distance_to(pitch_class)
54
- end
55
-
56
- # @param other [#pitches, #to_a, Array]
57
- def == other
58
- if other.respond_to? :pitches
59
- @pitches == other.pitches
60
- elsif other.respond_to? :to_a
61
- @pitches == other.to_a
62
- else
63
- @pitches == other
64
- end
65
- end
66
-
67
- def to_s
68
- @pitches.inspect
69
- end
70
-
71
- end
72
-
73
- # Construct a {PitchSet} from any supported type
74
- def PitchSet(*anything)
75
- anything = anything.first if anything.size == 1
76
- case anything
77
- when Array then PitchSet.new(anything.map{|elem| Pitch(elem) })
78
- when PitchSet then anything
79
- else PitchSet.new([Pitch(anything)])
80
- end
81
- end
82
- module_function :PitchSet
83
-
84
- end
@@ -1,29 +0,0 @@
1
- module MTK
2
- module Sequencer
3
-
4
- # A Sequencer which uses a :rhythm type {Pattern} to determine the delta times between entries in the {Timeline}.
5
- class RhythmicSequencer < AbstractSequencer
6
-
7
- def initialize(patterns, options={})
8
- patterns = patterns.clone
9
- patterns.each_with_index do |pattern, index|
10
- if pattern.type == :rhythm
11
- @rhythm = pattern
12
- patterns.delete_at index # so we don't enumerate the rhythm values in EventBuilder
13
- end
14
- end
15
- super(patterns, options)
16
- end
17
-
18
- ########################
19
- protected
20
-
21
- # (see AbstractSequencer#advance!)
22
- def advance!
23
- @time += @rhythm.next
24
- end
25
-
26
- end
27
-
28
- end
29
- end
@@ -1,15 +0,0 @@
1
- module MTK::Transform
2
-
3
- # {Mappable} class whose elements can handle the :invert message
4
- # @note Classes including this module should include either MTK::Collection or provide a #first method
5
- module Invertible
6
-
7
- # Invert all elements around the given inversion point
8
- # @param inversion_point [Numeric] the value around which all elements will be inverted (defaults to the first element in the collection)
9
- def invert(inversion_point=first)
10
- map{|elem| elem.invert(inversion_point) }
11
- end
12
-
13
- end
14
-
15
- end
@@ -1,18 +0,0 @@
1
- module MTK::Transform
2
-
3
- # Similar to Enumerable, but relies on the including Class's from_a method to
4
- # provide an implementation of #map which returns an object of the same type.
5
- module Mappable
6
- include Enumerable
7
-
8
- # the original Enumerable#map implementation, which returns an Array
9
- alias enumerable_map map
10
-
11
- # the overriden #map implementation, which returns an object of the same type
12
- def map &block
13
- self.class.from_a(enumerable_map &block)
14
- end
15
-
16
- end
17
-
18
- end
@@ -1,34 +0,0 @@
1
- module MTK::Transform
2
-
3
- # {Helper::Collection} that supports set theory operations
4
- module SetTheoryOperations
5
-
6
- # the collection of elements present in both sets
7
- def intersection(other)
8
- self.class.from_a(to_a & other.to_a)
9
- end
10
-
11
- # the collection of all elements present in either set
12
- def union(other)
13
- self.class.from_a(to_a | other.to_a)
14
- end
15
-
16
- # the collection of elements from this set with any elements from the other set removed
17
- def difference(other)
18
- self.class.from_a(to_a - other.to_a)
19
- end
20
-
21
- # the collection of elements that are members of exactly one of the sets
22
- def symmetric_difference(other)
23
- union(other).difference( intersection(other) )
24
- end
25
-
26
- # the collection of elements that are not members of this set
27
- # @note this method requires that the including class define the class method .all(), which returns the collection of all possible elements
28
- def complement
29
- self.class.all.difference(self)
30
- end
31
-
32
- end
33
-
34
- end
@@ -1,14 +0,0 @@
1
- module MTK::Transform
2
-
3
- # {Mappable} class whose elements can handle the :transpose message
4
- module Transposable
5
-
6
- # Transpose all elements upward by the given interval
7
- # @param interval_in_semitones [Numeric] an interval in semitones
8
- def transpose interval_in_semitones
9
- map{|elem| elem + interval_in_semitones }
10
- end
11
-
12
- end
13
-
14
- end
@@ -1,139 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Event do
4
-
5
- let(:intensity) { mf }
6
- let(:duration) { 2.5 }
7
- let(:event) { Event.new(intensity, duration) }
8
-
9
- describe "#intensity" do
10
- it "is the intensity used to create the Event" do
11
- event.intensity.should == intensity
12
- end
13
-
14
- it "is a read-only attribute" do
15
- lambda{ event.intensity = 0 }.should raise_error
16
- end
17
- end
18
-
19
- describe "#duration" do
20
- it "is the duration used to create the Event" do
21
- event.duration.should == duration
22
- end
23
-
24
- it "is a read-only attribute" do
25
- lambda{ event.duration = 0 }.should raise_error
26
- end
27
-
28
- it "is always positive (absolute value of the duration used to construct the Event)" do
29
- Event.new(intensity, -duration).duration.should == duration
30
- end
31
- end
32
-
33
- describe "#rest?" do
34
- it "is true when the duration used to create the Event was negative" do
35
- Event.new(intensity, -duration).rest?.should be_true
36
- end
37
-
38
- it "is false when the duration used to create the Event was positive" do
39
- event.rest?.should be_false
40
- end
41
- end
42
-
43
- describe "from_hash" do
44
- it "constructs an Event using a hash" do
45
- Event.from_hash({ :intensity => intensity, :duration => duration }).should == event
46
- end
47
- end
48
-
49
- describe "#to_hash" do
50
- it "is a hash containing all the attributes of the Event" do
51
- event.to_hash.should == { :intensity => intensity, :duration => duration }
52
- end
53
- end
54
-
55
- describe "#clone_with" do
56
- it "clones the Event when given an empty hash" do
57
- event.clone_with({}).should == event
58
- end
59
-
60
- it "creates an Event with the given :intensity, and the current Event's duration if not provided" do
61
- event2 = event.clone_with :intensity => (intensity * 0.5)
62
- event2.intensity.should == (intensity * 0.5)
63
- event2.duration.should == duration
64
- end
65
-
66
- it "creates an Event with the given :duration, and the current Event's intensity if not provided" do
67
- event2 = event.clone_with :duration => (duration * 2)
68
- event2.intensity.should == intensity
69
- event2.duration.should == (duration * 2)
70
- end
71
- end
72
-
73
- describe '#scale_intensity' do
74
- it 'multiplies @intensity by the argument' do
75
- (event.scale_intensity 0.5).should == Event.new(intensity * 0.5, duration)
76
- end
77
- it 'does not affect the immutability of the Evebt' do
78
- (event.scale_intensity 0.5).should_not == event
79
- end
80
- end
81
-
82
- describe '#scale_duration' do
83
- it 'multiplies @duration by the argument' do
84
- (event.scale_duration 2).should == Event.new(intensity, duration*2)
85
- end
86
- it 'does not affect the immutability of the Event' do
87
- (event.scale_duration 0.5).should_not == event
88
- end
89
- end
90
-
91
- describe "#velocity" do
92
- it "converts intensities in the range 0.0-1.0 to a MIDI velocity in the range 0-127" do
93
- Event.new(0, 0).velocity.should == 0
94
- Event.new(1, 0).velocity.should == 127
95
- end
96
- it "rounds to the nearest MIDI velocity" do
97
- Event.new(0.5, 0).velocity.should == 64 # not be truncated to 63!
98
- end
99
- end
100
-
101
- describe "#duration_in_pulses" do
102
- it "converts beats to pulses, given pulses_per_beat" do
103
- Event.new(0,1).duration_in_pulses(60).should == 60
104
- end
105
-
106
- it "rounds to the nearest pulse" do
107
- Event.new(0,1.5).duration_in_pulses(59).should == 89
108
- end
109
-
110
- it "is always positive (uses absolute value of the duration used to construct the Event)" do
111
- Event.new(intensity, -1).duration_in_pulses(60).should == 60
112
- end
113
- end
114
-
115
- describe "#==" do
116
- it "is true when the intensities and durations are equal" do
117
- event.should == Event.new(intensity, duration)
118
- end
119
- it "is false when the intensities are not equal" do
120
- event.should_not == Event.new(intensity * 0.5, duration)
121
- end
122
- it "is false when the durations are not equal" do
123
- event.should_not == Event.new(intensity, duration * 2)
124
- end
125
- end
126
-
127
- describe "#to_s" do
128
- it "is the intensity and duration to 2-decimal places" do
129
- Event.new(0.454545, 0.789789).to_s.should == "0.45, 0.79"
130
- end
131
- end
132
-
133
- describe "#inspect" do
134
- it "is the string values of intensity and duration" do
135
- Event.new(0.454545, 0.789789).inspect.should == "0.454545, 0.789789"
136
- end
137
- end
138
-
139
- end
@@ -1,92 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MTK::Helper::EventBuilder do
4
-
5
- EVENT_BUILDER = MTK::Helper::EventBuilder
6
-
7
- let(:intensity) { EVENT_BUILDER::DEFAULT_INTENSITY }
8
- let(:duration) { EVENT_BUILDER::DEFAULT_DURATION }
9
-
10
- def notes(*pitches)
11
- pitches.map{|pitch| Note(pitch, intensity, duration) }
12
- end
13
-
14
-
15
- describe "#next" do
16
- it "builds a single-note list from a single-pitch list argument" do
17
- event_builder = EVENT_BUILDER.new [Pattern.Cycle(C4)]
18
- event_builder.next.should == notes(C4)
19
- end
20
-
21
- it "builds a list of notes from any pitches in the argument" do
22
- event_builder = EVENT_BUILDER.new [Pattern.Cycle(C4), Pattern.Cycle(D4)]
23
- event_builder.next.should == notes(C4, D4)
24
- end
25
-
26
- it "builds a list of notes from pitch sets" do
27
- event_builder = EVENT_BUILDER.new [ Pattern.Cycle( PitchSet(C4,D4) ) ]
28
- event_builder.next.should == notes(C4, D4)
29
- end
30
-
31
- it "builds notes from pitch classes and a default_pitch, selecting the nearest pitch class to the previous pitch" do
32
- event_builder = EVENT_BUILDER.new [Pattern.Sequence(C,G,B,Eb,D,C)], :default_pitch => D3
33
- notes = []
34
- loop do
35
- notes << event_builder.next
36
- end
37
- notes.flatten.should == notes(C3,G2,B2,Eb3,D3,C3)
38
- end
39
-
40
- it "defaults to a starting point of C4 (middle C)" do
41
- event_builder = EVENT_BUILDER.new [Pattern.Sequence(C4)]
42
- event_builder.next.should == notes(C4)
43
- end
44
-
45
- it "builds notes from pitch class sets, selecting the neartest pitch classes to the previous/default pitch" do
46
- pitch_class_sequence = Pattern::Sequence.new([PitchClassSet(C,G),PitchClassSet(B,Eb),PitchClassSet(D,C)])
47
- event_builder = EVENT_BUILDER.new [pitch_class_sequence], :default_pitch => D3
48
- event_builder.next.should == notes(C3,G3)
49
- event_builder.next.should == notes(B3,Eb3)
50
- event_builder.next.should == notes(D3,C3)
51
- end
52
-
53
- it "builds notes from by adding Numeric intervals in :pitch type Patterns to the previous Pitch" do
54
- event_builder = EVENT_BUILDER.new [ Pattern.PitchSequence( C4, M3, m3, -P5) ]
55
- nexts = []
56
- loop { nexts << event_builder.next }
57
- nexts.should == [notes(C4), notes(E4), notes(G4), notes(C4)]
58
- end
59
-
60
- it "builds notes from by adding Numeric intervals in :pitch type Patterns to all pitches in the previous PitchSet" do
61
- event_builder = EVENT_BUILDER.new [ Pattern.PitchSequence( PitchSet(C4,Eb4), M3, m3, -P5) ]
62
- nexts = []
63
- loop { nexts << event_builder.next }
64
- nexts.should == [notes(C4,Eb4), notes(E4,G4), notes(G4,Bb4), notes(C4,Eb4)]
65
- end
66
-
67
- it "builds notes from intensities" do
68
- event_builder = EVENT_BUILDER.new [ Pattern.PitchCycle(C4), Pattern.IntensitySequence(mf, p, fff) ]
69
- nexts = []
70
- loop { nexts += event_builder.next }
71
- nexts.should == [Note(C4, mf, duration), Note(C4, p, duration), Note(C4, fff, duration)]
72
- end
73
-
74
- it "builds notes from durations" do
75
- event_builder = EVENT_BUILDER.new [ Pattern.PitchCycle(C4), Pattern.DurationSequence(1,2,3) ]
76
- nexts = []
77
- loop { nexts += event_builder.next }
78
- nexts.should == [Note(C4, intensity, 1), Note(C4, intensity, 2), Note(C4, intensity, 3)]
79
- end
80
- end
81
-
82
- describe "#rewind" do
83
- it "resets the state of the EventBuilder" do
84
- event_builder = EVENT_BUILDER.new [ Pattern.PitchSequence(C,P8) ]
85
- event_builder.next.should == [Note(C4,intensity,duration)]
86
- event_builder.next.should == [Note(C5,intensity,duration)]
87
- event_builder.rewind
88
- event_builder.next.should == [Note(C4,intensity,duration)]
89
- end
90
- end
91
-
92
- end