local mos = require('Module:MOS')
local rat = require('Module:Rational')
local p = {}
-- Helper function that turns a mosstep into a step count as a string
-- EG, the 3-mosstep of "LLsLsLs" becomes "2L + s"
function p.mos_interval_to_step_count_string(step_pattern, mossteps)
local L_count = 0
local s_count = 0
for i = 1, mossteps do
local step = string.sub(step_pattern, i, i)
if step == "L" then
L_count = L_count + 1
elseif step == "s" then
s_count = s_count + 1
end
end
local return_string = ""
if L_count == 0 and s == 0 then
return_string = "0"
elseif L_count == 1 and s == 1 then
return_string = "L + s"
elseif L_count == 1 and s_count == 0 then
return_string = "L"
elseif L_count == 1 and s_count > 2 then
return_string = "L + " .. s_count .. "s"
elseif L_count == 0 and s_count == 1 then
return_string = "s"
elseif L_count > 2 and s_count == 1 then
return_string = L_count .. "L + s"
else
return_string = L_count .. "L + " .. s_count .. "s"
end
return return_string
end
function p.mos_intervals_frame()
-- Default param for input mos is 5L 2s
local input_mos = mos.parse(frame.args['Scale Signature']) or mos.new(2, 5, 2)
-- Get the brightest and darkest modes for the mos
local brightest_mode = mos.brightest_mode(input_mos)
local darkest_mode = string.reverse(brightest_mode)
-- Get the number of steps per period and equave
local steps_per_equave = (input_mos.nL + input_mos.ns)
local steps_per_period = steps_per_equave / rat.gcd(input_mos.nL, input_mos.ns)
-- Get the step counts for the bright and dark generators
local bright_gen = mos.bright_gen(input_mos)
local steps_per_bright_gen = bright_gen['L'] + bright_gen['s']
local steps_per_dark_gen = steps_per_period - steps_per_bright_gen
-- Get the scale sig
local scale_sig = mos.as_string(input_mos)
-- Create the table, starting with the headers
local result = '{| class="wikitable"\n'
result = result .. '|+\n'
result = result .. scale_sig .. ' interval varieties\n'
result = result .. '! rowspan="2" |Interval class\n'
result = result .. '! colspan="2" |Large variety\n'
result = result .. '! colspan="2" |Small variety\n'
result = result .. '|-\n'
result = result .. '! Size\n'
result = result .. '! Quality\n'
result = result .. '!Size\n'
result = result .. '!Quality\n'
-- First row is the unison
result = result .. "|-\n"
result = result .. "|'''0-mosstep (unison)'''\n"
result = result .. "|0\n"
result = result .. "|Perfect\n"
result = result .. "|0\n"
result = result .. "|Perfect\n"
-- Successive rows are the mossteps, starting at the 1-mosstep
-- Name the interval according to whether it's major/minor or
-- perf/aug/dim; for nL ns mosses, it's only major/minor for any
-- non-period intervals.
local is_nL_ns = input_mos.nL == input_mos.ns
for i = 1, steps_per_equave do
-- If i corresponds to the bright generator, then the large size is
-- perfect and the small size is diminished.
-- If i corresponds to the dark generator, then the large size is
-- augmented and the small size is perfect.
-- If i corresponds to the period, then the large and small sizes are
-- the same and they're perfect.
-- For any other interval, and for generators for nL ns mosses, the
-- large size is major and the small size is minor.
if i % steps_per_period == steps_per_bright_gen and not is_nL_ns then
result = result .. "|'''" .. i .. "-mosstep'''\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(brightest_mode, i) .. "\n"
result = result .. "|Perfect\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(darkest_mode, i) .. "\n"
result = result .. "|Diminished\n"
elseif i % steps_per_period == steps_per_bright_gen and not is_nL_ns then
result = result .. "|'''" .. i .. "-mosstep'''\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(brightest_mode, i) .. "\n"
result = result .. "|Augmented\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(darkest_mode, i) .. "\n"
result = result .. "|Perfect\n"
elseif i % steps_per_period == 0 then
result = result .. "|'''" .. i .. "-mosstep (period)'''\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(brightest_mode, i) .. "\n"
result = result .. "|Perfect\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(darkest_mode, i) .. "\n"
result = result .. "|Perfect\n"
else
result = result .. "|" .. i .. "-mosstep\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(brightest_mode, i) .. "\n"
result = result .. "|Major\n"
result = result .. "|" .. p.mos_interval_to_step_count_string(darkest_mode, i) .. "\n"
result = result .. "|Minor\n"
end
end
return result
end
return p