Class: Tonal::Ratio::Approximation
- Inherits:
-
Object
- Object
- Tonal::Ratio::Approximation
- Extended by:
- Forwardable
- Defined in:
- lib/tonal/approximation.rb
Defined Under Namespace
Classes: Set
Constant Summary collapse
- DEFAULT_MIN_PRIME =
2- DEFAULT_MAX_PRIME =
Float::INFINITY
- DEFAULT_MAX_GRID_SCALE =
100- DEFAULT_MAX_GRID_BOUNDARY =
5- DEFAULT_DEPTH =
Float::INFINITY
- DEFAULT_TREE_PATH_DEPTH =
10- DEFAULT_SUPERPART_DEPTH =
20- DEFAULT_NEIGHBORHOOD_DEPTH =
10- DEFAULT_COMPLEXITY_AMOUNT =
50.0- CONVERGENT_LIMIT =
10
Instance Attribute Summary collapse
-
#ratio ⇒ Object
readonly
Returns the value of attribute ratio.
Class Method Summary collapse
-
.neighbors(vacinity:, away: 1) ⇒ Array
An array of Tonal::Ratio neighbors in the scaled ratio's grid neighborhood.
Instance Method Summary collapse
-
#by_continued_fraction(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, conv_limit: CONVERGENT_LIMIT) ⇒ Tonal::Ratio::Approximation::Set
Of ratios within cent tolerance of self found using continued fraction approximation.
-
#by_neighborhood(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_NEIGHBORHOOD_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, max_boundary: DEFAULT_MAX_GRID_BOUNDARY, max_scale: DEFAULT_MAX_GRID_SCALE) ⇒ Array
Of ratios within cent tolerance of self found on the ratio grid.
-
#by_superparticular(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_SUPERPART_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, superpart: :upper) ⇒ Tonal::Ratio::Approximation::Set
Of superparticular approximations within cent tolerance of self.
-
#by_tree_path(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_TREE_PATH_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME) ⇒ Tonal::Ratio::Approximation::Set
Of fraction tree ratios within cent tolerance of self.
-
#initialize(ratio:) ⇒ Approximation
constructor
A new instance of Approximation.
-
#neighborhood(scale: 2**0, boundary: 1) ⇒ Array
Of bounding ratios in the ratio grid vacinity of antecedent/consequent scaled by scale.
Constructor Details
#initialize(ratio:) ⇒ Approximation
Returns a new instance of Approximation.
19 20 21 22 |
# File 'lib/tonal/approximation.rb', line 19 def initialize(ratio:) raise ArgumentError, "Tonal::Ratio required" unless ratio.kind_of?(Tonal::Ratio) @ratio = ratio end |
Instance Attribute Details
#ratio ⇒ Object (readonly)
Returns the value of attribute ratio.
17 18 19 |
# File 'lib/tonal/approximation.rb', line 17 def ratio @ratio end |
Class Method Details
.neighbors(vacinity:, away: 1) ⇒ Array
Returns an array of Tonal::Ratio neighbors in the scaled ratio's grid neighborhood.
167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/tonal/approximation.rb', line 167 def self.neighbors(vacinity:, away: 1) [vacinity, vacinity.class.new(vacinity.antecedent+away, vacinity.consequent), vacinity.class.new(vacinity.antecedent-away, vacinity.consequent), vacinity.class.new(vacinity.antecedent, vacinity.consequent+away), vacinity.class.new(vacinity.antecedent, vacinity.consequent-away), vacinity.class.new(vacinity.antecedent+away, vacinity.consequent+away), vacinity.class.new(vacinity.antecedent+away, vacinity.consequent-away), vacinity.class.new(vacinity.antecedent-away, vacinity.consequent+away), vacinity.class.new(vacinity.antecedent-away, vacinity.consequent-away)] end |
Instance Method Details
#by_continued_fraction(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, conv_limit: CONVERGENT_LIMIT) ⇒ Tonal::Ratio::Approximation::Set
Returns of ratios within cent tolerance of self found using continued fraction approximation.
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/tonal/approximation.rb', line 34 def by_continued_fraction(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, conv_limit: CONVERGENT_LIMIT) return Set.new(ratio: ratio){|ratios| ratios << ratio} if (antecedent == 1) && (consequent == 1) self_in_cents = to_cents within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance) Set.new(ratio: ratio) do |ratios| ContinuedFraction.new(antecedent.to_f/consequent, conv_limit).convergents.each do |convergent| ratio2 = ratio.class.new(convergent.numerator,convergent.denominator) ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && max_prime_at_most?(ratio2, max_prime) && !prime_factor_at_most?(ratio2, min_prime - 1) break if ratios.length >= depth end end end |
#by_neighborhood(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_NEIGHBORHOOD_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, max_boundary: DEFAULT_MAX_GRID_BOUNDARY, max_scale: DEFAULT_MAX_GRID_SCALE) ⇒ Array
Returns of ratios within cent tolerance of self found on the ratio grid.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/tonal/approximation.rb', line 107 def by_neighborhood(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_NEIGHBORHOOD_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, max_boundary: DEFAULT_MAX_GRID_BOUNDARY, max_scale: DEFAULT_MAX_GRID_SCALE) self_in_cents = to_cents within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance) Set.new(ratio: ratio) do |ratios| scale = 1 boundary = 1 while ratios.length <= depth && scale <= max_scale do while boundary <= max_boundary vacinity = ratio.respond_to?(:to_basic_ratio) ? to_basic_ratio.scale(scale) : ratio.scale(scale) self.class.neighbors(away: boundary, vacinity: vacinity).each do |neighbor| ratios << neighbor if (neighbor != ratio) && ratio.class.within_cents?(self_in_cents, neighbor.to_cents, within) && max_prime_at_most?(neighbor, max_prime) && !prime_factor_at_most?(neighbor, min_prime - 1) end boundary += 1 end boundary = 1 scale += 1 end end end |
#by_superparticular(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_SUPERPART_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, superpart: :upper) ⇒ Tonal::Ratio::Approximation::Set
Returns of superparticular approximations within cent tolerance of self.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/tonal/approximation.rb', line 80 def by_superparticular(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_SUPERPART_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME, superpart: :upper) # One of n and n+1 is even, so every candidate has 2 as a factor and none can meet a higher min_prime return Set.new(ratio: ratio) if min_prime > 2 self_in_cents = to_cents within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance) Set.new(ratio: ratio) do |ratios| n = 1 while true do ratio2 = ratio.class.superparticular(n, factor: ratio.to_r, superpart:) ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && (ratio2 != ratio) && max_prime_at_most?(ratio2, max_prime) && !prime_factor_at_most?(ratio2, min_prime - 1) break if ratios.length >= depth n += 1 end end end |
#by_tree_path(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_TREE_PATH_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME) ⇒ Tonal::Ratio::Approximation::Set
Returns of fraction tree ratios within cent tolerance of self.
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/tonal/approximation.rb', line 56 def by_tree_path(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_TREE_PATH_DEPTH, max_prime: DEFAULT_MAX_PRIME, min_prime: DEFAULT_MIN_PRIME) return Set.new(ratio: ratio){|ratios| ratios << ratio} if (antecedent == 1) && (consequent == 1) self_in_cents = to_cents within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance) Set.new(ratio: ratio) do |ratios| FractionTree.node(to_f).path.each do |node| next if node.number.infinite? ratio2 = ratio.class.new(node.number) ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && max_prime_at_most?(ratio2, max_prime) && !prime_factor_at_most?(ratio2, min_prime - 1) break if ratios.length >= depth end end end |
#neighborhood(scale: 2**0, boundary: 1) ⇒ Array
Returns of bounding ratios in the ratio grid vacinity of antecedent/consequent scaled by scale.
135 136 137 138 139 140 141 142 143 |
# File 'lib/tonal/approximation.rb', line 135 def neighborhood(scale: 2**0, boundary: 1) scale = scale.round vacinity = ratio.respond_to?(:to_basic_ratio) ? to_basic_ratio.scale(scale) : ratio.scale(scale) SortedSet.new([].tap do |ratio_list| 1.upto(boundary) do |away| ratio_list << self.class.neighbors(away: away, vacinity: vacinity) end end.flatten).to_a end |