Module:MOS tunings: Difference between revisions

Ganaram inukshuk (talk | contribs)
m comments
Ganaram inukshuk (talk | contribs)
Adopt ji-ratios template
Line 5: Line 5:
local yesno = require("Module:Yesno")
local yesno = require("Module:Yesno")
local tip = require("Module:Template input parse")
local tip = require("Module:Template input parse")
local jira = require("Module:JI ratios")
local utils = require("Module:Utils")
local utils = require("Module:Utils")
local p = {}
local p = {}
Line 14: Line 15:
-- TODO:
-- TODO:
-- - Add option to enter a custom set of ratios; requires sorting
-- - Add option to enter a custom set of ratios; requires sorting
-- - Add option to refine JI ratio search (EG, prime limit, Tenney height, subgroup, etc...)
-- - Add option to omit JI col altogether
-- - Add option to omit JI col altogether
-- - Diatonic interval category lookup?
-- - Diatonic interval category lookup?
Line 50: Line 50:
end
end
return step_ratios
return step_ratios
end
-- Find JI ratios up to an integer limit via mediants
function p.ji_ratio_search(integer_limit, max_cents)
local SEARCH_MAX = 120
local max_cents = max_cents or 1200
local integer_limit = integer_limit or SEARCH_MAX
integer_limit = math.max(0, math.min(SEARCH_MAX, integer_limit))
local ratios = {{1,1}, {2,1}}
-- Find ratios by finding the mediants between existing ratios, only adding
-- those that do not exceed the integer limit.
local new_ratios_added = true
while new_ratios_added do
new_ratios_added = false
local new_ratios = {}
for i = 1, #ratios-1 do
local ratio_1 = ratios[i]
local ratio_2 = ratios[i+1]
local mediant = {ratio_1[1]+ratio_2[1], ratio_1[2]+ratio_2[2]}
local int_max = math.max(mediant[1], mediant[2])
table.insert(new_ratios, ratios[i])
if int_max <= integer_limit then
new_ratios_added = true
table.insert(new_ratios, mediant)
end
end
table.insert(new_ratios, ratios[#ratios])
ratios = new_ratios
end
-- If the max cents is greater than the octave, duplicate all existing
-- ratios and raise them by the required number of octaves.
if max_cents > 1200 then
local new_ratios = {}
local num_octaves_up = math.ceil(max_cents / 1200)
for j = 1, num_octaves_up do
for i = 2, #ratios do
local num = ratios[i][1] * math.pow(2, j)
local den = ratios[i][2]
local gcd = utils._gcd(num, den)
num = num / gcd
den = den / gcd
if math.max(num, den) <= integer_limit then
table.insert(new_ratios, {num, den})
end
end
end
for i = 1, #new_ratios do
table.insert(ratios, new_ratios[i])
end
end
-- Remove any ratios that exceed the max cents
-- Convert to ratios that Module:Rational can work with
return ratios
end
end


Line 189: Line 123:
end
end
-- Sort ratios by closeness to each degree in the modal union
local sorted_ratios = jira.sort_by_closeness_to_cent_values(ji_ratios, cent_values, tolerance)
local sorted_ratios = {}
local curr_index = 1 -- Index of current_ratio
for i = 1, #cent_values do
local lower_bound = cent_values[i] - tolerance
local upper_bound = cent_values[i] + tolerance
local cents_within_range = true
local curr_ratios = {}
for j = curr_index, #ji_ratios do
local curr_ratio = ji_ratios[j]
local curr_cents = math.log(curr_ratio[1]/curr_ratio[2])/math.log(2) * 1200
if lower_bound < curr_cents and curr_cents < upper_bound then
table.insert(curr_ratios, curr_ratio)
--elseif curr_cents > upper_bound then
-- curr_index = j
-- break
end
end
table.insert(sorted_ratios, curr_ratios)
end
return sorted_ratios, string.format("Ratios within %.2f of the averaged scale degrees are shown.", tolerance)
return sorted_ratios, string.format("Ratios within %.1f of the averaged scale degrees are shown.", tolerance)
end
end


Line 232: Line 144:
-- Preprocess JI ratios
-- Preprocess JI ratios
local equave_in_cents = mos.equave_to_cents(input_mos)
local equave_in_cents = mos.equave_to_cents(input_mos)
local ji_ratios = ji_ratios or p.ji_ratio_search(30, equave_in_cents)
local ji_ratios = ji_ratios or jira.search_by_int_limit(32, mos.equave_to_cents(input_mos))
local sorted_ji_ratios, search_info = p.preprocess_ji_ratios(input_mos, modal_union, step_ratios, ji_ratios)
local sorted_ji_ratios, search_info = p.preprocess_ji_ratios(input_mos, modal_union, step_ratios, ji_ratios)
Line 294: Line 206:
-- Add cells for JI ratios
-- Add cells for JI ratios
-- TESTING: print only the unison and equave
local ratios_as_text = jira.ratios_as_text(sorted_ji_ratios[i])
local ratios = ""
result = result .. string.format("|| %s", ratios_as_text)
for j = 1, #sorted_ji_ratios[i] do
if j ~= #sorted_ji_ratios[i] then
ratios = ratios .. string.format("%s/%s, ", sorted_ji_ratios[i][j][1], sorted_ji_ratios[i][j][2])
else
ratios = ratios .. string.format("%s/%s", sorted_ji_ratios[i][j][1], sorted_ji_ratios[i][j][2])
end
end
result = result .. string.format("|| %s", ratios)
result = result .. "\n"
result = result .. "\n"
Line 336: Line 240:
function p.tester()
function p.tester()
local range, ratios = p.preprocess_step_ratios({ {7,1}, {3,1}, {2,1} })
local range, ratios = p.preprocess_step_ratios({ {7,1}, {3,1}, {2,1} })
local ji_ratios = p.ji_ratio_search(30, 2400)
local input_mos = mos.parse("9L 4s<7/2>")
local input_mos = mos.parse("9L 4s<7/2>")
return p.preprocess_ji_ratios(input_mos, mos.modal_union(input_mos), {{2,1}, {3,2}, {5,3}}, ji_ratios)
--return p.preprocess_ji_ratios(input_mos, mos.modal_union(input_mos), {{2,1}, {3,2}, {5,3}}, ji_ratios)
--return ji_ratios
--return ji_ratios
--return p._mos_tunings(input_mos)
return p._mos_tunings(input_mos)
end
end


return p
return p