Module:MOS mode degrees: Difference between revisions
Jump to navigation
Jump to search
Undo revision 148419 by Ganaram inukshuk (talk) (forgot that mosprefix was for the header, not the scale degrees in the udp) Tag: Undo |
m Changed how 5L 2s default mode names are presented |
||
| Line 204: | Line 204: | ||
-- Modes of harmonic minor | -- Modes of harmonic minor | ||
mode_names = { | mode_names = { | ||
"Aeolian ♮7 | "Harmonic minor<br>Aeolian ♮7", | ||
"Locrian ♮6", | "Locrian ♮6", | ||
"Ionian #5 | "Ionian augmented<br>Ionian #5", | ||
"Dorian #4", | "Dorian #4", | ||
"Phrygian ♮3 | "Phrygian dominant<br>Phrygian ♮3", | ||
"Lydian #2", | "Lydian #2", | ||
"Locrian b4 bb7 | "Altered diminished<br>Locrian b4 bb7", | ||
} | } | ||
elseif step_pattern == "LLsLsAs" then | elseif step_pattern == "LLsLsAs" then | ||
| Line 226: | Line 226: | ||
-- Modes of melodic minor | -- Modes of melodic minor | ||
mode_names = { | mode_names = { | ||
"Ionian b3 | "Melodic minor<br>Ionian b3", | ||
"Dorian b2", | "Dorian b2", | ||
"Lydian #5 | "Lydian augmented<br>Lydian #5", | ||
"Lydian b7 | "Lydian dominant<br>Lydian b7", | ||
"Mixolydian b6", | "Mixolydian b6", | ||
" | "Half-diminished<br>Aeolian b5", | ||
" | "Altered, Altered dominant<br>Locrian b4", | ||
} | } | ||
elseif step_pattern == "sLLLLLs" then | elseif step_pattern == "sLLLLLs" then | ||
-- Modes of Neapolitan major | -- Modes of Neapolitan major | ||
mode_names = { | mode_names = { | ||
"Ionian b2 b3 | "Neapolitan major<br>Ionian b2 b3", | ||
"Lydian | "Lydian augmented #6<br>Lydian #5 #6", | ||
"Lydian #5 b7 | "Lydian augmented dominant<br>Lydian #5 b7", | ||
"Lydian b6 b7 | "Lydian minor<br>Lydian b6 b7", | ||
"Mixolydian b5 b6 | "Major locrian<br>Mixolydian b5 b6", | ||
"Aeolian b4 b5 | "Altered dominant ♮2<br>Aeolian b4 b5", | ||
"Locrian bb3 b4 | "Altered dominant bb3<br>Locrian bb3 b4", | ||
} | } | ||
elseif step_pattern == "sLLLsAs" then | elseif step_pattern == "sLLLsAs" then | ||
-- TODO: Modes of Neapolitan minor | -- TODO: Modes of Neapolitan minor | ||
mode_names = { | mode_names = { | ||
"Phrygian ♮7 | "Neapolitan minor<br>Phrygian ♮7", | ||
"Lydian #6", | "Lydian #6", | ||
"Mixolydian #5 | "Mixolydian augmented<br>Mixolydian #5", | ||
"Aeolian #4", | "Aeolian #4", | ||
"Locrian ♮3 | "Locrian dominant<br>Locrian ♮3", | ||
"Ionian #2", | "Ionian #2", | ||
"Locrian bb3 b4 bb7 | "Altered diminished bb3<br>Locrian bb3 b4 bb7", | ||
} | } | ||
elseif #step_pattern == 0 then | elseif #step_pattern == 0 then | ||
Revision as of 22:56, 23 July 2024
- This module should not be invoked directly; use its corresponding template instead: Template:MOS mode degrees.
This module creates a table of the scale degrees for each mode of a MOS or MODMOS scale.
| Introspection summary for Module:MOS mode degrees | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||||||||||||||||||
No function descriptions were provided. The Lua code may have further information.
local mos = require("Module:MOS")
local tip = require("Module:Template input parse")
local tamnams = require("Module:TAMNAMS")
local p = {}
-- Global variables for cell colors
-- Colors are as follows:
-- Large intervals are yellow, small intervals are blue, augmented intervals are dark yellow, and diminished intervals are dark blue
p.cell_color_none = "NONE" -- For cells that don't have a color (default cell color applies)
p.cell_color_perfect_size = "NONE" -- Only applies for periods, including the root and equave
p.cell_color_lg_altered_size = "#BDD7EE"
p.cell_color_large_size = "#DDEBF7"
p.cell_color_small_size = "#FCE4D6"
p.cell_color_sm_altered_size = "#F8CBAD"
-- Finds the row color for a single cell
function p.cell_color(interval, input_mos)
local interval = interval or {["L"] = 3, ["s"] = 1}
local input_mos = input_mos or mos.new(5, 2)
local period_step_count = mos.period_step_count(input_mos)
local interval_step_count = mos.interval_step_count(interval)
local chroma_count = mos.interval_chroma_count(interval, input_mos)
local is_period_interval = interval_step_count % period_step_count == 0
local color = p.cell_color_none
if is_period_interval then
if chroma_count > 0 then
color = p.cell_color_lg_altered_size
elseif chroma_count == 0 then
color = p.cell_color_none
elseif chroma_count < 0 then
color = p.cell_color_sm_altered_size
end
else
if chroma_count > 0 then
color = p.cell_color_lg_altered_size
elseif chroma_count == 0 then
color = p.cell_color_large_size
elseif chroma_count == -1 then
color = p.cell_color_small_size
elseif chroma_count < -1 then
color = p.cell_color_sm_altered_size
end
end
return color
end
-- Create a table of a mos's degrees
-- If a step pattern is provided, it's assumed to be that of a modmos
function p._mos_mode_degrees(input_mos, mos_prefix, mode_names, use_default_mode_names, step_pattern)
local is_true_mos = step_pattern == nil
local input_mos = input_mos or mos.new(5, 2)
local mos_prefix = mos_prefix or "mos"
local mode_names = mode_names or nil
local use_default_mode_names = use_default_mode_names == 1
-- Get the modes as strings and step vectors
local step_patterns = {}
local step_matrices = {}
if is_true_mos then
step_patterns = mos.modes_by_brightness(input_mos)
step_matrices = mos.modes_to_step_matrices(input_mos)
else
step_patterns = mos.mode_rotations(step_pattern)
step_matrices = mos.mode_rotations_to_step_matrices(step_pattern)
end
-- Get the brightness (UDP) and rotational orderings (CPOs).
local udps = {}
local cpos = {}
if is_true_mos then
udps = tamnams.mos_mode_udps(input_mos)
cpos = tamnams.mos_mode_cpos(input_mos)
else
-- Modmos udps require a mosabbrev; this is forced to be "m" since some
-- abbrevs are tooo long. Get both the names for the closest-bright and
-- closest-dark mode. If they're the same, only one name will be used;
-- if not, both are used.
-- The CPOs of a modmos are simply 1 to n (n is the mode count).
local udps_closest_bright = tamnams.mode_rotation_udps(step_pattern, input_mos, "m", true)
local udps_closest_dark = tamnams.mode_rotation_udps(step_pattern, input_mos, "m", false)
for i = 1, #udps_closest_bright do
if udps_closest_bright[i] == udps_closest_dark[i] then
table.insert(udps, udps_closest_bright[i])
else
table.insert(udps, string.format("%s<br>%s", udps_closest_bright[i], udps_closest_dark[i]))
end
table.insert(cpos, i)
end
end
-- Get the scale sig
local scale_sig = mos.as_string(input_mos)
-- Equave step count; needed for degree column count
local equave_step_count = mos.equave_step_count(input_mos)
-- Create table
local result = "{| class=\"wikitable sortable\"\n"
-- Table header
-- If it's for a modmos, add the step pattern
result = result .. string.format("|+ style=\"font-size: 105%%;\" | Scale degree qualities of %s modes", scale_sig) .. (is_true_mos and "\n" or string.format(" (%s)\n", step_pattern))
-- Add table headers for first row
result = result
.. "! rowspan=\"2\" | UDP " .. (is_true_mos and "" or " and alterations ") -- If modmos, add "and alterations" string
.. "!! rowspan=\"2\" | Rotational Order "
.. "!! rowspan=\"2\" | Step pattern"
-- Add mode names if present
local mode_names_given = (mode_names ~= nil and #mode_names == #step_patterns) or use_default_mode_names
if mode_names_given then
result = result .. " !! rowspan=\"2\" class=\"unsortable\" | Mode names"
end
-- Add header for scale degrees
result = result .. string.format(" !! colspan=\"%d\" class=\"unsortable\" | Scale degree (%sdegree)\n", #step_matrices[1], mos_prefix)
-- Add second row of headers
result = result .. "|- class=\"unsortable\"\n"
.. "! 0"
for i = 1, #step_patterns[1] do
result = result .. string.format(" !! %d", i)
end
result = result .. "\n"
-- Add table contents
for i = 1, #step_patterns do
result = result .. "|-\n"
-- Add brightness order (as UDP), rotational order, and step pattern
.. string.format("| %s || %s || %s", udps[i], cpos[i], step_patterns[i])
-- Add mode name if given
if mode_names_given then
if use_default_mode_names then
result = result .. string.format(" || %s %s", scale_sig, udps[i])
else
result = result .. string.format(" || %s", mode_names[i])
end
end
-- Add scale degrees with cell coloring
for j = 1, #step_matrices[i] do
local current_interval = step_matrices[i][j]
local degree_quality = tamnams.decode_quality(current_interval, input_mos, "shortened")
local cell_color = p.cell_color(current_interval, input_mos)
local style_code = cell_color == p.cell_color_none and "" or string.format("style=\"background: %s;\" | ", cell_color)
result = result .. string.format(" || %s%s", style_code, degree_quality)
end
result = result .. "\n"
end
-- End of table
result = result .. "|}"
return result
end
-- Function to be called as part of a template
function p.mos_mode_degrees(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 scale sig; for calculating the mos prefix
local scale_sig = mos.as_string(input_mos)
-- Default param for mos prefix
-- If "NONE" is given, no prefix will be used
-- If left blank, try to find the appropriate mos prefix, or else defualt to "mos"
-- If not left blank, use the prefix passed in instead
local mos_prefix = "mos"
if frame.args["MOS Prefix"] == "NONE" then
mos_prefix = ""
elseif string.len(frame.args["MOS Prefix"]) == 0 then
mos_prefix_lookup = tamnams.lookup_prefix(input_mos) or ""
if string.len(mos_prefix_lookup) ~= 0 then
mos_prefix = mos_prefix_lookup
end
else
mos_prefix = frame.args["MOS Prefix"]
end
-- Get the step pattern
local step_pattern = frame.args["MODMOS Step Pattern"]
-- Get the mode names
local mode_names = nil
-- Default names for 5L 2s modes and select modmosses.
-- Names are based on whichever mode is returnd by UDP closest-mode search,
-- with common names added wherever applicable. Sources include:
-- - https://www.jazz-guitar-licks.com/ and likely others
-- - Whatever Wikipedia has cited for the Neapolitan scales
-- NOTE: these names can be overridden if they don't suffice.
if scale_sig == "5L 2s" then
if step_pattern == "LsLLsAs" then
-- Modes of harmonic minor
mode_names = {
"Harmonic minor<br>Aeolian ♮7",
"Locrian ♮6",
"Ionian augmented<br>Ionian #5",
"Dorian #4",
"Phrygian dominant<br>Phrygian ♮3",
"Lydian #2",
"Altered diminished<br>Locrian b4 bb7",
}
elseif step_pattern == "LLsLsAs" then
-- Modes of harmonic major
mode_names = {
"Ionian b6 (Harmonic major)",
"Dorian b5",
"Phrygian b4",
"Lydian b3",
"Mixolydian b2",
"Lydian #2 #5 (Lydian augmented #2)",
"Locrian bb7",
}
elseif step_pattern == "LsLLLLs" then
-- Modes of melodic minor
mode_names = {
"Melodic minor<br>Ionian b3",
"Dorian b2",
"Lydian augmented<br>Lydian #5",
"Lydian dominant<br>Lydian b7",
"Mixolydian b6",
"Half-diminished<br>Aeolian b5",
"Altered, Altered dominant<br>Locrian b4",
}
elseif step_pattern == "sLLLLLs" then
-- Modes of Neapolitan major
mode_names = {
"Neapolitan major<br>Ionian b2 b3",
"Lydian augmented #6<br>Lydian #5 #6",
"Lydian augmented dominant<br>Lydian #5 b7",
"Lydian minor<br>Lydian b6 b7",
"Major locrian<br>Mixolydian b5 b6",
"Altered dominant ♮2<br>Aeolian b4 b5",
"Altered dominant bb3<br>Locrian bb3 b4",
}
elseif step_pattern == "sLLLsAs" then
-- TODO: Modes of Neapolitan minor
mode_names = {
"Neapolitan minor<br>Phrygian ♮7",
"Lydian #6",
"Mixolydian augmented<br>Mixolydian #5",
"Aeolian #4",
"Locrian dominant<br>Locrian ♮3",
"Ionian #2",
"Altered diminished bb3<br>Locrian bb3 b4 bb7",
}
elseif #step_pattern == 0 then
-- True-mos modes
mode_names = {
"Lydian",
"Ionian (major)",
"Mixolydian",
"Dorian",
"Aeolian (minor)",
"Phrygian",
"Locrian"
}
end
end
-- If mode names are given, use those instead
-- If using default mode names (scalesig+udp), those names are auto-added by the relevant function
local use_default_names = 0
if #frame.args["Mode Names"] ~= 0 then
if frame.args["Mode Names"] == "Default" then
use_default_names = 1
else
mode_names = tip.parse_entries(frame.args["Mode Names"])
end
end
-- If a modmos step pattern was never provided, call the function mos_mode_degrees
-- Otherwise, call the function modmos_mode_degrees
local result = ""
if step_pattern == "" then
result = p._mos_mode_degrees(input_mos, mos_prefix, mode_names, use_default_names)
--elseif #step_pattern == input_mos.nL + input_mos.ns then
else
result = p._mos_mode_degrees(input_mos, mos_prefix, mode_names, use_default_names, step_pattern)
end
return result
end
return p