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
@@ -1,8 +1,8 @@
|
|
1
1
|
module MTK
|
2
|
-
module
|
2
|
+
module Sequencers
|
3
3
|
|
4
4
|
# A Sequencer which has a constant {#step_size} time between {Timeline} entries.
|
5
|
-
class StepSequencer <
|
5
|
+
class StepSequencer < Sequencer
|
6
6
|
|
7
7
|
# The time between entries in the {Timeline}.
|
8
8
|
attr_accessor :step_size
|
@@ -15,8 +15,8 @@ module MTK
|
|
15
15
|
########################
|
16
16
|
protected
|
17
17
|
|
18
|
-
# (see
|
19
|
-
def advance
|
18
|
+
# (see Sequencer#advance)
|
19
|
+
def advance
|
20
20
|
@time += @step_size
|
21
21
|
end
|
22
22
|
|
data/lib/mtk/timeline.rb
CHANGED
@@ -2,13 +2,12 @@ module MTK
|
|
2
2
|
|
3
3
|
# A collection of timed events. The core data structure used to interface with input and output.
|
4
4
|
#
|
5
|
-
# Maps sorted times to lists of events.
|
5
|
+
# Maps sorted floating point times to lists of events.
|
6
6
|
#
|
7
7
|
# Enumerable as [time,event_list] pairs.
|
8
8
|
#
|
9
9
|
class Timeline
|
10
|
-
|
11
|
-
include Transform::Mappable
|
10
|
+
include Enumerable
|
12
11
|
|
13
12
|
def initialize()
|
14
13
|
@timeline = {}
|
@@ -22,7 +21,7 @@ module MTK
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def merge enumerable
|
25
|
-
|
24
|
+
enumerable.each do |time,events|
|
26
25
|
add(time,events)
|
27
26
|
end
|
28
27
|
self
|
@@ -43,23 +42,23 @@ module MTK
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def [](time)
|
46
|
-
@timeline[time]
|
45
|
+
@timeline[time.to_f]
|
47
46
|
end
|
48
47
|
|
49
48
|
def []=(time, events)
|
50
49
|
time = time.to_f unless time.is_a? Numeric
|
51
50
|
case events
|
52
51
|
when nil?
|
53
|
-
@timeline.delete time
|
52
|
+
@timeline.delete time.to_f
|
54
53
|
when Array
|
55
|
-
@timeline[time] = events
|
54
|
+
@timeline[time.to_f] = events
|
56
55
|
else
|
57
|
-
@timeline[time] = [events]
|
56
|
+
@timeline[time.to_f] = [events]
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
60
|
def add(time, event)
|
62
|
-
events = @timeline[time]
|
61
|
+
events = @timeline[time.to_f]
|
63
62
|
if events
|
64
63
|
if event.is_a? Array
|
65
64
|
events.concat event
|
@@ -72,17 +71,23 @@ module MTK
|
|
72
71
|
end
|
73
72
|
|
74
73
|
def delete(time)
|
75
|
-
@timeline.delete(time)
|
74
|
+
@timeline.delete(time.to_f)
|
76
75
|
end
|
77
76
|
|
78
77
|
def has_time? time
|
79
|
-
@timeline.has_key? time
|
78
|
+
@timeline.has_key? time.to_f
|
80
79
|
end
|
81
80
|
|
82
81
|
def times
|
83
82
|
@timeline.keys.sort
|
84
83
|
end
|
85
84
|
|
85
|
+
def length
|
86
|
+
last_time = times.last
|
87
|
+
events = @timeline[last_time]
|
88
|
+
last_time + events.map{|event| event.duration }.max
|
89
|
+
end
|
90
|
+
|
86
91
|
def empty?
|
87
92
|
@timeline.empty?
|
88
93
|
end
|
@@ -93,15 +98,24 @@ module MTK
|
|
93
98
|
|
94
99
|
def each
|
95
100
|
# this is similar to @timeline.each, but by iterating over #times, we yield the events in chronological order
|
96
|
-
|
97
|
-
yield time
|
101
|
+
times.each do |time|
|
102
|
+
yield time, @timeline[time]
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
106
|
+
# the original Enumerable#map implementation, which returns an Array
|
107
|
+
alias enumerable_map map
|
108
|
+
|
109
|
+
# Constructs a new Timeline by mapping each [time,event_list] pair
|
110
|
+
# @see #map!
|
111
|
+
def map &block
|
112
|
+
self.class.from_a enumerable_map(&block)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Perform #map in place
|
116
|
+
# @see #map
|
101
117
|
def map! &block
|
102
|
-
|
103
|
-
# because Mappable#map will create an extra timeline instance, which is unnecessary in this case
|
104
|
-
mapped = enumerable_map &block
|
118
|
+
mapped = enumerable_map(&block)
|
105
119
|
clear
|
106
120
|
merge mapped
|
107
121
|
end
|
@@ -109,7 +123,7 @@ module MTK
|
|
109
123
|
# Map every individual event, without regard for the time at which is occurs
|
110
124
|
def map_events
|
111
125
|
mapped_timeline = Timeline.new
|
112
|
-
|
126
|
+
self.each do |time,events|
|
113
127
|
mapped_timeline[time] = events.map{|event| yield event }
|
114
128
|
end
|
115
129
|
mapped_timeline
|
@@ -117,7 +131,7 @@ module MTK
|
|
117
131
|
|
118
132
|
# Map every individual event in place, without regard for the time at which is occurs
|
119
133
|
def map_events!
|
120
|
-
|
134
|
+
each do |time,events|
|
121
135
|
self[time] = events.map{|event| yield event }
|
122
136
|
end
|
123
137
|
end
|
@@ -132,10 +146,10 @@ module MTK
|
|
132
146
|
|
133
147
|
def flatten
|
134
148
|
flattened = Timeline.new
|
135
|
-
|
136
|
-
|
149
|
+
self.each do |time,events|
|
150
|
+
events.each do |event|
|
137
151
|
if event.is_a? Timeline
|
138
|
-
|
152
|
+
event.flatten.each do |subtime,subevent|
|
139
153
|
flattened.add(time+subtime, subevent)
|
140
154
|
end
|
141
155
|
else
|
@@ -195,7 +209,10 @@ module MTK
|
|
195
209
|
end
|
196
210
|
|
197
211
|
def to_s
|
198
|
-
times
|
212
|
+
times = self.times
|
213
|
+
last = times.last
|
214
|
+
width = sprintf("%d",last).length + 3 # nicely align the '=>' against the longest number
|
215
|
+
times.map{|t| sprintf("%#{width}.2f",t)+" => #{@timeline[t].join ', '}" }.join "\n"
|
199
216
|
end
|
200
217
|
|
201
218
|
def inspect
|
data/lib/mtk/variable.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module MTK
|
2
|
+
|
3
|
+
# A placeholder element for a variable value, for use within a {Patterns::Pattern} such as a {Patterns::ForEach} pattern.
|
4
|
+
# Will be evaluated to an actual value by the Pattern or Sequencer
|
5
|
+
#
|
6
|
+
class Variable
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
attr_accessor :value
|
11
|
+
|
12
|
+
def initialize name, value=nil
|
13
|
+
@name = name
|
14
|
+
@value = value
|
15
|
+
@implicit = !!(name =~ /^\$+$/)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return true when this variable has no specific value and references the implicit variable stack (such as in a {Patterns::ForEach})
|
19
|
+
def implicit?
|
20
|
+
@implicit
|
21
|
+
end
|
22
|
+
|
23
|
+
def == other
|
24
|
+
other.is_a? self.class and other.name == self.name
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{self.class}<#{name}#{'='+value.to_s if value}>"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MTK::Chord do
|
4
|
+
|
5
|
+
let(:c_major) { Chord.new([C4,E4,G4]) }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
it "removes duplicates" do
|
9
|
+
Chord.new([C4, E4, G4, C4]).pitches.should == [C4, E4, G4]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sorts the pitches" do
|
13
|
+
Chord.new([F4, G4, E4, D4, C4]).pitches.should == [C4, D4, E4, F4, G4]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#inversion' do
|
18
|
+
it "adds an octave to the chord's pitches starting from the lowest, for each whole number in a postive argument" do
|
19
|
+
c_major.inversion(2).should == Chord.new([G4,C5,E5])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "subtracts an octave to the chord's pitches starting fromt he highest, for each whole number in a negative argument" do
|
23
|
+
c_major.inversion(-2).should == Chord.new([E3,G3,C4])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "wraps around to the lowest pitch when the argument is bigger than the number of pitches in the chord (positive argument)" do
|
27
|
+
c_major.inversion(4).should == Chord.new([E5,G5,C6])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "wraps around to the highest pitch when the magnitude of the argument is bigger than the number of pitches in the chord (negative argument)" do
|
31
|
+
c_major.inversion(-4).should == Chord.new([G2,C3,E3])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#nearest" do
|
36
|
+
it "returns the nearest Melody where the first Pitch has the given PitchClass" do
|
37
|
+
c_major.nearest(F).should == c_major.transpose(5)
|
38
|
+
c_major.nearest(G).should == c_major.transpose(-5)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe MTK do
|
45
|
+
|
46
|
+
describe '#Chord' do
|
47
|
+
|
48
|
+
it "acts like new for a single Array argument" do
|
49
|
+
Chord([C4,D4]).should == Chord.new([C4,D4])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "acts like new for multiple arguments, by treating them like an Array (splat)" do
|
53
|
+
Chord(C4,D4).should == Chord.new([C4,D4])
|
54
|
+
end
|
55
|
+
|
56
|
+
it "handles an Array with elements that can be converted to Pitches" do
|
57
|
+
Chord(['C4','D4']).should == Chord.new([C4,D4])
|
58
|
+
end
|
59
|
+
|
60
|
+
it "handles multiple arguments that can be converted to a Pitch" do
|
61
|
+
Chord(:C4,:D4).should == Chord.new([C4,D4])
|
62
|
+
end
|
63
|
+
|
64
|
+
it "handles a single Pitch" do
|
65
|
+
Chord(C4).should == Chord.new([C4])
|
66
|
+
end
|
67
|
+
|
68
|
+
it "handles single elements that can be converted to a Pitch" do
|
69
|
+
Chord('C4').should == Chord.new([C4])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns the argument if it's already a Chord" do
|
73
|
+
pitch_set = Chord.new([C4,D4,D4])
|
74
|
+
Chord(pitch_set).should == Chord.new([C4,D4])
|
75
|
+
end
|
76
|
+
|
77
|
+
it "raises an error for types it doesn't understand" do
|
78
|
+
lambda{ Chord({:not => :compatible}) }.should raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::Durations do
|
3
|
+
describe MTK::Constants::Durations do
|
4
4
|
|
5
5
|
describe 'w' do
|
6
6
|
it 'is 4 beats' do
|
7
|
-
w.should == 4
|
7
|
+
w.value.should == 4
|
8
8
|
end
|
9
9
|
it 'is available via a module property and via mixin' do
|
10
10
|
Durations::w.should == w
|
@@ -13,7 +13,7 @@ describe MTK::Durations do
|
|
13
13
|
|
14
14
|
describe 'h' do
|
15
15
|
it 'is 2 beats' do
|
16
|
-
h.should == 2
|
16
|
+
h.value.should == 2
|
17
17
|
end
|
18
18
|
it 'is available via a module property and via mixin' do
|
19
19
|
Durations::h.should == h
|
@@ -22,25 +22,25 @@ describe MTK::Durations do
|
|
22
22
|
|
23
23
|
describe 'q' do
|
24
24
|
it 'is 1 beat' do
|
25
|
-
q.
|
25
|
+
q.value.should == 1
|
26
26
|
end
|
27
27
|
it 'is available via a module property and via mixin' do
|
28
28
|
Durations::q.should == q
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe '
|
32
|
+
describe 'i' do
|
33
33
|
it 'is 1/2 of a beat' do
|
34
|
-
|
34
|
+
i.value.should == 1.0/2
|
35
35
|
end
|
36
36
|
it 'is available via a module property and via mixin' do
|
37
|
-
Durations::
|
37
|
+
Durations::i.should == i
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe 's' do
|
42
42
|
it 'is 1/4 of a beat' do
|
43
|
-
s.should == 1.0/4
|
43
|
+
s.value.should == 1.0/4
|
44
44
|
end
|
45
45
|
it 'is available via a module property and via mixin' do
|
46
46
|
Durations::s.should == s
|
@@ -49,7 +49,7 @@ describe MTK::Durations do
|
|
49
49
|
|
50
50
|
describe 'r' do
|
51
51
|
it 'is 1/8 of a beat' do
|
52
|
-
r.should == 1.0/8
|
52
|
+
r.value.should == 1.0/8
|
53
53
|
end
|
54
54
|
it 'is available via a module property and via mixin' do
|
55
55
|
Durations::r.should == r
|
@@ -58,7 +58,7 @@ describe MTK::Durations do
|
|
58
58
|
|
59
59
|
describe 'x' do
|
60
60
|
it 'is 1/16 of a beat' do
|
61
|
-
x.should == 1.0/16
|
61
|
+
x.value.should == 1.0/16
|
62
62
|
end
|
63
63
|
it 'is available via a module property and via mixin' do
|
64
64
|
Durations::x.should == x
|
@@ -67,7 +67,7 @@ describe MTK::Durations do
|
|
67
67
|
|
68
68
|
describe "DURATIONS" do
|
69
69
|
it "contains all Durations pseudo-constants" do
|
70
|
-
Durations::DURATIONS.should =~ [w, h, q,
|
70
|
+
Durations::DURATIONS.should =~ [w, h, q, i, s, r, x]
|
71
71
|
end
|
72
72
|
|
73
73
|
it "is immutable" do
|
@@ -77,7 +77,7 @@ describe MTK::Durations do
|
|
77
77
|
|
78
78
|
describe "DURATION_NAMES" do
|
79
79
|
it "contains all Durations pseudo-constants names as strings" do
|
80
|
-
Durations::DURATION_NAMES.should =~ ['w', 'h', 'q', '
|
80
|
+
Durations::DURATION_NAMES.should =~ ['w', 'h', 'q', 'i', 's', 'r', 'x']
|
81
81
|
end
|
82
82
|
|
83
83
|
it "is immutable" do
|
@@ -85,34 +85,5 @@ describe MTK::Durations do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
describe ".[]" do
|
89
|
-
it "looks up the constant by name" do
|
90
|
-
for duration in Durations::DURATION_NAMES
|
91
|
-
Durations[duration].should == Durations.send(duration)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it "supports a '.' suffix, which multiples the value by 1.5" do
|
96
|
-
for duration in Durations::DURATION_NAMES
|
97
|
-
Durations["#{duration}."].should == Durations.send(duration) * 1.5
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
it "supports a 't' suffix, which multiples the value by 2/3" do
|
102
|
-
for duration in Durations::DURATION_NAMES
|
103
|
-
Durations["#{duration}t"].should == Durations.send(duration) * 2/3.0
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
it "supports '.' and 't' suffixes in any combination" do
|
108
|
-
for duration in Durations::DURATION_NAMES
|
109
|
-
Durations["#{duration}.t"].should == Durations.send(duration) * 1.5 * 2/3.0
|
110
|
-
Durations["#{duration}t."].should == Durations.send(duration) * 1.5 * 2/3.0
|
111
|
-
Durations["#{duration}.."].should == Durations.send(duration) * 1.5 * 1.5
|
112
|
-
Durations["#{duration}..t.t."].should == Durations.send(duration) * 1.5**4 * (2/3.0)**2
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
88
|
end
|
118
89
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MTK::Intensities do
|
3
|
+
describe MTK::Constants::Intensities do
|
4
4
|
|
5
5
|
describe 'ppp' do
|
6
6
|
it 'is equivalent to MIDI velocity 16' do
|
7
|
-
(ppp * 127).round.should == 16
|
7
|
+
(ppp.value * 127).round.should == 16
|
8
8
|
end
|
9
9
|
it 'is available via a module property and via mixin' do
|
10
10
|
Intensities::ppp.should == ppp
|
@@ -13,7 +13,7 @@ describe MTK::Intensities do
|
|
13
13
|
|
14
14
|
describe 'pp' do
|
15
15
|
it 'is equivalent to MIDI velocity 32' do
|
16
|
-
(pp * 127).round.should == 32
|
16
|
+
(pp.value * 127).round.should == 32
|
17
17
|
end
|
18
18
|
it 'is available via a module property and via mixin' do
|
19
19
|
Intensities::pp.should == pp
|
@@ -22,7 +22,7 @@ describe MTK::Intensities do
|
|
22
22
|
|
23
23
|
describe 'p' do
|
24
24
|
it 'is equivalent to MIDI velocity 48' do
|
25
|
-
(p * 127).round.should == 48
|
25
|
+
(p.value * 127).round.should == 48
|
26
26
|
end
|
27
27
|
it 'is available via a module property and via mixin' do
|
28
28
|
Intensities::p.should == p
|
@@ -31,7 +31,7 @@ describe MTK::Intensities do
|
|
31
31
|
|
32
32
|
describe 'mp' do
|
33
33
|
it 'is equivalent to MIDI velocity 64' do
|
34
|
-
(mp * 127).round.should == 64
|
34
|
+
(mp.value * 127).round.should == 64
|
35
35
|
end
|
36
36
|
it 'is available via a module property and via mixin' do
|
37
37
|
Intensities::mp.should == mp
|
@@ -40,19 +40,19 @@ describe MTK::Intensities do
|
|
40
40
|
|
41
41
|
describe 'mf' do
|
42
42
|
it 'is equivalent to MIDI velocity 79' do
|
43
|
-
(mf * 127).round.should == 79
|
43
|
+
(mf.value * 127).round.should == 79
|
44
44
|
end
|
45
45
|
it 'is available via a module property and via mixin' do
|
46
46
|
Intensities::mf.should == mf
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
describe '
|
50
|
+
describe 'o' do # AKA forte
|
51
51
|
it 'is equivalent to MIDI velocity 95' do
|
52
|
-
(
|
52
|
+
(o.value * 127).round.should == 95
|
53
53
|
end
|
54
54
|
it 'is available via a module property and via mixin' do
|
55
|
-
Intensities::
|
55
|
+
Intensities::o.should == o
|
56
56
|
end
|
57
57
|
it "does not overwrite the PitchClass constant 'F'" do
|
58
58
|
F.should be_a PitchClass
|
@@ -61,7 +61,7 @@ describe MTK::Intensities do
|
|
61
61
|
|
62
62
|
describe 'ff' do
|
63
63
|
it 'is equivalent to MIDI velocity 111' do
|
64
|
-
(ff * 127).round.should == 111
|
64
|
+
(ff.value * 127).round.should == 111
|
65
65
|
end
|
66
66
|
it 'is available via a module property and via mixin' do
|
67
67
|
Intensities::ff.should == ff
|
@@ -70,7 +70,7 @@ describe MTK::Intensities do
|
|
70
70
|
|
71
71
|
describe 'fff' do
|
72
72
|
it 'is equivalent to MIDI velocity 127' do
|
73
|
-
(fff * 127).round.should == 127
|
73
|
+
(fff.value * 127).round.should == 127
|
74
74
|
end
|
75
75
|
it 'is available via a module property and via mixin' do
|
76
76
|
Intensities::fff.should == fff
|
@@ -79,7 +79,7 @@ describe MTK::Intensities do
|
|
79
79
|
|
80
80
|
describe "INTENSITIES" do
|
81
81
|
it "contains all Intensities pseudo-constants" do
|
82
|
-
Intensities::INTENSITIES.should =~ [ppp, pp, p, mp, mf,
|
82
|
+
Intensities::INTENSITIES.should =~ [ppp, pp, p, mp, mf, o, ff, fff]
|
83
83
|
end
|
84
84
|
|
85
85
|
it "is immutable" do
|
@@ -89,7 +89,7 @@ describe MTK::Intensities do
|
|
89
89
|
|
90
90
|
describe "INTENSITY_NAMES" do
|
91
91
|
it "contains all Intensities pseudo-constants names as strings" do
|
92
|
-
Intensities::INTENSITY_NAMES.should =~ ['ppp', 'pp', 'p', 'mp', 'mf', '
|
92
|
+
Intensities::INTENSITY_NAMES.should =~ ['ppp', 'pp', 'p', 'mp', 'mf', 'o', 'ff', 'fff']
|
93
93
|
end
|
94
94
|
|
95
95
|
it "is immutable" do
|
@@ -97,29 +97,5 @@ describe MTK::Intensities do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
describe ".[]" do
|
101
|
-
it "looks up the constant by name" do
|
102
|
-
for name in INTENSITY_NAMES
|
103
|
-
Intensities[name].should == Intensities.send(name)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
it "adds 1.0/24 when the name ends with '+', except for 'fff+' which is 1.0 like 'fff'" do
|
108
|
-
for name in INTENSITY_NAMES
|
109
|
-
if name == 'fff'
|
110
|
-
Intensities["#{name}+"].should == 1.0
|
111
|
-
else
|
112
|
-
Intensities["#{name}+"].should == Intensities.send(name)+1.0/24
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
it "subtracts 1.0/24 when the name ends with '-'" do
|
118
|
-
for name in INTENSITY_NAMES
|
119
|
-
Intensities["#{name}-"].should == Intensities.send(name)-1.0/24
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
100
|
end
|
125
101
|
|