Module:MOS degrees: Difference between revisions
No edit summary |
Added support for up to three step ratios |
||
| Line 5: | Line 5: | ||
local mosnot = require('Module:MOS notation') -- Contains the important functions | local mosnot = require('Module:MOS notation') -- Contains the important functions | ||
local p = {} | local p = {} | ||
-- Helper function | |||
-- Parses up to 3 step ratios entered as text in a semicolon-delimited string, | |||
-- where each step ratio is separated with a slash | |||
-- EG, "2/1; 3/1; 3/2" becomes {{2, 1}, {3, 1}, {3, 2}} | |||
function p.parse_step_ratios(unparsed) | |||
local parsed = {} | |||
for entry in string.gmatch(unparsed, '([^;]+)') do | |||
local trimmed = entry:gsub("^%s*(.-)%s*$", "%1") | |||
table.insert(parsed, trimmed) -- Add to array | |||
end | |||
-- Parse up to 3 step ratios | |||
local loop_limit = math.min(3, #parsed) | |||
local step_ratios = {} | |||
for i = 1, loop_limit do | |||
local ratio = mosnot.parse_step_ratio(parsed[i]) | |||
table.insert(step_ratios, ratio) | |||
end | |||
return step_ratios | |||
end | |||
-- Helper function | -- Helper function | ||
| Line 204: | Line 225: | ||
local input_mos = mos.parse(frame.args['Scale Signature']) or mos.new(2, 5, 2) | local input_mos = mos.parse(frame.args['Scale Signature']) or mos.new(2, 5, 2) | ||
-- Step ratio | -- Step ratios | ||
local | -- Up to three step ratios can be entered; the default is one step ratio | ||
-- of 2/1, for a basic step ratio | |||
local step_ratios = p.parse_step_ratios(frame.args['Step Ratio']) or {{ 2, 1 }} | |||
-- Get the number of mossteps per period and equave | -- Get the number of mossteps per period and equave | ||
| Line 261: | Line 284: | ||
--[[ | --[[ | ||
local input_mos = mos.new(5, 2, 2) | local input_mos = mos.new(5, 2, 2) | ||
local | local step_ratios = {{ 2, 1 }, {3, 1}, {3, 2}} | ||
local udp = { 5, 1 } | local udp = { 5, 1 } | ||
local note_symbols = "CDEFGAB" | local note_symbols = "CDEFGAB" | ||
| Line 269: | Line 292: | ||
local periods_per_equave = rat.gcd(input_mos.nL, input_mos.ns) | local periods_per_equave = rat.gcd(input_mos.nL, input_mos.ns) | ||
local mossteps_per_period = mossteps_per_equave / periods_per_equave | local mossteps_per_period = mossteps_per_equave / periods_per_equave | ||
local scale_sig = mos.as_string( | local scale_sig = mos.as_string(inpnut_mos) | ||
]]-- | ]]-- | ||
| Line 283: | Line 306: | ||
-- Get the step and cent values | -- Get the step and cent values | ||
local steps_and_cents = p.preprocess_steps_and_cents(input_mos, | -- Do this for each step ratio | ||
local steps_and_cents = {} | |||
for i = 1, #step_ratios do | |||
local cells = p.preprocess_steps_and_cents(input_mos, step_ratios[i], asc_chain_length, des_chain_length) | |||
table.insert(steps_and_cents, cells) | |||
end | |||
-- Format the output as a table, starting with the header row | -- Format the output as a table, starting with the header row | ||
local result = '{| class="wikitable sortable"\n' | local result = '{| class="wikitable sortable"\n' | ||
-- Pre-calculate the ets and step counts for each step ratio | |||
local steps_in_ets = {} | |||
local ets_for_mos = {} | |||
for i = 1, #step_ratios do | |||
local steps_in_ets_i = input_mos.nL * step_ratios[i][1] + input_mos.ns * step_ratios[i][2] | |||
local ets_for_mos_i = et.new(steps_in_ets_i, input_mos.equave) | |||
table.insert(steps_in_ets, steps_in_ets_i) | |||
table.insert(ets_for_mos, ets_for_mos_i) | |||
end | |||
-- Produce the headers; first row | -- Produce the headers; first row | ||
result = result .. '! rowspan="2" |Scale degree\n' | result = result .. '! rowspan="2" |Scale degree\n' | ||
result = result .. '! rowspan="2" |Note name\n(on ' .. string.sub(note_symbols, 1, 1) .. ")\n" | result = result .. '! rowspan="2" |Note name\n(on ' .. string.sub(note_symbols, 1, 1) .. ")\n" | ||
-- Add this once for every step ratio to be represented | -- Add this once for every step ratio to be represented | ||
result = result .. '! colspan="2" |Steps of ' .. et.as_string( | for i = 1, #step_ratios do | ||
result = result .. '! colspan="2" |Steps of ' .. et.as_string(ets_for_mos[i]) .. '\n' | |||
result = result .. "(L:s = " .. step_ratios[i][1] .. ":" .. step_ratios[i][2] .. ")\n" | |||
end | |||
-- Next row | -- Next row | ||
| Line 309: | Line 347: | ||
-- Is the row for a nominal? (Nominals have no accidentals and are | -- Is the row for a nominal? (Nominals have no accidentals and are | ||
-- therefore strings of size 1) | -- therefore strings of size 1) | ||
-- Nominals don't depend on step ratio | |||
local is_nominal = string.len(degrees_and_note_names[i][2]) == 1 | local is_nominal = string.len(degrees_and_note_names[i][2]) == 1 | ||
-- Add new row, with coloring | -- Add new row, with coloring | ||
| Line 320: | Line 356: | ||
result = result .. "|-\n" | result = result .. "|-\n" | ||
end | end | ||
-- Is the row for a period? | |||
-- Check whether it's a period for the first step ratio, since it'll be | |||
-- a period for any of the other step ratios | |||
local is_period = steps_and_cents[1][i][1] % (steps_in_ets[1] / periods_per_equave) == 0 | |||
-- Add cells for degree and note name | -- Add cells for degree and note name | ||
| Line 331: | Line 372: | ||
-- Add cells for step size | -- Add cells for step size | ||
result = result .. "| " .. steps_and_cents[i][1] .. "\n" -- Steps | for j = 1, #step_ratios do | ||
result = result .. "| " .. steps_and_cents[j][i][1] .. "\n" -- Steps | |||
result = result .. "| " .. steps_and_cents[j][i][2] .. "¢\n" -- Cents | |||
end | |||
end | end | ||