Module:JI ratios in ED: Difference between revisions

Ganaram inukshuk (talk | contribs)
Denominator limit -> integer limit; tolerance will max out at +/- 40 cents
Ganaram inukshuk (talk | contribs)
Cleanup code
Line 24: Line 24:


-- Helper function
-- Helper function
-- Converts a set of primes into a subgroup
-- Converts a set of primes (typically a prime subgroup) into text
function p.primes_as_subgroup(primes)
function p.subgroup_as_text(primes)
local primes = primes or { 2, 3, 5, 7 }
local primes = primes or { 2, 3, 5, 7 }
Line 40: Line 40:


-- Helper function
-- Helper function
-- Given a set of primes, find its temperament interpretation; IE, is it a
-- Creates the non-header cells in the table
-- prime subgroup temperament (EG, 2.3.7) or a prime-limit temperament (EG,
function p.ji_ratio_in_ed_content_cells(steps, equave, candidate_ratios, primes)
-- 7-limit)?
local steps = steps or 12
-- If the set of primes is a prime limit, then it should contain all the primes
local equave = equave or rat.new(2)
-- between 2 (inclusive) and the largest prime (inclusive). If it skips any
local candidate_ratios = candidate_ratios or { rat.new(1), rat.new(2), rat.new(3, 2), rat.new(4, 3), rat.new (5, 4), rat.new (9, 7)}
-- primes, then it's a subgroup.
local primes = primes or { 2, 3, 7 }
function p.primes_as_temperament_interpretation(primes)
local primes = primes or { 2, 3, 5, 7 }
-- Calculate equave and tolerance
local primes_to_compare = p.primes_within_prime_limit(primes[#primes])
-- Tolerance is +/- 40 cents or 40% of a step, whichever is smaller.
local equave_in_cents = rat.cents(equave)
local tolerance = math.min(equave_in_cents / steps * 0.4, 40)
local temperament_interpretation = ""
-- Build the rows for each step, showing ratios by limit
if p.primes_as_subgroup(primes) == p.primes_as_subgroup(primes_to_compare) then
local result = ""
temperament_interpretation = string.format("%d-limit", primes[#primes])
for i = 1, steps + 1 do
else
local step = i - 1
temperament_interpretation = p.primes_as_subgroup(primes) .. " subgroup"
-- Table headers
local step_in_cents = (step / steps) * rat.cents(equave)
result = result .. string.format('| %d\n', step)
result = result .. string.format('| %.3f\n', step_in_cents)
-- Filter ratios by whether they're within the current step
local filtered_ratios = jiraf.filter_ratios_by_range(candidate_ratios, step_in_cents - tolerance, step_in_cents + tolerance)
-- Add ratios according to harmonic class
for j = 1, #primes do
local current_prime = primes[j]
-- For each prime, filter by harmonic class
-- For the first column, filter by prime limit instead
local prime_filtered_ratios = {}
if j == 1 then
prime_filtered_ratios = jiraf.filter_ratios_by_prime_limit(filtered_ratios, primes[j])
else
prime_filtered_ratios = jiraf.filter_ratios_by_harmonic_class(filtered_ratios, primes[j])
end
 
local ratios_as_text = jiraf.ratios_to_text_with_error(prime_filtered_ratios, step_in_cents, "<br>", true)
result = result .. string.format('| %s\n', ratios_as_text)
end
result = result .. string.format('|-\n')
end
end
return result
return temperament_interpretation
end
end


-- Primary function
-- Main function variant for prime limit
function p.find_ratios_in_ed(input_et, primes, tenney_height, int_limit)
function p.ji_ratios_in_ed_by_prime_limit(input_et, int_limit, prime_limit, tenney_height)
local input_et = input_et or et.parse("12ed5/2")
local input_et = input_et or et.parse("12edo")
local primes = primes or { 2, 3, 5, 7 }
local prime_limit = 7
local tenney_height = tenney_height or 10
local tenney_height = tenney_height or 10
local int_limit = int_limit or 99
local int_limit = int_limit or 99
Line 79: Line 106:
local equave_in_cents = rat.cents(equave)
local equave_in_cents = rat.cents(equave)
local tolerance = math.min(equave_in_cents / steps * 0.4, 40)
local tolerance = math.min(equave_in_cents / steps * 0.4, 40)
-- Calculate candidate ratios
-- Then filter based on whether their complements exceed the int limit
-- Then filter candidate ratios by tenney height (excludes equave factors)
local candidate_ratios = jiraf.find_candidate_ratios_within_prime_limit(equave_in_cents, int_limit, prime_limit)
candidate_ratios = jiraf.filter_ratios_by_equave_complement_int_limit(candidate_ratios, int_limit, equave)
candidate_ratios = jiraf.filter_ratios_by_no_equave_factors_tenney_height(candidate_ratios, tenney_height, equave)
-- Calculate temperament interpretation
-- Get the primes
local temperament_interpretation = p.primes_as_temperament_interpretation(primes)
local primes = p.primes_within_prime_limit(prime_limit)
-- Find candidate ratios; filter later
local max_prime = primes[#primes]
local candidate_ratios = jiraf.find_candidate_ratios_within_subgroup(equave_in_cents, int_limit, primes)
-- Build table headers
-- Build table headers
local result = string.format('{| class="wikitable center-all"\n')
local result = string.format('{| class="wikitable center-all"\n')
result = result .. string.format('|+ Intervals of %s (as a %s temperament)\n', et_as_string, temperament_interpretation)
result = result .. string.format('|+ Intervals of %s (as a %d-limit temperament)\n', et_as_string, prime_limit)
result = result .. string.format('|-\n')
result = result .. string.format('|-\n')
result = result .. string.format('! rowspan="2" | [[Degree]]\n')
result = result .. string.format('! rowspan="2" | [[Degree]]\n')
Line 96: Line 126:
result = result .. string.format('|-\n')
result = result .. string.format('|-\n')
-- Add table headers for prime limits (technically harmonic classes)
-- Add rest of table
for i = 1, #primes do
result = result .. p.ji_ratio_in_ed_content_cells(steps, equave, candidate_ratios, primes)
local current_prime = primes[i]
result = result .. string.format('! [[%d-limit]]\n', current_prime)
result = result .. string.format('|}\n')
return result
end
 
-- Main function variant for prime subgroup
function p.ji_ratios_in_ed_by_prime_subgroup(input_et, int_limit, primes, tenney_height)
local input_et = input_et or et.parse("12edo")
local primes = primes or { 2, 3, 5, 11 }
local tenney_height = tenney_height or 10
local int_limit = int_limit or 99
-- Get the number of divisions, equave, and et as text (eg edo, edt, etc)
local steps = input_et['size']
local equave = input_et['equave']
if tonumber(equave) ~= nil then
equave = rat.new(equave)
end
end
local et_as_string = et.as_string(input_et)
-- Calculate equave and tolerance
-- Tolerance is +/- 40 cents or 40% of a step, whichever is smaller.
local equave_in_cents = rat.cents(equave)
local tolerance = math.min(equave_in_cents / steps * 0.4, 40)
-- Calculate candidate ratios
-- Then filter based on whether their complements exceed the int limit
-- Then filter candidate ratios by tenney height (excludes equave factors)
local candidate_ratios = jiraf.find_candidate_ratios_within_subgroup(equave_in_cents, int_limit, primes)
candidate_ratios = jiraf.filter_ratios_by_equave_complement_int_limit(candidate_ratios, int_limit, equave)
candidate_ratios = jiraf.filter_ratios_by_no_equave_factors_tenney_height(candidate_ratios, tenney_height, equave)
-- Get subgroup as text
local subgroup_as_text = p.subgroup_as_text(primes)
-- Build table headers
local result = string.format('{| class="wikitable center-all"\n')
result = result .. string.format('|+ Intervals of %s (as a %s subgroup temperament)\n', et_as_string, subgroup_as_text)
result = result .. string.format('|-\n')
result = result .. string.format('! rowspan="2" | [[Degree]]\n')
result = result .. string.format('! rowspan="2" | [[Cent]]s\n')
result = result .. string.format('! colspan="%d" | Approximated [[JI]] intervals ([[error]] in cents)\n', #primes)
result = result .. string.format('|-\n')
result = result .. string.format('|-\n')
-- Build the rows for each step, showing ratios by limit
-- Add rest of table
for i = 1, steps + 1 do
result = result .. p.ji_ratio_in_ed_content_cells(steps, equave, candidate_ratios, primes)
local step = i - 1
-- Table headers
local step_in_cents = (step / steps) * rat.cents(equave)
result = result .. string.format('| %d\n', step)
result = result .. string.format('| %.3f\n', step_in_cents)
filtered_ratios = jiraf.filter_ratios_by_range(candidate_ratios, step_in_cents - tolerance, step_in_cents + tolerance)
-- Add ratios according to harmonic class
for j = 1, #primes do
local current_prime = primes[j]
local prime_filtered_ratios = {}
-- Override filtered ratios denpending on whether the ratio is the
-- unison or equave
if step == 0 and j == 1 then
prime_filtered_ratios = { rat.new(1) }
elseif step == 0 and j ~= 1 then
prime_filtered_ratios = {}
elseif step == steps then
prime_filtered_ratios = jiraf.filter_ratios_by_harmonic_class({ equave }, current_prime)
else
-- Filter ratios by harmonic class, then whether the ratios'
-- equave complement exceeds the int limit, then by
-- no-equave-factors tenney height (nefth).
prime_filtered_ratios = jiraf.filter_ratios_by_harmonic_class(filtered_ratios, current_prime)
prime_filtered_ratios = jiraf.filter_ratios_by_equave_complement_int_limit(prime_filtered_ratios, int_limit, equave)
prime_filtered_ratios = jiraf.filter_ratios_by_no_equave_factors_tenney_height(prime_filtered_ratios, tenney_height, equave)
end
-- Add ratios to cells
-- TODO: make first column go by prime limit (this way, the unison
-- is not excluded), with successive columns by harmonic class.
local ratios_as_text = jiraf.ratios_to_text_with_error(prime_filtered_ratios, step_in_cents, "<br>", true)
result = result .. string.format('| %s\n', ratios_as_text)
end
result = result .. string.format('|-\n')
end
result = result .. string.format('|}\n')
result = result .. string.format('|}\n')
Line 159: Line 188:
end
end
local input_et = et.parse(input_et_unparsed)
local input_et = et.parse(input_et_unparsed)
local tenney_height = tonumber(frame.args["Tenney Height"]) or 10
local int_limit = tonumber(frame.args["Integer Limit"]) or 99


local primes = { 2, 3, 5, 7 }
local primes = nil
local temperament_type = ""
if string.len(frame.args["Subgroup"]) > 0 then  
if string.len(frame.args["Subgroup"]) > 0 then  
primes = tip.parse_numeric_entries(frame.args["Subgroup"], '.') or tip.parse_numeric_entries(frame.args["Subgroup"], ',')
primes = tip.parse_numeric_entries(frame.args["Subgroup"], '.') or tip.parse_numeric_entries(frame.args["Subgroup"], ',')
temperament_type = "Subgroup"
end
end
if string.len(frame.args["Prime Limit"]) > 0 and string.len(frame.args["Subgroup"]) == 0 then
if string.len(frame.args["Prime Limit"]) > 0 and string.len(frame.args["Subgroup"]) == 0 then
primes = p.primes_within_prime_limit(tonumber(frame.args["Prime Limit"]))
primes = tonumber(frame.args["Prime Limit"])
temperament_type = "Prime Limit"
end
end
local tenney_height = tonumber(frame.args["Tenney Height"]) or 10
local result = ""
local int_limit = tonumber(frame.args["Integer Limit"]) or 99
if temperament_type == "Subgroup" then
result = p.find_ratios_in_ed_by_subgroup(input_et, primes, tenney_height, int_limit)
local result = p.find_ratios_in_ed(input_et, primes, tenney_height, int_limit)
elseif temperament_type == "Prime Limit" then
result = p.find_ratios_in_ed_by_subgroup(input_et, primes, tenney_height, int_limit)
end
return result
return result