Module:Scale tree: Difference between revisions

Ganaram inukshuk (talk | contribs)
Scale tree automatically adds "(Generators smaller than this are proper)" to appropriate mosses
Ganaram inukshuk (talk | contribs)
All values now round to 3 decimal points no matter what; fixed issue with dark gen of a multi-period mos being reported as the equave complement, not the period complement; rearranged code
Line 51: Line 51:
end
end


function p.scale_tree(frame)
-- Rewrite of scale tree function (has bugfixes and new formatting)
local mos = MOS.parse(frame.args["tuning"])
function p._scale_tree(input_mos, depth, comments)
local equave = mos.equave
local input_mos = input_mos or MOS.new(5, 2)
local L = mos.nL
local depth = depth or 5
local s = mos.ns
local comments = comments or {}
local n = utils._gcd(L, s)
local collapsed_et = ET.new(L, equave)
local equave = input_mos.equave
local abstract_bright_gen = MOS.bright_gen(mos)
local L = input_mos.nL -- Large steps in mos
local collapsed_bright_steps = abstract_bright_gen["L"]
local s = input_mos.ns -- Small steps in mos
local equalized_et = ET.new(L + s, equave)
local n = utils._gcd(L, s) -- Number of periods
local equalized_bright_steps = abstract_bright_gen["L"] + abstract_bright_gen["s"]
local abstract_bright_gen = MOS.bright_gen(input_mos)
local result = ""
 
local depth = frame.args["depth"] or 5
local step_ratios = sb.sb_tree_ratios(depth)
local step_ratios = sb.sb_tree_ratios(depth)
-- Default comments; these correspond to the TAMNAMS-named step ratios
-- Default comments for TAMNAMS-named step ratios
local default_comments = {}
local default_comments = {}
default_comments["1/1"] = "Equalized " .. MOS.as_string(mos)
default_comments["1/1"] = "Equalized " .. MOS.as_string(mos)
Line 79: Line 77:
default_comments["1/0"] = "Collapsed " .. MOS.as_string(mos)
default_comments["1/0"] = "Collapsed " .. MOS.as_string(mos)
-- Default comment for L:s = 2:1 has an extra line: "(Generators smaller than this are proper)"
-- Create table
-- This comment should not be added to the following mosses:
local result = ""
-- - Mosses of the form xL 1s, as they are always proper
-- - Mosses of the form nxL ns, as mosses of the true form are always proper
if s ~= n then
default_comments["2/1"] = default_comments["2/1"] .. "<br>(Generators smaller than this are proper)"
end
-- Get comments
-- Comments are entered as a pair consisting of a step ratio and comment, separated by a colon
-- p/q: comment text as a string, and [[links]] can be added too
-- Each entry is then entered as a semicolon-delimtied list
local comments_unparsed = frame.args["Comments"] or ""
local comments = p.parse_kv_pairs(comments_unparsed) or {}
-- Table headers
-- Table headers
Line 102: Line 88:
result = '{| class="wikitable"\n'
result = '{| class="wikitable"\n'
result = result .. '|+\n'
result = result .. '|+\n'
result = result .. '! rowspan="2" |Steps of ED\n'
result = result .. '! rowspan="2" | Generator (in steps)\n'
result = result .. '! colspan="2" |Generator in cents\n'
result = result .. '! colspan="2" | Generator in cents\n'
result = result .. '! colspan="2" |Step ratio\n'
result = result .. '! rowspan="2" | Step ratio (hardness)\n'
result = result .. '! rowspan="2" |Comments\n'
result = result .. '! rowspan="2" | Comments\n'
result = result .. '|-\n'
result = result .. '|-\n'
result = result .. '!Bright\n'
result = result .. '! Bright generator\n'
result = result .. '!Dark\n'
result = result .. '! Dark generator\n'
result = result .. '!L:s\n'
 
