jmtk 0.0.3.3-java
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 +10 -0
- data/DEVELOPMENT_NOTES.md +115 -0
- data/INTRO.md +129 -0
- data/LICENSE.txt +27 -0
- data/README.md +50 -0
- data/Rakefile +102 -0
- data/bin/jmtk +250 -0
- data/bin/mtk +250 -0
- data/examples/crescendo.rb +20 -0
- data/examples/drum_pattern.rb +23 -0
- data/examples/dynamic_pattern.rb +36 -0
- data/examples/gets_and_play.rb +27 -0
- data/examples/notation.rb +22 -0
- data/examples/play_midi.rb +17 -0
- data/examples/print_midi.rb +13 -0
- data/examples/random_tone_row.rb +18 -0
- data/examples/syntax_to_midi.rb +28 -0
- data/examples/test_output.rb +7 -0
- data/examples/tone_row_melody.rb +23 -0
- data/lib/mtk.rb +76 -0
- data/lib/mtk/core/duration.rb +213 -0
- data/lib/mtk/core/intensity.rb +158 -0
- data/lib/mtk/core/interval.rb +157 -0
- data/lib/mtk/core/pitch.rb +154 -0
- data/lib/mtk/core/pitch_class.rb +194 -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/events/timeline.rb +232 -0
- data/lib/mtk/groups/chord.rb +56 -0
- data/lib/mtk/groups/collection.rb +196 -0
- data/lib/mtk/groups/melody.rb +96 -0
- data/lib/mtk/groups/pitch_class_set.rb +163 -0
- data/lib/mtk/groups/pitch_collection.rb +23 -0
- data/lib/mtk/io/dls_synth_device.rb +146 -0
- data/lib/mtk/io/dls_synth_output.rb +62 -0
- data/lib/mtk/io/jsound_input.rb +87 -0
- data/lib/mtk/io/jsound_output.rb +82 -0
- data/lib/mtk/io/midi_file.rb +209 -0
- data/lib/mtk/io/midi_input.rb +97 -0
- data/lib/mtk/io/midi_output.rb +195 -0
- data/lib/mtk/io/notation.rb +162 -0
- data/lib/mtk/io/unimidi_input.rb +117 -0
- data/lib/mtk/io/unimidi_output.rb +140 -0
- data/lib/mtk/lang/durations.rb +57 -0
- data/lib/mtk/lang/intensities.rb +61 -0
- data/lib/mtk/lang/intervals.rb +73 -0
- data/lib/mtk/lang/mtk_grammar.citrus +237 -0
- data/lib/mtk/lang/parser.rb +29 -0
- data/lib/mtk/lang/pitch_classes.rb +29 -0
- data/lib/mtk/lang/pitches.rb +52 -0
- data/lib/mtk/lang/pseudo_constants.rb +26 -0
- data/lib/mtk/lang/variable.rb +32 -0
- data/lib/mtk/numeric_extensions.rb +66 -0
- data/lib/mtk/patterns/chain.rb +49 -0
- data/lib/mtk/patterns/choice.rb +43 -0
- 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/patterns/lines.rb +54 -0
- data/lib/mtk/patterns/palindrome.rb +45 -0
- data/lib/mtk/patterns/pattern.rb +171 -0
- data/lib/mtk/patterns/sequence.rb +20 -0
- data/lib/mtk/sequencers/event_builder.rb +132 -0
- data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
- data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
- data/lib/mtk/sequencers/sequencer.rb +111 -0
- data/lib/mtk/sequencers/step_sequencer.rb +26 -0
- data/spec/mtk/core/duration_spec.rb +372 -0
- data/spec/mtk/core/intensity_spec.rb +289 -0
- data/spec/mtk/core/interval_spec.rb +265 -0
- data/spec/mtk/core/pitch_class_spec.rb +343 -0
- data/spec/mtk/core/pitch_spec.rb +297 -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/events/timeline_spec.rb +430 -0
- data/spec/mtk/groups/chord_spec.rb +85 -0
- data/spec/mtk/groups/collection_spec.rb +374 -0
- data/spec/mtk/groups/melody_spec.rb +225 -0
- data/spec/mtk/groups/pitch_class_set_spec.rb +340 -0
- data/spec/mtk/io/midi_file_spec.rb +243 -0
- data/spec/mtk/io/midi_output_spec.rb +102 -0
- data/spec/mtk/lang/durations_spec.rb +89 -0
- data/spec/mtk/lang/intensities_spec.rb +101 -0
- data/spec/mtk/lang/intervals_spec.rb +143 -0
- data/spec/mtk/lang/parser_spec.rb +603 -0
- data/spec/mtk/lang/pitch_classes_spec.rb +62 -0
- data/spec/mtk/lang/pitches_spec.rb +56 -0
- data/spec/mtk/lang/pseudo_constants_spec.rb +20 -0
- data/spec/mtk/lang/variable_spec.rb +52 -0
- data/spec/mtk/numeric_extensions_spec.rb +83 -0
- data/spec/mtk/patterns/chain_spec.rb +110 -0
- data/spec/mtk/patterns/choice_spec.rb +97 -0
- data/spec/mtk/patterns/cycle_spec.rb +123 -0
- data/spec/mtk/patterns/for_each_spec.rb +136 -0
- data/spec/mtk/patterns/function_spec.rb +120 -0
- data/spec/mtk/patterns/lines_spec.rb +77 -0
- data/spec/mtk/patterns/palindrome_spec.rb +108 -0
- data/spec/mtk/patterns/pattern_spec.rb +132 -0
- data/spec/mtk/patterns/sequence_spec.rb +203 -0
- 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/sequencers/step_sequencer_spec.rb +93 -0
- data/spec/spec_coverage.rb +2 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/test.mid +0 -0
- metadata +226 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generate a MIDI file using a tone row, repeated 3 times using random rhythms
|
2
|
+
#
|
3
|
+
# NOTE: this blindly overwrites any existing MTK-tone_row_melody.mid file, unless an argument is provided
|
4
|
+
|
5
|
+
require 'mtk'
|
6
|
+
require 'mtk/io/midi_file'
|
7
|
+
include MTK
|
8
|
+
include MTK::Lang::PitchClasses
|
9
|
+
include MTK::Lang::Durations
|
10
|
+
|
11
|
+
file = ARGV[0] || 'MTK-tone_row_melody.mid'
|
12
|
+
|
13
|
+
row = PitchClassSet Db, G, Ab, F, Eb, E, D, C, B, Gb, A, Bb
|
14
|
+
pitch_pattern = Patterns.Cycle *row
|
15
|
+
rhythm_pattern = Patterns.Choice s, i, i+s, q # choose between sixteenth, eighth, dotted eighth, and quarter
|
16
|
+
|
17
|
+
chain = Patterns.Chain pitch_pattern, rhythm_pattern, min_elements: 36, max_elements: 36
|
18
|
+
|
19
|
+
sequencer = Sequencers.LegatoSequencer chain
|
20
|
+
timeline = sequencer.to_timeline
|
21
|
+
|
22
|
+
MIDIFile(file).write timeline
|
23
|
+
|
data/lib/mtk.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Description of modules for documentation:
|
2
|
+
|
3
|
+
# The top level module for this library
|
4
|
+
module MTK
|
5
|
+
|
6
|
+
# Core data types
|
7
|
+
module Core
|
8
|
+
end
|
9
|
+
|
10
|
+
# Musical events, such as {MTK::Events::Note}s and {MTK::Events::Parameter} changes, that are arranged in time via a {MTK::Events::Timeline}.
|
11
|
+
module Events
|
12
|
+
end
|
13
|
+
|
14
|
+
# Collections of {MTK::Core} objects
|
15
|
+
module Groups
|
16
|
+
end
|
17
|
+
|
18
|
+
# Optional classes for MIDI {MTK::IO::File} and realtime MIDI {MTK::IO::Input} and {MTK::IO::Output}.
|
19
|
+
module IO
|
20
|
+
end
|
21
|
+
|
22
|
+
# Optional classes for the "MTK language", which let's you compose music via MTK without writing any Ruby code
|
23
|
+
module Lang
|
24
|
+
end
|
25
|
+
|
26
|
+
# Classes that emit elements one at a time. Used by {MTK::Sequencers::Sequencer}s to construct {MTK::Events::Timeline}s.
|
27
|
+
module Patterns
|
28
|
+
end
|
29
|
+
|
30
|
+
# Classes that assemble {MTK::Patterns::Pattern}s into {MTK::Events::Timeline}s.
|
31
|
+
module Sequencers
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'mtk/core/pitch_class'
|
37
|
+
require 'mtk/core/pitch'
|
38
|
+
require 'mtk/core/duration'
|
39
|
+
require 'mtk/core/intensity'
|
40
|
+
require 'mtk/core/interval'
|
41
|
+
|
42
|
+
require 'mtk/lang/pseudo_constants'
|
43
|
+
require 'mtk/lang/pitch_classes'
|
44
|
+
require 'mtk/lang/pitches'
|
45
|
+
require 'mtk/lang/intervals'
|
46
|
+
require 'mtk/lang/intensities'
|
47
|
+
require 'mtk/lang/durations'
|
48
|
+
require 'mtk/lang/variable'
|
49
|
+
require 'mtk/lang/parser'
|
50
|
+
|
51
|
+
require 'mtk/groups/collection'
|
52
|
+
require 'mtk/groups/pitch_collection'
|
53
|
+
require 'mtk/groups/pitch_class_set'
|
54
|
+
require 'mtk/groups/melody'
|
55
|
+
require 'mtk/groups/chord'
|
56
|
+
|
57
|
+
require 'mtk/events/event'
|
58
|
+
require 'mtk/events/note'
|
59
|
+
require 'mtk/events/parameter'
|
60
|
+
require 'mtk/events/timeline'
|
61
|
+
|
62
|
+
require 'mtk/patterns/pattern'
|
63
|
+
require 'mtk/patterns/sequence'
|
64
|
+
require 'mtk/patterns/cycle'
|
65
|
+
require 'mtk/patterns/choice'
|
66
|
+
require 'mtk/patterns/function'
|
67
|
+
require 'mtk/patterns/lines'
|
68
|
+
require 'mtk/patterns/palindrome'
|
69
|
+
require 'mtk/patterns/chain'
|
70
|
+
require 'mtk/patterns/for_each'
|
71
|
+
|
72
|
+
require 'mtk/sequencers/event_builder'
|
73
|
+
require 'mtk/sequencers/sequencer'
|
74
|
+
require 'mtk/sequencers/step_sequencer'
|
75
|
+
require 'mtk/sequencers/rhythmic_sequencer'
|
76
|
+
require 'mtk/sequencers/legato_sequencer'
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module MTK
|
2
|
+
module Core
|
3
|
+
|
4
|
+
# A measure of time in musical beats.
|
5
|
+
# May be negative to indicate a rest, which uses the absolute value for the effective duration.
|
6
|
+
class Duration
|
7
|
+
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
# The names of the base durations. See {MTK::Lang::Durations} for more info.
|
11
|
+
NAMES = %w[w h q i s r x].freeze
|
12
|
+
|
13
|
+
VALUES_BY_NAME = {
|
14
|
+
'w' => 4,
|
15
|
+
'h' => 2,
|
16
|
+
'q' => 1,
|
17
|
+
'i' => Rational(1,2),
|
18
|
+
's' => Rational(1,4),
|
19
|
+
'r' => Rational(1,8),
|
20
|
+
'x' => Rational(1,16)
|
21
|
+
}
|
22
|
+
|
23
|
+
@flyweight = {}
|
24
|
+
|
25
|
+
# The number of beats, typically represented as a Rational
|
26
|
+
attr_reader :value
|
27
|
+
|
28
|
+
def initialize( length_in_beats )
|
29
|
+
@value = length_in_beats
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return a duration, only constructing a new instance when not already in the flyweight cache
|
33
|
+
def self.[](length_in_beats)
|
34
|
+
if length_in_beats.is_a? Fixnum
|
35
|
+
value = length_in_beats
|
36
|
+
else
|
37
|
+
value = Rational(length_in_beats)
|
38
|
+
end
|
39
|
+
@flyweight[value] ||= new(value)
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
alias :from_f :[]
|
44
|
+
alias :from_i :[]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Lookup a duration by name.
|
48
|
+
# This method supports appending any combination of '.' and 't' for more fine-grained values.
|
49
|
+
# each '.' multiplies by 3/2, and each 't' multiplies by 2/3.
|
50
|
+
# You may use the prefix '-' to negate the duration (which turns it into a rest of the same length).
|
51
|
+
# You may also prefix (after the '-' if present) the base duration name with an integer, float, or rational number
|
52
|
+
# to multiply the base duration value. Rationals are in the form "#!{numerator_integer}/#!{denominator_integer}".
|
53
|
+
# @example lookup value of 'q.', which is 1.5 times a quarter note (1.5 beats):
|
54
|
+
# MTK::Core::Duration.from_s('q.')
|
55
|
+
# @example lookup the value of 3/4w, which three-quarters of a whole note (3 beats):
|
56
|
+
# MTK::Core::Duration.from_s('3/4w')
|
57
|
+
def self.from_s(s)
|
58
|
+
if s =~ /^(-)?(\d+([\.\/]\d+)?)?([whqisrx])((\.|t)*)$/i
|
59
|
+
name = $4.downcase
|
60
|
+
modifier = $5.downcase
|
61
|
+
modifier << $1 if $1 # negation
|
62
|
+
multiplier = $2
|
63
|
+
else
|
64
|
+
raise ArgumentError.new("Invalid Duration string '#{s}'")
|
65
|
+
end
|
66
|
+
|
67
|
+
value = VALUES_BY_NAME[name]
|
68
|
+
modifier.each_char do |mod|
|
69
|
+
case mod
|
70
|
+
when '-' then value *= -1
|
71
|
+
when '.' then value *= Rational(3,2)
|
72
|
+
when 't' then value *= Rational(2,3)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if multiplier
|
77
|
+
case multiplier
|
78
|
+
when /\./
|
79
|
+
value *= multiplier.to_f
|
80
|
+
when /\//
|
81
|
+
numerator, denominator = multiplier.split('/')
|
82
|
+
value *= Rational(numerator.to_i, denominator.to_i)
|
83
|
+
else
|
84
|
+
value *= multiplier.to_i
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
self[value]
|
89
|
+
end
|
90
|
+
|
91
|
+
class << self
|
92
|
+
alias :from_name :from_s
|
93
|
+
end
|
94
|
+
|
95
|
+
# The magnitude (absolute value) of the duration.
|
96
|
+
# This is the actual duration for rests.
|
97
|
+
# @see #rest?
|
98
|
+
def length
|
99
|
+
@value < 0 ? -@value : @value
|
100
|
+
end
|
101
|
+
|
102
|
+
# Durations with negative values are rests.
|
103
|
+
# @see #length
|
104
|
+
# @see #-@
|
105
|
+
def rest?
|
106
|
+
@value < 0
|
107
|
+
end
|
108
|
+
|
109
|
+
# The number of beats as a floating point number
|
110
|
+
def to_f
|
111
|
+
@value.to_f
|
112
|
+
end
|
113
|
+
|
114
|
+
# The numerical value for the nearest whole number of beats
|
115
|
+
def to_i
|
116
|
+
@value.round
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_s
|
120
|
+
value = @value.to_s
|
121
|
+
value = sprintf '%.2f', @value if value.length > 6 # threshold is 6 for no particular reason...
|
122
|
+
"#{value} #{@value.abs > 1 || @value==0 ? 'beats' : 'beat'}"
|
123
|
+
end
|
124
|
+
|
125
|
+
def inspect
|
126
|
+
"#<#{self.class}:#{object_id} @value=#{@value}>"
|
127
|
+
end
|
128
|
+
|
129
|
+
def ==( other )
|
130
|
+
if other.is_a? MTK::Core::Duration
|
131
|
+
other.value == @value
|
132
|
+
else
|
133
|
+
other == @value
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def <=> other
|
138
|
+
if other.respond_to? :value
|
139
|
+
@value <=> other.value
|
140
|
+
else
|
141
|
+
@value <=> other
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Add this duration to another.
|
146
|
+
# @return a new Duration that has a value of the sum of the arguments.
|
147
|
+
def + duration
|
148
|
+
if duration.is_a? MTK::Core::Duration
|
149
|
+
MTK::Core::Duration[@value + duration.value]
|
150
|
+
else
|
151
|
+
MTK::Core::Duration[@value + duration]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Subtract another duration from this one.
|
156
|
+
# @return a new Duration that has a value of the difference of the arguments.
|
157
|
+
def - duration
|
158
|
+
if duration.is_a? MTK::Core::Duration
|
159
|
+
MTK::Core::Duration[@value - duration.value]
|
160
|
+
else
|
161
|
+
MTK::Core::Duration[@value - duration]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Multiply this duration with another.
|
166
|
+
# @return a new Duration that has a value of the product of the arguments.
|
167
|
+
def * duration
|
168
|
+
if duration.is_a? MTK::Core::Duration
|
169
|
+
MTK::Core::Duration[@value * duration.value]
|
170
|
+
else
|
171
|
+
MTK::Core::Duration[@value * duration]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Divide this duration with another.
|
176
|
+
# @return a new Duration that has a value of the division of the arguments.
|
177
|
+
def / duration
|
178
|
+
if duration.is_a? MTK::Core::Duration
|
179
|
+
MTK::Core::Duration[to_f / duration.value]
|
180
|
+
else
|
181
|
+
MTK::Core::Duration[to_f / duration]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Negate the duration value.
|
186
|
+
# Turns normal durations into rests and vice versa.
|
187
|
+
# @return a new Duration that has a negated value.
|
188
|
+
# @see #rest?
|
189
|
+
def -@
|
190
|
+
MTK::Core::Duration[@value * -1]
|
191
|
+
end
|
192
|
+
|
193
|
+
# Allow basic math operations with Numeric objects.
|
194
|
+
def coerce(other)
|
195
|
+
return MTK::Core::Duration[other], self
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Construct a {Duration} from any supported type
|
202
|
+
def Duration(*anything)
|
203
|
+
anything = anything.first if anything.length == 1
|
204
|
+
case anything
|
205
|
+
when Numeric then MTK::Core::Duration[anything]
|
206
|
+
when String, Symbol then MTK::Core::Duration.from_s(anything)
|
207
|
+
when Duration then anything
|
208
|
+
else raise "Duration doesn't understand #{anything.class}"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
module_function :Duration
|
212
|
+
|
213
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module MTK
|
2
|
+
module Core
|
3
|
+
|
4
|
+
# A measure of intensity, using an underlying value in the range 0.0-1.0
|
5
|
+
class Intensity
|
6
|
+
|
7
|
+
include Comparable
|
8
|
+
|
9
|
+
# The names of the base intensities. See {}MTK::Lang::Intensities} for more info.
|
10
|
+
NAMES = %w[ppp pp p mp mf o ff fff].freeze
|
11
|
+
|
12
|
+
VALUES_BY_NAME = {
|
13
|
+
'ppp' => 0.125,
|
14
|
+
'pp' => 0.25,
|
15
|
+
'p' => 0.375,
|
16
|
+
'mp' => 0.5,
|
17
|
+
'mf' => 0.625,
|
18
|
+
'o' => 0.75,
|
19
|
+
'ff' => 0.875,
|
20
|
+
'fff' => 1.0
|
21
|
+
}
|
22
|
+
|
23
|
+
@flyweight = {}
|
24
|
+
|
25
|
+
# The number of beats, typically representation as a Rational
|
26
|
+
attr_reader :value
|
27
|
+
|
28
|
+
def initialize(value)
|
29
|
+
@value = value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return an Intensity, only constructing a new instance when not already in the flyweight cache
|
33
|
+
def self.[](value)
|
34
|
+
value = value.to_f
|
35
|
+
@flyweight[value] ||= new(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
alias :from_f :[]
|
40
|
+
alias :from_i :[]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Lookup an intensity by name.
|
44
|
+
# This method supports appending '-' or '+' for more fine-grained values.
|
45
|
+
def self.from_s(s)
|
46
|
+
return self[1.0] if s == 'fff+' # special case because "fff" is already the maximum
|
47
|
+
|
48
|
+
name = nil
|
49
|
+
modifier = nil
|
50
|
+
if s =~ /^(\w+)([+-])?$/
|
51
|
+
name = $1
|
52
|
+
modifier = $2
|
53
|
+
end
|
54
|
+
|
55
|
+
value = VALUES_BY_NAME[name]
|
56
|
+
raise ArgumentError.new("Invalid Intensity string '#{s}'") unless value
|
57
|
+
|
58
|
+
value += 1.0/24 if modifier == '+'
|
59
|
+
value -= 1.0/24 if modifier == '-'
|
60
|
+
|
61
|
+
self[value]
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
alias :from_name :from_s
|
66
|
+
end
|
67
|
+
|
68
|
+
# The number of beats as a floating point number
|
69
|
+
def to_f
|
70
|
+
@value.to_f
|
71
|
+
end
|
72
|
+
|
73
|
+
# The numerical value for the nearest whole number of beats
|
74
|
+
def to_i
|
75
|
+
@value.round
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_midi
|
79
|
+
(to_f * 127).round
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_percent
|
83
|
+
(@value * 100).round
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
"#{to_percent}% intensity"
|
88
|
+
end
|
89
|
+
|
90
|
+
def inspect
|
91
|
+
"#<#{self.class}:#{object_id} @value=#{@value}>"
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==( other )
|
95
|
+
other.is_a? MTK::Core::Intensity and other.value == @value
|
96
|
+
end
|
97
|
+
|
98
|
+
def <=> other
|
99
|
+
if other.respond_to? :value
|
100
|
+
@value <=> other.value
|
101
|
+
else
|
102
|
+
@value <=> other
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def + intensity
|
108
|
+
if intensity.is_a? MTK::Core::Intensity
|
109
|
+
MTK::Core::Intensity[@value + intensity.value]
|
110
|
+
else
|
111
|
+
MTK::Core::Intensity[@value + intensity]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def -intensity
|
116
|
+
if intensity.is_a? MTK::Core::Intensity
|
117
|
+
MTK::Core::Intensity[@value - intensity.value]
|
118
|
+
else
|
119
|
+
MTK::Core::Intensity[@value - intensity]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def * intensity
|
124
|
+
if intensity.is_a? MTK::Core::Intensity
|
125
|
+
MTK::Core::Intensity[@value * intensity.value]
|
126
|
+
else
|
127
|
+
MTK::Core::Intensity[@value * intensity]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def / intensity
|
132
|
+
if intensity.is_a? MTK::Core::Intensity
|
133
|
+
MTK::Core::Intensity[to_f / intensity.value]
|
134
|
+
else
|
135
|
+
MTK::Core::Intensity[to_f / intensity]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def coerce(other)
|
140
|
+
return MTK::Core::Intensity[other], self
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Construct a {Duration} from any supported type
|
147
|
+
def Intensity(*anything)
|
148
|
+
anything = anything.first if anything.length == 1
|
149
|
+
case anything
|
150
|
+
when Numeric then MTK::Core::Intensity[anything]
|
151
|
+
when String, Symbol then MTK::Core::Intensity.from_s(anything)
|
152
|
+
when Intensity then anything
|
153
|
+
else raise "Intensity doesn't understand #{anything.class}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
module_function :Intensity
|
157
|
+
|
158
|
+
end
|