Class: MTK::Core::Duration
- Inherits:
-
Object
- Object
- MTK::Core::Duration
- Includes:
- Comparable
- Defined in:
- lib/mtk/core/duration.rb
Overview
A measure of time in musical beats. May be negative to indicate a rest, which uses the absolute value for the effective duration.
Constant Summary collapse
- NAMES =
The names of the base durations. See Lang::Durations for more info.
%w[w h q e s r x].freeze
- VALUES_BY_NAME =
{ 'w' => 4, 'h' => 2, 'q' => 1, 'e' => Rational(1,2), 's' => Rational(1,4), 'r' => Rational(1,8), 'x' => Rational(1,16) }
Instance Attribute Summary collapse
-
#value ⇒ Object
readonly
The number of beats, typically represented as a Rational.
Class Method Summary collapse
-
.[](length_in_beats) ⇒ Object
(also: from_f, from_i)
Return a duration, only constructing a new instance when not already in the flyweight cache.
-
.from_s(s) ⇒ Object
(also: from_name)
Lookup a duration by name.
Instance Method Summary collapse
-
#*(duration) ⇒ Object
Multiply this duration with another.
-
#+(duration) ⇒ Object
Add this duration to another.
-
#-(duration) ⇒ Object
Subtract another duration from this one.
-
#-@ ⇒ Object
Negate the duration value.
-
#/(duration) ⇒ Object
Divide this duration with another.
- #<=>(other) ⇒ Object
- #==(other) ⇒ Object
-
#abs ⇒ Object
Force resets to be non-rests, otherwise don’t change the duration.
-
#coerce(other) ⇒ Object
Allow basic math operations with Numeric objects.
-
#initialize(length_in_beats) ⇒ Duration
constructor
A new instance of Duration.
- #inspect ⇒ Object
-
#length ⇒ Object
The magnitude (absolute value) of the duration.
-
#rest? ⇒ Boolean
Durations with negative values are rests.
-
#to_f ⇒ Object
The number of beats as a floating point number.
-
#to_i ⇒ Object
The numerical value for the nearest whole number of beats.
- #to_s ⇒ Object
Constructor Details
#initialize(length_in_beats) ⇒ Duration
Returns a new instance of Duration.
30 31 32 |
# File 'lib/mtk/core/duration.rb', line 30 def initialize( length_in_beats ) @value = length_in_beats end |
Instance Attribute Details
#value ⇒ Object (readonly)
The number of beats, typically represented as a Rational
28 29 30 |
# File 'lib/mtk/core/duration.rb', line 28 def value @value end |
Class Method Details
.[](length_in_beats) ⇒ Object Also known as: from_f, from_i
Return a duration, only constructing a new instance when not already in the flyweight cache
35 36 37 38 39 40 41 42 |
# File 'lib/mtk/core/duration.rb', line 35 def self.[](length_in_beats) if length_in_beats.is_a? Fixnum value = length_in_beats else value = Rational(length_in_beats) end @flyweight[value] ||= new(value) end |
.from_s(s) ⇒ Object Also known as: from_name
Lookup a duration by name. This method supports appending any combination of ‘.’ and ‘t’ for more fine-grained values. each ‘.’ multiplies by 3/2, and each ‘t’ multiplies by 2/3. You may use the prefix ‘-’ to negate the duration (which turns it into a rest of the same length). You may also prefix (after the ‘-’ if present) the base duration name with an integer, float, or rational number to multiply the base duration value. Rationals are in the form “#{numerator_integer}/#{denominator_integer}”.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/mtk/core/duration.rb', line 59 def self.from_s(s) if s =~ /^(-)?(\d+([\.\/]\d+)?)?([whqesrx])((\.|t)*)$/i name = $4.downcase modifier = $5.downcase modifier << $1 if $1 # negation multiplier = $2 else raise ArgumentError.new("Invalid Duration string '#{s}'") end value = VALUES_BY_NAME[name] modifier.each_char do |mod| case mod when '-' then value *= -1 when '.' then value *= Rational(3,2) when 't' then value *= Rational(2,3) end end if multiplier case multiplier when /\./ value *= multiplier.to_f when /\// numerator, denominator = multiplier.split('/') value *= Rational(numerator.to_i, denominator.to_i) else value *= multiplier.to_i end end self[value] end |
Instance Method Details
#*(duration) ⇒ Object
Multiply this duration with another.
182 183 184 185 186 187 188 |
# File 'lib/mtk/core/duration.rb', line 182 def * duration if duration.is_a? MTK::Core::Duration MTK::Core::Duration[@value * duration.value] else MTK::Core::Duration[@value * duration] end end |
#+(duration) ⇒ Object
Add this duration to another.
162 163 164 165 166 167 168 |
# File 'lib/mtk/core/duration.rb', line 162 def + duration if duration.is_a? MTK::Core::Duration MTK::Core::Duration[@value + duration.value] else MTK::Core::Duration[@value + duration] end end |
#-(duration) ⇒ Object
Subtract another duration from this one.
172 173 174 175 176 177 178 |
# File 'lib/mtk/core/duration.rb', line 172 def - duration if duration.is_a? MTK::Core::Duration MTK::Core::Duration[@value - duration.value] else MTK::Core::Duration[@value - duration] end end |
#-@ ⇒ Object
Negate the duration value. Turns normal durations into rests and vice versa.
204 205 206 |
# File 'lib/mtk/core/duration.rb', line 204 def -@ MTK::Core::Duration[@value * -1] end |
#/(duration) ⇒ Object
Divide this duration with another.
192 193 194 195 196 197 198 |
# File 'lib/mtk/core/duration.rb', line 192 def / duration if duration.is_a? MTK::Core::Duration MTK::Core::Duration[to_f / duration.value] else MTK::Core::Duration[to_f / duration] end end |
#<=>(other) ⇒ Object
152 153 154 155 156 157 158 |
# File 'lib/mtk/core/duration.rb', line 152 def <=> other if other.respond_to? :value @value <=> other.value else @value <=> other end end |
#==(other) ⇒ Object
144 145 146 147 148 149 150 |
# File 'lib/mtk/core/duration.rb', line 144 def ==( other ) if other.is_a? MTK::Core::Duration other.value == @value else other == @value end end |
#abs ⇒ Object
Force resets to be non-rests, otherwise don’t change the duration.
116 117 118 119 120 121 122 |
# File 'lib/mtk/core/duration.rb', line 116 def abs if @value < 0 -self else self end end |
#coerce(other) ⇒ Object
Allow basic math operations with Numeric objects.
209 210 211 |
# File 'lib/mtk/core/duration.rb', line 209 def coerce(other) return MTK::Core::Duration[other], self end |
#inspect ⇒ Object
140 141 142 |
# File 'lib/mtk/core/duration.rb', line 140 def inspect "#<#{self.class}:#{object_id} @value=#{@value}>" end |
#length ⇒ Object
The magnitude (absolute value) of the duration. This is the actual duration for rests.
101 102 103 |
# File 'lib/mtk/core/duration.rb', line 101 def length @value < 0 ? -@value : @value end |
#rest? ⇒ Boolean
Durations with negative values are rests.
108 109 110 |
# File 'lib/mtk/core/duration.rb', line 108 def rest? @value < 0 end |
#to_f ⇒ Object
The number of beats as a floating point number
125 126 127 |
# File 'lib/mtk/core/duration.rb', line 125 def to_f @value.to_f end |
#to_i ⇒ Object
The numerical value for the nearest whole number of beats
130 131 132 |
# File 'lib/mtk/core/duration.rb', line 130 def to_i @value.round end |
#to_s ⇒ Object
134 135 136 137 138 |
# File 'lib/mtk/core/duration.rb', line 134 def to_s value = @value.to_s value = sprintf '%.2f', @value if value.length > 6 # threshold is 6 for no particular reason... "#{value} #{@value.abs > 1 || @value==0 ? 'beats' : 'beat'}" end |