Module:MOS modes: Difference between revisions
Jump to navigation
Jump to search
m Added todo |
Adopt functions provided by other templates; also a bugfix to "round" being missing |
||
Line 2: | Line 2: | ||
local rat = require('Module:Rational') | local rat = require('Module:Rational') | ||
local utils = require('Module:Utils') | local utils = require('Module:Utils') | ||
local tip = require('Module:Template input parse') | |||
local p = {} | local p = {} | ||
-- TODO: collapse table if the number of modes is, say, more than 12 | -- TODO: collapse table if the number of modes is, say, more than 12 | ||
-- "Main" function | -- "Main" function | ||
Line 71: | Line 18: | ||
-- Get the mos's modes and the mode count | -- Get the mos's modes and the mode count | ||
local mos_modes = | local mos_modes = mos.modes_by_brightness(input_mos) | ||
local periods = | local periods = mos.period_count(input_mos) | ||
local mossteps_per_period = (input_mos | local mossteps_per_period = mos.period_step_count(input_mos) | ||
-- This is for entering multiple columns of info, if a single column of mode names isn't enough | -- This is for entering multiple columns of info, if a single column of mode names isn't enough | ||
Line 92: | Line 39: | ||
-- Used for calculating rotational order | -- Used for calculating rotational order | ||
local bright_gen = mos.bright_gen(input_mos) | local bright_gen = mos.bright_gen(input_mos) | ||
local mossteps_per_bright_gen = | local mossteps_per_bright_gen = mos.bright_gen_step_count(input_mos) | ||
-- Make a table with a column for the mode (as a string of L's and s's) and UDP | -- Make a table with a column for the mode (as a string of L's and s's) and UDP | ||
Line 118: | Line 65: | ||
-- As of coding, mos mode listings are fairly inconsistent or nonexistent, but consist of | -- As of coding, mos mode listings are fairly inconsistent or nonexistent, but consist of | ||
-- the UDP, step pattern, and any mode names(s) in some order | -- the UDP, step pattern, and any mode names(s) in some order | ||
-- This table orders them as UDP, step pattern, and | -- This table orders them as UDP, step pattern, and mode names, as that's more common | ||
for i = 1, #mos_modes do | for i = 1, #mos_modes do | ||
result = result .. "|-\n" | result = result .. "|-\n" | ||
Line 178: | Line 125: | ||
else | else | ||
mode_names_unparsed = frame.args['Mode Names'] | mode_names_unparsed = frame.args['Mode Names'] | ||
mode_names = | mode_names = tip.parse_entries(mode_names_unparsed) | ||
end | end | ||
Revision as of 03:48, 5 June 2024
Note: Do not invoke this module directly; use the corresponding template instead: Template:MOS modes.
This template is used for mos pages to automatically generate and list that mos's modes, along with the modes' UDP (up-down-period) notation.
local mos = require('Module:MOS')
local rat = require('Module:Rational')
local utils = require('Module:Utils')
local tip = require('Module:Template input parse')
local p = {}
-- TODO: collapse table if the number of modes is, say, more than 12
-- "Main" function
-- To be called by wrapper
function p._mos_modes(input_mos, mode_names, headers, entries)
-- Mos is entered as a scale signature "xL ys" or "xL ys<p/q>" since the mos module can parse that format
local input_mos = input_mos or mos.parse(scale_sig)
-- Get the mos's mode names, if given
-- Mode names are entered as a semicolon-delimited list
local mode_names = mode_names or {}
-- Get the mos's modes and the mode count
local mos_modes = mos.modes_by_brightness(input_mos)
local periods = mos.period_count(input_mos)
local mossteps_per_period = mos.period_step_count(input_mos)
-- This is for entering multiple columns of info, if a single column of mode names isn't enough
-- For n headers, the number of entries must match the number of modes times the number of headers
-- or else column data won't be added
local headers = headers or {}
local entries = entries or {}
-- To determine whether to add additional columns, determine whether the number of entries
-- and the number of columns are greater than zero, and if so, determine whether the number of entries
-- is equal to the number of headers times the number of modes
local add_columns = #headers > 0 and #entries > 0
if add_columns then
add_columns = add_columns and #mos_modes * #headers == #entries
end
-- Get the number of mossteps in the bright gen
-- Used for calculating rotational order
local bright_gen = mos.bright_gen(input_mos)
local mossteps_per_bright_gen = mos.bright_gen_step_count(input_mos)
-- Make a table with a column for the mode (as a string of L's and s's) and UDP
local result = '{| class="wikitable sortable"\n'
result = result .. "|+ " .. "Modes of " .. mos.as_string(input_mos) .. "\n" -- To create the scale signature with〈〉instead of <>
result = result .. "|-\n"
result = result .. "! [[UDP]]\n"
result = result .. "! Rotational order\n"
result = result .. "! Step pattern\n"
-- If there are mode names (if the mode names array is not nil), then add a column for mode names
if #mode_names == #mos_modes then
result = result .. '! class="unsortable" | Mode names\n'
end
-- Add columns
-- If mode names and columns are used, mode names come first
if add_columns then
for i = 1, #headers do
result = result .. '! class="unsortable" |' .. headers[i] .. "\n"
end
end
-- Enter each row
-- As of coding, mos mode listings are fairly inconsistent or nonexistent, but consist of
-- the UDP, step pattern, and any mode names(s) in some order
-- This table orders them as UDP, step pattern, and mode names, as that's more common
for i = 1, #mos_modes do
result = result .. "|-\n"
-- Add the UDP, formatted as up|dp(p), where u is the number of bright generators going up,
-- d is the number of bright generators going down, and p is the number of periods
-- Omit p if p = 1
local gens_down = (i - 1) * periods
local gens_up = (#mos_modes - i) * periods
local udp_as_text = ""
if periods == 1 then
udp_as_text = gens_up .. '|' .. gens_down
else
udp_as_text = gens_up .. '|' .. gens_down .. "(" .. periods .. ")"
end
result = result .. "|" .. udp_as_text .. "\n"
-- Add the mode's rotational order
local bright_gens_up = mossteps_per_bright_gen * (i-1)
local rotational_order = bright_gens_up % mossteps_per_period + 1
result = result .. "|" .. rotational_order .. "\n"
-- Add the mode's step pattern
result = result .. "|" .. mos_modes[i] .. "\n"
-- Add the mode's name, if given
if #mode_names == #mos_modes then
result = result .. "|" .. mode_names[i] .. "\n"
end
-- Add columns if given
if add_columns then
for j = 1, #headers do
local index = (i - 1) * #headers + j
result = result .. "|" .. entries[index] .. "\n"
end
end
end
result = result .. "|}"
return result
end
-- Wrapper function; to be called by template
function p.modes_table(frame)
-- Mos is entered as a scale signature "xL ys" or "xL ys<p/q>" since the mos module can parse that format
local scale_sig = frame.args['Scale Signature'] or "5L 2s"
local input_mos = mos.parse(scale_sig)
-- Get the mos's mode names, if given
-- Mode names are entered as a semicolon-delimited list
-- 5L 2s gets default names
local mode_names = nil
if scale_sig == "5L 2s" then
mode_names_unparsed = "Lydian; Ionian (major); Mixolydian; Dorian; Aeolian (minor); Phrygian; Locrian"
mode_names = p.parse_entries(mode_names_unparsed)
else
mode_names_unparsed = frame.args['Mode Names']
mode_names = tip.parse_entries(mode_names_unparsed)
end
-- This is for entering multiple columns of info, if a single column of mode names isn't enough
-- For n headers, the number of entries must match the number of modes times the number of headers
-- or else column data won't be added
local headers_unparsed = frame.args['Table Headers']
local headers = p.parse_entries(headers_unparsed)
local entries_unparsed = frame.args['Table Entries']
local entries = p.parse_entries(entries_unparsed)
local result = p._mos_modes(input_mos, mode_names, headers, entries)
return result
end
return p