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