tonal-tools 4.0.1 → 5.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/commas.yml +1 -1
- data/lib/tonal/approximation.rb +37 -25
- data/lib/tonal/attributions.rb +1 -1
- data/lib/tonal/cents.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc49345ed34f38eed1600818c0b28910a5525a22c8388338c5739650339c9ec1
|
4
|
+
data.tar.gz: a63830d52d1ed45aa575c6ee2d924c547a74260697853680928fbc0a586d1cfb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8111bb7846cc0dc220742313c253f6d719d31213ac05c35443eb4dc27058ec236b6bd13b946ad6870ca38b5e48f853385532bc2513f8897c3e5df10c3be3afed
|
7
|
+
data.tar.gz: cb3b394f94d175c127b874bba207fc4933e49a91197c48822ea8968578ec57d0dd42730b19eb2a7d6a57eebf44b77615d8b84094d2b3419f88d30b5ae34f1e03
|
data/data/commas.yml
CHANGED
data/lib/tonal/approximation.rb
CHANGED
@@ -4,6 +4,9 @@ class Tonal::Ratio
|
|
4
4
|
DEFAULT_MAX_GRID_SCALE = 100
|
5
5
|
DEFAULT_MAX_GRID_BOUNDARY = 5
|
6
6
|
DEFAULT_DEPTH = Float::INFINITY
|
7
|
+
DEFAULT_FRACTION_TREE_DEPTH = 10
|
8
|
+
DEFAULT_SUPERPART_DEPTH = 20
|
9
|
+
DEFAULT_NEIGHBORHOOD_DEPTH = 10
|
7
10
|
DEFAULT_COMPLEXITY_AMOUNT = 50.0
|
8
11
|
CONVERGENT_LIMIT = 10
|
9
12
|
|
@@ -20,7 +23,7 @@ class Tonal::Ratio
|
|
20
23
|
# @return [Tonal::Ratio::Approximation::Set] of ratios within cent tolerance of self found using continued fraction approximation
|
21
24
|
# @example
|
22
25
|
# Tonal::Ratio.ed(12,1).approximate.by_continued_fraction
|
23
|
-
# => (4771397596969315/4503599627370496): [(
|
26
|
+
# => (4771397596969315/4503599627370496): [(17/16), (18/17), (89/84), (196/185), (1461/1379), (1657/1564), (3118/2943), (7893/7450), (18904/17843)]
|
24
27
|
# @param cents_tolerance the cents tolerance used to scope the collection
|
25
28
|
# @param depth the maximum number of ratios in the collection
|
26
29
|
# @param max_prime the maximum prime number to allow in the collection
|
@@ -29,11 +32,11 @@ class Tonal::Ratio
|
|
29
32
|
def by_continued_fraction(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_DEPTH, max_prime: DEFAULT_MAX_PRIME, conv_limit: CONVERGENT_LIMIT)
|
30
33
|
self_in_cents = to_cents
|
31
34
|
within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance)
|
32
|
-
Set.new(ratio: ratio)
|
35
|
+
Set.new(ratio: ratio) do |ratios|
|
33
36
|
ContinuedFraction.new(antecedent.to_f/consequent, conv_limit).convergents.each do |convergent|
|
34
37
|
ratio2 = ratio.class.new(convergent.numerator,convergent.denominator)
|
35
|
-
|
36
|
-
break if
|
38
|
+
ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && ratio2.within_prime?(max_prime)
|
39
|
+
break if ratios.length >= depth
|
37
40
|
end
|
38
41
|
end
|
39
42
|
end
|
@@ -41,21 +44,21 @@ class Tonal::Ratio
|
|
41
44
|
# @return [Tonal::Ratio::Approximation::Set] of ratios within cent tolerance of self found using a quotient walk on the fraction tree
|
42
45
|
# @example
|
43
46
|
# Tonal::Ratio.ed(12,1).approximate.by_quotient_walk(max_prime: 89)
|
44
|
-
# => (4771397596969315/4503599627370496): [(
|
47
|
+
# => (4771397596969315/4503599627370496): [(17/16), (18/17), (35/33), (53/50), (71/67), (89/84), (196/185)]
|
45
48
|
# @param cents_tolerance the cents tolerance used to scope the collection
|
46
49
|
# @param depth the maximum number of ratios in the collection
|
47
50
|
# @param max_prime the maximum prime number to allow in the collection
|
48
51
|
# @param conv_limit the number of convergents to limit the ContinuedFraction method
|
49
52
|
#
|
50
|
-
def by_quotient_walk(cents_tolerance: Tonal::Cents::TOLERANCE, depth:
|
53
|
+
def by_quotient_walk(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_FRACTION_TREE_DEPTH, max_prime: DEFAULT_MAX_PRIME, conv_limit: CONVERGENT_LIMIT)
|
51
54
|
self_in_cents = to_cents
|
52
55
|
within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance)
|
53
56
|
|
54
|
-
Set.new(ratio: ratio)
|
57
|
+
Set.new(ratio: ratio) do |ratios|
|
55
58
|
FractionTree.quotient_walk(to_f, limit: conv_limit).each do |node|
|
56
59
|
ratio2 = ratio.class.new(node.weight)
|
57
|
-
|
58
|
-
break if
|
60
|
+
ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && ratio2.within_prime?(max_prime)
|
61
|
+
break if ratios.length >= depth
|
59
62
|
end
|
60
63
|
end
|
61
64
|
end
|
@@ -63,19 +66,19 @@ class Tonal::Ratio
|
|
63
66
|
# @return [Tonal::Ratio::Approximation::Set] of fraction tree ratios within cent tolerance of self
|
64
67
|
# @example
|
65
68
|
# Tonal::Ratio.ed(12,1).approximate.by_tree_path(max_prime: 17)
|
66
|
-
# => (4771397596969315/4503599627370496): [(
|
69
|
+
# => (4771397596969315/4503599627370496): [(17/16), (18/17), (35/33)]
|
67
70
|
# @param cents_tolerance the cents tolerance used to scope the collection
|
68
71
|
# @param depth the maximum number of ratios in the collection
|
69
72
|
# @param max_prime the maximum prime number to allow in the collection
|
70
73
|
#
|
71
|
-
def by_tree_path(cents_tolerance: Tonal::Cents::TOLERANCE, depth:
|
74
|
+
def by_tree_path(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_FRACTION_TREE_DEPTH, max_prime: DEFAULT_MAX_PRIME)
|
72
75
|
self_in_cents = to_cents
|
73
76
|
within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance)
|
74
|
-
Set.new(ratio: ratio)
|
77
|
+
Set.new(ratio: ratio) do |ratios|
|
75
78
|
FractionTree.path_to(to_f).each do |node|
|
76
79
|
ratio2 = ratio.class.new(node.weight)
|
77
|
-
|
78
|
-
break if
|
80
|
+
ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && ratio2.within_prime?(max_prime)
|
81
|
+
break if ratios.length >= depth
|
79
82
|
end
|
80
83
|
end
|
81
84
|
end
|
@@ -83,21 +86,21 @@ class Tonal::Ratio
|
|
83
86
|
# @return [Tonal::Ratio::Approximation::Set] of superparticular approximations within cent tolerance of self
|
84
87
|
# @example
|
85
88
|
# Tonal::Ratio.new(3/2r).approximate.by_superparticular
|
86
|
-
# => (3/2): [(
|
89
|
+
# => (3/2): [(1041/692), (1044/694), (1047/696), (1050/698), (1053/700), (1056/702), (1059/704), (1062/706), (1065/708), (1068/710), (1071/712), (1074/714), (1077/716), (1080/718), (1083/720), (1086/722), (1089/724), (1092/726), (1095/728), (1098/730)]
|
87
90
|
# @param cents_tolerance the cents tolerance used to scope the collection
|
88
91
|
# @param depth the maximum number of ratios in the collection
|
89
92
|
# @param max_prime the maximum prime number to allow in the collection
|
90
93
|
# @param superpart if the superior part is the numerator or denominator
|
91
94
|
#
|
92
|
-
def by_superparticular(cents_tolerance: Tonal::Cents::TOLERANCE, depth:
|
95
|
+
def by_superparticular(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_SUPERPART_DEPTH, max_prime: DEFAULT_MAX_PRIME, superpart: :upper)
|
93
96
|
self_in_cents = to_cents
|
94
97
|
within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance)
|
95
|
-
Set.new(ratio: ratio)
|
98
|
+
Set.new(ratio: ratio) do |ratios|
|
96
99
|
n = 1
|
97
100
|
while true do
|
98
101
|
ratio2 = ratio.class.superparticular(n, factor: ratio.to_r, superpart:)
|
99
|
-
|
100
|
-
break if
|
102
|
+
ratios << ratio2 if ratio.class.within_cents?(self_in_cents, ratio2.to_cents, within) && ratio2.within_prime?(max_prime) && ratio2 != ratio
|
103
|
+
break if ratios.length >= depth
|
101
104
|
n += 1
|
102
105
|
end
|
103
106
|
end
|
@@ -113,18 +116,18 @@ class Tonal::Ratio
|
|
113
116
|
# @param max_boundary the maximum distance grid ratios will be from the scaled ratio
|
114
117
|
# @param max_scale the maximum self will be scaled
|
115
118
|
#
|
116
|
-
def by_neighborhood(cents_tolerance: Tonal::Cents::TOLERANCE, depth:
|
119
|
+
def by_neighborhood(cents_tolerance: Tonal::Cents::TOLERANCE, depth: DEFAULT_NEIGHBORHOOD_DEPTH, max_prime: DEFAULT_MAX_PRIME, max_boundary: DEFAULT_MAX_GRID_BOUNDARY, max_scale: DEFAULT_MAX_GRID_SCALE)
|
117
120
|
self_in_cents = to_cents
|
118
121
|
within = cents_tolerance.kind_of?(Tonal::Cents) ? cents_tolerance : Tonal::Cents.new(cents: cents_tolerance)
|
119
|
-
Set.new(ratio: ratio)
|
122
|
+
Set.new(ratio: ratio) do |ratios|
|
120
123
|
scale = 1
|
121
124
|
boundary = 1
|
122
125
|
|
123
|
-
while
|
126
|
+
while ratios.length <= depth && scale <= max_scale do
|
124
127
|
while boundary <= max_boundary
|
125
128
|
vacinity = ratio.respond_to?(:to_basic_ratio) ? to_basic_ratio.scale(scale) : ratio.scale(scale)
|
126
129
|
self.class.neighbors(away: boundary, vacinity: vacinity).each do |neighbor|
|
127
|
-
|
130
|
+
ratios << neighbor if ratio.class.within_cents?(self_in_cents, neighbor.to_cents, within) && neighbor.within_prime?(max_prime) && neighbor != ratio
|
128
131
|
end
|
129
132
|
boundary += 1
|
130
133
|
end
|
@@ -171,19 +174,28 @@ class Tonal::Ratio
|
|
171
174
|
|
172
175
|
class Set
|
173
176
|
extend Forwardable
|
174
|
-
def_delegators :@ratios, :count, :length, :min, :max, :entries, :all?, :any?, :reject, :map
|
177
|
+
def_delegators :@ratios, :count, :length, :min, :max, :entries, :all?, :any?, :reject, :map, :find_index
|
175
178
|
|
176
179
|
attr_reader :ratios, :ratio
|
177
180
|
|
178
181
|
def initialize(ratio:)
|
179
182
|
@ratio = ratio
|
180
|
-
@ratios =
|
183
|
+
@ratios = ::Set.new
|
184
|
+
yield @ratios if block_given?
|
181
185
|
end
|
182
186
|
alias :approximations :entries
|
183
187
|
|
184
188
|
def inspect
|
185
189
|
"#{ratio}: #{entries}"
|
186
190
|
end
|
191
|
+
|
192
|
+
def sort_by(&)
|
193
|
+
self.class.new(ratio: ratio) do |ratios|
|
194
|
+
entries.sort_by(&).each do |ratio|
|
195
|
+
ratios << ratio
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
187
199
|
end
|
188
200
|
end
|
189
201
|
end
|
data/lib/tonal/attributions.rb
CHANGED
data/lib/tonal/cents.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tonal-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jose Hales-Garcia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yaml
|