Module:MOS degrees: Difference between revisions

Ganaram inukshuk (talk | contribs)
No edit summary
Ganaram inukshuk (talk | contribs)
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 step_ratio = mosnot.parse_step_ratio(frame.args['Step Ratio']) or { 2, 1 }
-- 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 step_ratio = { 2, 1 }
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(input_mos)
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, step_ratio, asc_chain_length, des_chain_length)
-- 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
local steps_in_et = input_mos.nL * step_ratio[1] + input_mos.ns * step_ratio[2]
local et_for_mos = et.new(steps_in_et, input_mos.equave)
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(et_for_mos) .. '\n'
for i = 1, #step_ratios do
result = result .. "(L:s = " .. step_ratio[1] .. ":" .. step_ratio[2] .. ")\n"
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
-- Is the row for a period?
local is_period = steps_and_cents[i][1] % (steps_in_et / periods_per_equave) == 0
-- 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[i][2] .. "¢\n" -- Cents
result = result .. "| " .. steps_and_cents[j][i][1] .. "\n" -- Steps
result = result .. "| " .. steps_and_cents[j][i][2] .. "¢\n" -- Cents
end
end
end