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.
- 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
|