result = result .. '!Hardness\n'
-- Rounding is done using string.format, to 3 decimal places (%.3f)
-- Table rows
-- Create each row of the table
local i = 1
for i = 1, #step_ratios do
while i <= #step_ratios do
local step_ratio = step_ratios[i]
local step_ratio = step_ratios[i]
local et = ET.new(step_ratio[1] * L + step_ratio[2] * s, equave)
local steps_per_equave = step_ratio[1] * L + step_ratio[2] * s
local generator_steps = step_ratio[1] * collapsed_bright_steps + step_ratio[2] * (equalized_bright_steps - collapsed_bright_steps)
local steps_per_period = steps_per_equave / n
local et = ET.new(steps_per_equave, equave)
-- Calculate the bright gen and cent value
local bright_generator_steps = step_ratio[1] * abstract_bright_gen['L'] + step_ratio[2] * abstract_bright_gen['s']
local bright_generator_cents = ET.cents(et, bright_generator_steps)
-- Calculate dark generator step count and cent value
-- Calculate dark generator step count and cent value
local dark_generator_steps = step_ratio[1] * L + step_ratio[2] * s - generator_steps
local dark_generator_steps = steps_per_period - bright_generator_steps
local dark_generator_cents = ET.cents(et, dark_generator_steps)
local dark_generator_cents = ET.cents(et, dark_generator_steps)
-- Entry of comments is done using an associative array, as entries may be sparse
-- New row
-- If a default comment exists, it goes first and the custom comment is added on a newline in the cell itself
result = result .. "|-\n"
-- Old code commented out
--local comments = frame.args[("comment_" .. step_ratio[1] .. "_" .. step_ratio[2])] or ""
-- Cell for bright generator, as steps in et
result = result .. string.format("| [[%s|%d%s]]\n", ET.as_string(et), bright_generator_steps, ET.backslash_modifier(et))
-- Cells for generators in cents
result = result .. string.format("| %.3f\n", bright_generator_cents)
result = result .. string.format("| %.3f\n", dark_generator_cents)
-- Cell for step ratio, with divide-by-zero check
local hardness = -1
if step_ratio[2] == 0 then
hardness = "→ ∞"
else
hardness = string.format("%.3f", step_ratio[1] / step_ratio[2])
end
local step_ratio_as_string = string.format("%d:%d", step_ratio[1], step_ratio[2])
result = result .. string.format("| %s (%s)\n", step_ratio_as_string, hardness)
-- Cell for comment
local key = step_ratios[i][1] .. "/" .. step_ratios[i][2] -- The step ratio is (literally and figuratively) the key to add comments!
local key = step_ratios[i][1] .. "/" .. step_ratios[i][2] -- The step ratio is (literally and figuratively) the key to add comments!
local comment = ""
local contains_default_comment = default_comments[key] ~= nil
-- Check for comments
local contains_custom_comment = comments[key] ~= nil
local contains_custom_comment = comments[key] ~= nil
if contains_default_comment and contains_custom_comment then
if contains_default_comment and contains_custom_comment then
Line 139: Line 146:
end
end
local l_s = "&rarr; ∞"
local comment = comments[key] or ""
if not (step_ratio[1] == 1 and step_ratio[2] == 0)  then
result = result .. string.format("| %s\n", comment)
l_s =  u._round_dec(step_ratio[1] / step_ratio[2], 3)
end
-- Row's cells
result = result .. "|-\n"
-- Steps in ET
result = result .. "|[[" .. ET.as_string(et) .. "|" .. generator_steps  .. ET.backslash_modifier(et) .. "]]\n"
-- Bright generator in cents
result = result .. "|" .. u._round_dec(math.log(rat.as_float(et.equave)^(generator_steps / et.size))/math.log(2) * 1200, 3) .. "\n"
-- Dark generator in cents
result = result .. "|" .. u._round_dec(dark_generator_cents, 3) .. "\n" -- Round to 3 places
-- Step ratio and hardness value
result = result .. "|" .. step_ratio[1] .. ":" .. step_ratio[2] .. "\n"
result = result .. "|" .. l_s .. "\n"
-- Comment
result = result .. "|" .. comment .. "\n"
i = i + 1
end
end
result = result .. "|}"
result = result .. "|}"
return result
return result
end
end
function p.scale_tree(frame)
local mos = MOS.parse(frame.args["tuning"])
local depth = frame.args["depth"] or 5
local comments_unparsed = frame.args["Comments"] or ""
local comments = p.parse_kv_pairs(comments_unparsed) or {}
local result = p._scale_tree(mos, depth, comments)
return result
end
return p
return p