Class: Tonal::Cents

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Comparable
Defined in:
lib/tonal/cents.rb

Constant Summary collapse

HUNDREDTHS_ROUNDOFF =
-2
FLOAT_PRECISION =
100
CENT_SCALE =
1200.0
TOLERANCE =
5
PRECISION =
2

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cents: nil, log: nil, ratio: nil, precision: PRECISION) ⇒ Tonal::Cents

Examples:

Tonal::Cents.new(ratio: 2**(2.0/12)) => 200.0

Parameters:

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/tonal/cents.rb', line 24

def initialize(cents: nil, log: nil, ratio: nil, precision: PRECISION)
  raise ArgumentError, "One of cents:, log: or ratio: must be provided" unless [cents, log, ratio].compact.count == 1

  @precision = precision

  if cents
    @log = derive_log(cents: cents)
    @value = derive_cents(cents: cents)
    @ratio = derive_ratio(log: @log)
  elsif log
    @log = derive_log(log: log)
    @value = derive_cents(log: @log)
    @ratio = derive_ratio(log: @log)
  elsif ratio
    @log = derive_log(ratio: ratio)
    @value = derive_cents(log: @log)
    @ratio = derive_ratio(ratio: ratio)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(op, *args, &blk) ⇒ Object (private)

All these operators are binary except for |, ~ and typeof , so the left hand (A) object would be the context object, and the right hand object (B) would be the argument passed to the operator member in A. For unary operators, there won’t be arguments, and the function would be called upon its target. operator functions would only be called if the operator is explicitly used in the source code.



171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/tonal/cents.rb', line 171

def method_missing(op, *args, &blk)
  rhs = args.collect do |arg|
    arg.kind_of?(self.class) ? arg.value : arg
  end
  result = value.send(op, *rhs)
  return result if op == :coerce
  case result
  when Numeric
    self.class.new(cents: result)
  else
    result
  end
end

Instance Attribute Details

#logObject (readonly)

Returns the value of attribute log.



14
15
16
# File 'lib/tonal/cents.rb', line 14

def log
  @log
end

#ratioObject (readonly)

Returns the value of attribute ratio.



14
15
16
# File 'lib/tonal/cents.rb', line 14

def ratio
  @ratio
end

Class Method Details

.default_toleranceTonal::Cents

Returns the default cents tolerance.

Examples:

Tonal::Cents.default_tolerance => 5

Returns:



50
51
52
# File 'lib/tonal/cents.rb', line 50

def self.default_tolerance
  self.new(cents: TOLERANCE)
end

Instance Method Details

#*(rhs) ⇒ Tonal::Cents, Numeric

Returns result of operation.

Examples:

Tonal::Cents.new(cents: 200) * 2 => 400.0

Parameters:

Returns:



126
127
128
# File 'lib/tonal/cents.rb', line 126

def *(rhs)
  method_missing(:*, rhs)
end

#+(rhs) ⇒ Tonal::Cents, Numeric

Returns result of operation.

Examples:

Tonal::Cents.new(cents: 100) + Tonal::Cents.new(cents: 200) => 300.0

Parameters:

Returns:



117
118
119
# File 'lib/tonal/cents.rb', line 117

def +(rhs)
  method_missing(:+, rhs)
end

#-(rhs) ⇒ Tonal::Cents, Numeric

Operator overloads

Examples:

Tonal::Cents.new(cents: 200) - Tonal::Cents.new(cents: 100) => 100.0

Parameters:

Returns:



108
109
110
# File 'lib/tonal/cents.rb', line 108

def -(rhs)
  method_missing(:-, rhs)
end

#/(rhs) ⇒ Tonal::Cents, Numeric

Returns result of operation.

Examples:

Tonal::Cents.new(cents: 400) / 2 => 200.0

Parameters:

Returns:



135
136
137
# File 'lib/tonal/cents.rb', line 135

def /(rhs)
  method_missing(:/, rhs)
end

#<=>(rhs) ⇒ Object



143
144
145
# File 'lib/tonal/cents.rb', line 143

def <=>(rhs)
  rhs.kind_of?(self.class) ? value.round(PRECISION) <=> rhs.value.round(PRECISION) : value.round(PRECISION) <=> rhs.round(PRECISION)
end

#inspectObject Also known as: to_s

Returns [String] the string representation of Tonal::Cents.

Examples:

Tonal::Cents.new(100.0).inspect => "100.0"

Returns:

  • String

    the string representation of Tonal::Cents



96
97
98
# File 'lib/tonal/cents.rb', line 96

def inspect
  "#{value.round(@precision)}"
end

#nearest_hundredthObject

Returns [Tonal::Cents] nearest hundredth cent value.

Examples:

Tonal::Cents.new(cents: 701.9550008653874).nearest_hundredth => 700.0

Returns:

  • Tonal::Cents

    nearest hundredth cent value



69
70
71
# File 'lib/tonal/cents.rb', line 69

def nearest_hundredth
  self.class.new(cents: value.round(Tonal::Cents::HUNDREDTHS_ROUNDOFF).to_f)
end

#nearest_hundredth_differenceObject

Returns [Tonal::Cents] nearest hundredth cent difference.

Examples:

Tonal::Cents.new(cents: 701.9550008653874).nearest_hundredth_difference => 1.96

Returns:

  • Tonal::Cents

    nearest hundredth cent difference



78
79
80
# File 'lib/tonal/cents.rb', line 78

def nearest_hundredth_difference
  self.class.new(cents: (value - nearest_hundredth))
end

#plus_minus(limit = 5) ⇒ Array

Returns a tuple of self offset positively/negatively by limit.

Examples:

Tonal::Cents.new(cents: 100.0).plus_minus
=> [95.0, 105.0]

Returns:

  • (Array)

    a tuple of self offset positively/negatively by limit



87
88
89
# File 'lib/tonal/cents.rb', line 87

def plus_minus(limit = 5)
  [self - limit, self + limit]
end

#value(precision: @precision) ⇒ Float Also known as: cents, to_f

Returns value of self.

Examples:

Tonal::Cents.new(ratio: 2**(1.0/12)).value => 100.00

Returns:

  • (Float)

    value of self



58
59
60
# File 'lib/tonal/cents.rb', line 58

def value(precision: @precision)
  @value.round(precision)
end