mtk 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/mtk/pattern/sequence.rb
DELETED
@@ -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
|
data/spec/mtk/event_spec.rb
DELETED
@@ -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
|