Module:MOS tunings: Difference between revisions
mNo edit summary |
ArrowHead294 (talk | contribs) mNo edit summary |
||
| (56 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | |||
local et = require("Module:ET") | |||
local jira = require("Module:JI ratios") | |||
local mos = require("Module:MOS") | local mos = require("Module:MOS") | ||
local tamnams = require("Module:TAMNAMS") | local tamnams = require("Module:TAMNAMS") | ||
local | local tip = require("Module:Template input parse") | ||
local yesno = require("Module:Yesno") | local yesno = require("Module:Yesno") | ||
-- Rewritten/simplified module replacement for Module:MOS degrees | -- Rewritten/simplified module replacement for Module:MOS degrees | ||
| Line 12: | Line 13: | ||
-- TODO: | -- TODO: | ||
-- - | -- - Relegate JI ratio input to sorting entered ratios; this is to decouple | ||
-- ratio search from ratio sorting/filtering. | |||
-- - Diatonic interval category lookup? | -- - Diatonic interval category lookup? | ||
| Line 63: | Line 65: | ||
and step_ratios[2][1] == 2 and step_ratios[2][2] == 1 | and step_ratios[2][1] == 2 and step_ratios[2][2] == 1 | ||
and step_ratios[3][1] == 3 and step_ratios[3][2] == 1 then | and step_ratios[3][1] == 3 and step_ratios[3][2] == 1 then | ||
return "Simple Tunings", {{2,1}, {3,1}, {3,2}} | return "Simple Tunings", {{2, 1}, {3, 1}, {3, 2}} | ||
end | end | ||
end | end | ||
| Line 95: | Line 97: | ||
-- Preprocess step ratios | -- Preprocess step ratios | ||
function p.preprocess_ji_ratios(input_mos, modal_union, step_ratios, ji_ratios) | function p.preprocess_ji_ratios(input_mos, modal_union, step_ratios, ji_ratios, tolerance) | ||
-- Calculate the avegrage step ratio | -- Calculate the avegrage step ratio | ||
| Line 119: | Line 121: | ||
-- normalized to x:1.) | -- normalized to x:1.) | ||
-- Tolerance is how many cents away from an et-step a ratio can be. This is | -- Tolerance is how many cents away from an et-step a ratio can be. This is | ||
-- 30% of the small step size, and maxes out at 30 | -- by default 30% of the small step size, and maxes out at 30 cent. Can be | ||
-- overridden with a custom tolerance value. | |||
local steps_in_et = input_mos.nL * avg_step_ratio[1] + input_mos.ns * avg_step_ratio[2] | local steps_in_et = input_mos.nL * avg_step_ratio[1] + input_mos.ns * avg_step_ratio[2] | ||
local tolerance = math.min((mos.equave_to_cents(input_mos) / steps_in_et) * 0.30, 30) | local tolerance = tolerance or math.min((mos.equave_to_cents(input_mos) / steps_in_et) * 0.30, 30) | ||
-- Calculate the cent values for each interval in the modal union | -- Calculate the cent values for each interval in the modal union | ||
| Line 135: | Line 138: | ||
-- Main function | -- Main function | ||
function p._mos_tunings(input_mos, mos_prefix, mos_abbrev, step_ratios, ji_ratios) | function p._mos_tunings(input_mos, mos_prefix, mos_abbrev, step_ratios, ji_ratios, tolerance, footnotes, is_collapsed) | ||
local input_mos = input_mos or mos.new(5,2) | local input_mos = input_mos or mos.new(5,2) | ||
local mos_prefix = mos_prefix or "mos" | local mos_prefix = mos_prefix or "mos" | ||
local mos_abbrev = mos_abbrev or "m" | local mos_abbrev = mos_abbrev or "m" | ||
local step_ratios = step_ratios or {{2,1}, {3,1}, {3,2}} | local step_ratios = step_ratios or {{2, 1}, {3, 1}, {3, 2}} | ||
local ji_ratios = ji_ratios or {} | local ji_ratios = ji_ratios or {} | ||
local tolerance = tolerance or nil | |||
local is_collapsed = is_collapsed == true | |||
local footnotes = footnotes or "(footnotes here)" | |||
-- Scalesig | -- Scalesig | ||
| Line 151: | Line 157: | ||
-- Preprocess JI ratios | -- Preprocess JI ratios | ||
local modal_union = mos.modal_union(input_mos) | local modal_union = mos.modal_union(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, tolerance) | ||
-- Create table | -- Create table | ||
local result = "{| class=\"wikitable sortable right-all left-1 left-2\"\n" | local result = "{| class=\"wikitable sortable right-all left-1 left-2 mw-collapsible" .. (is_collapsed and " mw-collapsed\"\n" or "\"\n") | ||
-- Table caption | -- Table caption | ||
result = result .. | result = result .. "|+ style=\"font-size: 105%; white-space: nowrap;\" | " .. string.format("%s of %s\n", step_ratio_range, scale_sig) | ||
.. "|-\n" | |||
-- First row of headers | -- First row of headers | ||
-- First two headers span two rows | -- First two headers span two rows | ||
result = result .. "! rowspan=\"2\" class=\"unsortable\" | Scale degree\n" | result = result | ||
.. "! rowspan=\"2\" class=\"unsortable\" | Scale degree\n" | |||
.. "! rowspan=\"2\" class=\"unsortable\" | Abbrev.\n" | |||
-- Headers for tunings; these span two cols | -- Headers for tunings; these span two cols | ||
| Line 173: | Line 181: | ||
end | end | ||
local et_as_string = et.as_string(mos. | local et_as_string = et.as_string(mos.as_et(input_mos, step_ratios[i])) | ||
local header_text = string.format("%s<br>[[%s]]", step_ratio_as_text, et_as_string) | local header_text = string.format("%s<br />[[%s]]", step_ratio_as_text, et_as_string) | ||
result = result .. string.format("! colspan=\"2\" | %s\n", header_text) | result = result .. string.format("! colspan=\"2\" | %s\n", header_text) | ||
end | end | ||
-- Headers for JI ratios; this spans two rows | -- Headers for JI ratios; this spans two rows | ||
-- Commented out, pending rewrite | |||
--[[ | |||
if #ji_ratios ~= 0 then | if #ji_ratios ~= 0 then | ||
result = result .. "! rowspan=\"2\" class=\"unsortable\" | Approx. | result = result .. "! rowspan=\"2\" class=\"unsortable\" | Approx. ratios*\n" | ||
end | end | ||
]]-- | |||
result = result .. "|-\n" | result = result .. "|-\n" | ||
-- Second row of headers | -- Second row of headers | ||
for i = 1, #step_ratios do | for i = 1, #step_ratios do | ||
result = result .. "! Steps\n" | result = result .. "! style=\"border-right: none;\" class=\"unsortable\" | Steps\n" | ||
result = result .. "! | result = result .. "! style=\"border-left: none; text-align: right;\" | ¢\n" | ||
end | end | ||
| Line 200: | Line 211: | ||
result = result | result = result | ||
.. "|-\n" | .. "|-\n" | ||
.. string.format("| %s | .. string.format("| %s\n", degree_name) | ||
.. string.format("| %s\n", degree_abbrev) | |||
-- Add cells for each interval's tunings | -- Add cells for each interval's tunings | ||
| Line 209: | Line 221: | ||
result = result | result = result | ||
.. " " | --.. string.format("\n| %s\\%s\n| %.1f", step_count, input_mos.nL * step_ratio[1] + input_mos.ns * step_ratio[2], cents) | ||
.. string.format("|| %s\\%s | .. string.format("| style=\"border-right: none;\" | %s\\%s\n", step_count, input_mos.nL * step_ratio[1] + input_mos.ns * step_ratio[2]) | ||
.. string.format("| style=\"border-left: none;\" | %.1f\n", cents) | |||
end | end | ||
-- Add cells for JI ratios | -- Add cells for JI ratios | ||
--[[ | |||
-- Commented out, pending rewrite | |||
if #ji_ratios ~= 0 then | if #ji_ratios ~= 0 then | ||
-- Ratios link to their respective pages, and are comma-delimited. | -- Ratios link to their respective pages, and are comma-delimited. | ||
local ratios_as_text = jira. | local ratios_as_text = jira.ratios_as_string(sorted_ji_ratios[i], true, ", ") | ||
result = result .. | result = result .. "| style=\"text-align: left;\" | " .. string.format("%s\n", ratios_as_text) | ||
end | end | ||
]]-- | |||
end | end | ||
-- End of table | -- End of table, plus footnotes | ||
result = result .. "|}" | result = result .. "|}" | ||
--[[ | |||
-- Commented out, pending rewrite | |||
if #ji_ratios ~= 0 then | |||
-- Make footnote text smaller than the rest of the text to avoid confusion with paragraph text | |||
result = result .. string.format("<span style=\"font-size: 0.75em;\">* %s</span>", footnotes) | |||
end | |||
]]-- | |||
return result | return result | ||
| Line 237: | Line 259: | ||
function p.parse_step_ratios(unparsed) | function p.parse_step_ratios(unparsed) | ||
local parsed = {} | local parsed = {} | ||
local lookup_table = { | |||
["Central Spectrum"] = {{4, 3}, {3, 2}, {5, 3}, {2, 1}, {5, 2}, {3, 1}, {4, 1}}, | |||
["Simple Tunings"] = {{2, 1}, {3, 1}, {3, 2}}, | |||
["Soft-of-basic"] = {{4, 3}, {3, 2}, {2, 1}}, | |||
["Ultrasoft"] = {{6, 5}, {5, 4}, {4, 3}}, | |||
["Parasoft"] = {{4, 3}, {7, 5}, {3, 2}}, | |||
["Quasisoft"] = {{3, 2}, {8, 5}, {5, 3}}, | |||
["Minisoft"] = {{5, 3}, {7, 4}, {2, 1}}, | |||
["Hyposoft"] = {{3, 2}, {5, 3}, {2, 1}}, | |||
["Hypohard"] = {{2, 1}, {5, 2}, {3, 1}}, | |||
["Minihard"] = {{2, 1}, {7, 3}, {5, 2}}, | |||
["Quasihard"] = {{5, 2}, {8, 3}, {3, 1}}, | |||
["Parahard"] = {{3, 1}, {7, 2}, {4, 1}}, | |||
["Ultrahard"] = {{4, 1}, {5, 1}, {6, 1}}, | |||
["Hard-of-basic"] = {{2, 1}, {3, 1}, {4, 1}}, | |||
} | |||
if unparsed == "" then | |||
parsed = lookup_table["Simple Tunings"] | |||
elseif unparsed == "NONE" then | elseif unparsed == "NONE" then | ||
parsed = {} | parsed = {} | ||
else | else | ||
parsed = tip.parse_numeric_pairs(unparsed) | parsed = lookup_table[unparsed] or tip.parse_numeric_pairs(unparsed) | ||
end | end | ||
return parsed | return parsed | ||
| Line 260: | Line 290: | ||
-- If the unparsed string corresponds to a list of JI ratios ("a/b; c/d; e/f"), | -- If the unparsed string corresponds to a list of JI ratios ("a/b; c/d; e/f"), | ||
-- then parse it as a list of ratios. If it's not that, parse it as search | -- then parse it as a list of ratios. If it's not that, parse it as search | ||
-- | -- args. If the text is "NONE", then there should be no ratios passed in. | ||
-- If the unparsed string is an empty string, return nil. (This is so the | -- If the unparsed string is an empty string, return nil. (This is so the | ||
-- wrapper function can go by default search | -- wrapper function can go by default search args.) | ||
function p.parse_ji_ratios(unparsed, | function p.parse_ji_ratios(unparsed, equave) | ||
local ratios = nil | local ratios = nil | ||
local | local search_args = nil | ||
if unparsed == "" then | if unparsed == "" then | ||
search_args = {["Int Limit"] = 50, ["Tenney Height"] = 8; ["Complements Only"] = true} -- Defualt search args if no args were passed in | |||
ratios = jira. | ratios = jira.search_by_args_within_equave(equave, search_args) | ||
elseif unparsed == "NONE" then | elseif unparsed == "NONE" then | ||
search_args = {} | |||
ratios = {} | ratios = {} | ||
elseif string.match(unparsed, "Int Limit:") then | elseif string.match(unparsed, "Int Limit:") then | ||
search_args = jira.parse_search_args(unparsed) -- Search requires at the absolute least an int limit, so see if there's "Int Limit" | |||
ratios = jira. | ratios = jira.search_by_args_within_equave(equave, search_args) | ||
else | else | ||
search_args = {} | |||
ratios = jira.parse_ratios(unparsed) | ratios = jira.parse_ratios(unparsed) | ||
end | end | ||
return ratios, | return ratios, jira.search_footnotes(search_args) | ||
end | end | ||
| Line 286: | Line 317: | ||
function p.mos_tunings(frame) | function p.mos_tunings(frame) | ||
-- Get params | -- Get params | ||
local scalesig | local scalesig = frame.args["Scale Signature"] | ||
local input_mos = mos.parse(scalesig) | local input_mos = mos.parse(scalesig) | ||
local | local mos_prefix = tamnams.verify_prefix(input_mos, frame.args["MOS Prefix"]) | ||
local mos_abbrev = tamnams.verify_abbrev(input_mos, frame.args["MOS Abbrev"]) | |||
local is_collapsed = yesno(frame.args["Collapsed"], false) | |||
local step_ratios = p.parse_step_ratios(frame.args["Step Ratios"]) | |||
local tolerance = tonumber(frame.args["Tolerance"]) | |||
local debugg = yesno(frame.args["debug"]) | |||
local | --local ji_ratios, footnotes = p.parse_ji_ratios(frame.args["JI Ratios"], input_mos.equave) | ||
local | |||
local result = p._mos_tunings(input_mos, mos_prefix, mos_abbrev, step_ratios, ji_ratios, tolerance, footnotes, is_collapsed) | |||
if debugg == true then | |||
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" | |||
end | |||
return frame:preprocess(result) | |||
return | |||
end | end | ||
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 input_mos = mos.parse("9L 4s<7/2>") | local input_mos = mos.parse("9L 4s<7/2>") | ||