|
|
| (95 intermediate revisions by 3 users not shown) |
| Line 1: |
Line 1: |
| local mos = require('Module:MOS')
| |
| local rat = require('Module:Rational')
| |
| local utils = require('Module:Utils')
| |
| local mosnot = require('Module:MOS notation')
| |
| local et = require('Module:ET')
| |
| local tamnams = require('Module:TAMNAMS')
| |
| local p = {} | | local p = {} |
|
| |
|
| -- TODO:
| | local mos = require("Module:MOS") |
| -- - Adopt new mos/tamnams functions for modmosses
| | local tamnams = require("Module:TAMNAMS") |
| -- - Re-add cell colors for true-mos table | | local tip = require("Module:Template input parse") |
| | local yesno = require("Module:Yesno") |
| | |
| | -- TODO |
| | -- - Split off modmos mode degrees as a separate template |
|
| |
|
| -- Global variables for cell colors | | -- Global variables for cell colors |
| -- Colors are as follows: | | -- Colors are as follows: |
| -- Large intervals are yellow, small intervals are blue, augmented intervals are dark yellow, and diminished intervals are dark blue | | -- - Orange and blue for small and large sizes, respectively |
| | -- - Darker colors for altered scale degrees |
| | -- - No color for period intervals |
| p.cell_color_none = "NONE" -- For cells that don't have a color (default cell color applies) | | 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_perfect_size = "NONE" -- Only applies for periods, including the root and equave |
| p.cell_color_lg_altered_size = "BDD7EE" | | p.cell_color_lg_altered_size = "#BDD7EE" |
| p.cell_color_large_size = "DDEBF7" | | p.cell_color_large_size = "#DDEBF7" |
| p.cell_color_small_size = "FCE4D6" | | p.cell_color_small_size = "#FCE4D6" |
| p.cell_color_sm_altered_size = "F8CBAD" | | p.cell_color_sm_altered_size = "#F8CBAD" |
| | |
| -- TODO?: Move some functions to the mos notation module
| |
|
| |
|
| -- Helper function | | -- Finds the row color for a single cell |
| -- Parses entries from a semicolon-delimited string and returns them in an array
| | function p.cell_color(interval, input_mos) |
| -- TODO: Separate this and related functions (parse_pair and parse_kv_pairs) into its own module, as they're included
| | local interval = interval or {["L"] = 3, ["s"] = 1} |
| -- in various modules at this point, such as: scale tree, mos mdoes
| |
| function p.parse_entries(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
| |
| return parsed
| |
| end
| |
| | |
| -- Helper function
| |
| -- Determines whether an item is in an array
| |
| function p.find_item_in_table(table, item)
| |
| | |
| local item_found = false
| |
| for i = 1, #table do
| |
| if table[i] == item then
| |
| item_found = true
| |
| break
| |
| end
| |
| end
| |
| return item_found
| |
| end
| |
| | |
| -- Calculate the mosstep vector from the mosstep pattern
| |
| -- Given a mos's step pattern and a quantity of mossteps, this takes an interval
| |
| -- (as a substring of the mosstep pattern starting from the root) and counts the number
| |
| -- of L's and s's in that substring. Allowed steps are:
| |
| -- - L - a single large step
| |
| -- - s - a single small step (can be capital S or lowercase s)
| |
| -- - c - a single chroma, defined as L-s; counting this adds one L and subtracts one s
| |
| -- Note that L-c=s and s+c=L.
| |
| -- - A - an augmented step, defined as L+c; counting this adds two L's and subtracts one s
| |
| -- - d - a diminished step, defined as s-c; counting this subtracts one L and adds two s's
| |
| -- Note that adding a chroma to an s makes it an L, and removing a chroma from an L
| |
| -- makes it an s.
| |
| -- Above-equave mossteps are supported.
| |
| function p.convert_mosstep_pattern_to_mosstep_vector(mosstep_pattern, mossteps) | |
| local mossteps = mossteps or 7 | |
| local mosstep_pattern = mosstep_pattern or "LLLsLLs"
| |
|
| |
| local large_step_count = 0
| |
| local small_step_count = 0
| |
| local step_count = #mosstep_pattern
| |
| | |
| -- If the number of mossteps exceeds the mosstep pattern, divide that quantity
| |
| -- by the number of steps and round up, then duplicate the pattern by that much.
| |
| local number_of_repetitions = math.ceil(mossteps / step_count)
| |
| local mosstep_pattern_duplicated = string.rep(mosstep_pattern, number_of_repetitions)
| |
|
| |
| -- Count the number of L's and s's in the string
| |
| -- C's, A's, and d's are worth some number of L's and s's
| |
| for i = 1, mossteps do
| |
| local step = string.sub(mosstep_pattern_duplicated, i, i)
| |
| if step == "L" then
| |
| large_step_count = large_step_count + 1
| |
| elseif step == "s" or step == "S" then
| |
| small_step_count = small_step_count + 1
| |
| elseif step == "c" then
| |
| large_step_count = large_step_count + 1
| |
| small_step_count = small_step_count - 1
| |
| elseif step == "A" then
| |
| large_step_count = large_step_count + 2
| |
| small_step_count = small_step_count - 1
| |
| elseif step == "d" then
| |
| large_step_count = large_step_count - 1
| |
| small_step_count = small_step_count + 2
| |
| end
| |
| end
| |
|
| |
| local mosstep_vector = { ['L'] = large_step_count, ['s'] = small_step_count }
| |
| return mosstep_vector
| |
| end
| |
| | |
| -- Produce an encoded mosdegree from a mosstep vector
| |
| -- For an interval with two specific sizes, its large size is iL js and small size
| |
| -- is (i-1)L (j+1)s, for a difference of a single large step swapped with a single
| |
| -- small step. Alterations are denoted by adding or subtracting chromas, c, where a
| |
| -- chroma is L-s. An augmented step is L+c, denoted with a single A, so A=L+L-s.
| |
| -- Summing the number of L's and s's cancels out any negative step quantites for the
| |
| -- single A, so for any mosstep represented as a string of L's, s's, and A's, the sum of
| |
| -- the number of L's and s's produces the original interval (in mossteps). Similar
| |
| -- inductive reasoning applies with c's and d's, should a scale contain such steps.
| |
| -- To find how many alterations a mosstep vector had been applied to it:
| |
| -- - First, add or subtract chromas as needed until neither the L-count nor s-count
| |
| -- is negative, and record that number of chromas as k1.
| |
| -- - Then compare the step vector of that mosstep with the expected large or small size.
| |
| -- However many chromas are needed to add to reach the small size, or how many
| |
| -- chromas are need to remove to reach the small size, is the additional number
| |
| -- of chromas, k2, needed to reach the mos's large or small size. (Note that if
| |
| -- adding chromas, k2 is positive, but if removing chromas, k2 is negative.)
| |
| -- - Add k1 and k2. This is the number of alrerations the mosstep was from its large
| |
| -- or small size.
| |
| -- - Note that for mossteps with two specific sizes, there are effectively two "zero
| |
| -- points", one each for the large and small size, and which one to use depends
| |
| -- on whichever is closer. For mossteps with only one size, there is only one
| |
| -- zero point.
| |
| function p.calculate_mosstep_quality(input_mos, mosstep_vector)
| |
| local input_mos = input_mos or mos.new(5, 2) | | local input_mos = input_mos or mos.new(5, 2) |
| local mosstep_vector = mosstep_vector or { ['L'] = 5, ['s'] = 2 }
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps in the bright gen and dark gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s']
| |
| local mossteps_per_dark_gen = mossteps_per_period - mossteps_per_bright_gen
| |
|
| |
| -- Get the number of mossteps as the sum of the number of L's and s's
| |
| local mossteps = mosstep_vector['L'] + mosstep_vector['s']
| |
|
| |
| -- Get the brightest and darkest modes for the input mos
| |
| local brightest_mode = mos.brightest_mode(input_mos)
| |
| local darkest_mode = string.reverse(brightest_mode)
| |
|
| |
| -- Get the expected vector of the large mosstep
| |
| local expected_large_mosstep_vector = p.convert_mosstep_pattern_to_mosstep_vector(brightest_mode, mossteps)
| |
| | | |
| -- Since the size difference between the large and small intervals is a single chroma, | | local period_step_count = mos.period_step_count(input_mos) |
| -- which is L-s, simply count the large step difference between the given mosstep vector
| | local interval_step_count = mos.interval_step_count(interval) |
| -- and the expected large and small ones.
| | local chroma_count = mos.interval_chroma_count(interval, input_mos) |
| local large_step_count = mosstep_vector['L'] | |
| local number_of_chromas = large_step_count - expected_large_mosstep_vector['L'] | |
| | | |
| -- Determine what mosstep was passed in; is it a generator or period?
| | local is_period_interval = interval_step_count % period_step_count == 0 |
| local mos_is_nL_ns = input_mos.nL == input_mos.ns | |
| local mosstep_is_period = mossteps % mossteps_per_period == 0
| |
| local mosstep_is_bright_gen = mossteps % mossteps_per_period == mossteps_per_bright_gen and not mos_is_nL_ns
| |
| local mosstep_is_dark_gen = mossteps % mossteps_per_period == mossteps_per_dark_gen and not mos_is_nL_ns
| |
| | | |
| -- Rules for encoding are shown in the comments below. | | local color = p.cell_color_none |
| -- Encoding follows the rules as found in the module mos notation, where:
| | if is_period_interval then |
| -- - 3 = 2x augmented
| | if chroma_count > 0 then |
| -- - 2 = 1x augmented
| | color = p.cell_color_lg_altered_size |
| -- - 1 = major
| | elseif chroma_count == 0 then |
| -- - 0 = perfect (used for generators, roots, and periods)
| | color = p.cell_color_none |
| -- - -1 = minor
| | elseif chroma_count < 0 then |
| -- - -2 = 1x diminished
| | color = p.cell_color_sm_altered_size |
| -- - -3 = 2x diminished
| |
| -- The number_of_chromas found previously must be translated to this encoding.
| |
| local encoded_quality = 0
| |
| if mosstep_is_period then | |
| -- For periods:
| |
| -- - If the number of chromas is 1 or more, that quality is augmented
| |
| -- - If the nubmer of chromas is 0, that quality is perfect
| |
| -- - If the number of chromas is -1 or less, that quality is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 1 then | |
| encoded_quality = number_of_chromas + 1
| |
| elseif number_of_chromas == 0 then
| |
| encoded_quality = number_of_chromas | |
| elseif number_of_chromas <= -1 then
| |
| encoded_quality = number_of_chromas - 1
| |
| end
| |
| elseif mosstep_is_bright_gen then
| |
| -- For bright gens:
| |
| -- If the number of chromas is 1 or more, that quality is augmented
| |
| -- If the number of chromas is 0, that quality is perfect
| |
| -- If the number of chromas is -1 or less, that is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 1 then
| |
| encoded_quality = number_of_chromas + 1
| |
| elseif number_of_chromas == 0 then | |
| encoded_quality = 0 | |
| elseif number_of_chromas <= -1 then | |
| encoded_quality = number_of_chromas - 1
| |
| end
| |
| elseif mosstep_is_dark_gen then
| |
| -- For bright gens:
| |
| -- If the number of chromas is 0 or more, that quality is augmented
| |
| -- If the number of chromas is -1, that quality is perfect
| |
| -- If the number of chromas is -2 or less, that is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 0 then
| |
| encoded_quality = number_of_chromas + 2 | |
| elseif number_of_chromas == -1 then
| |
| encoded_quality = 0
| |
| elseif number_of_chromas <= -2 then
| |
| encoded_quality = number_of_chromas
| |
| end | | end |
| else | | else |
| -- For all other intervals:
| | if chroma_count > 0 then |
| -- If the number of chromas is 1 or more, that quality is augmented
| | color = p.cell_color_lg_altered_size |
| -- If the number of chromas is 0, that quality is major
| | elseif chroma_count == 0 then |
| -- If the number of chromas is -1, that quality is minor
| | color = p.cell_color_large_size |
| -- If the number of chromas is -2 or less, that is diminished
| | elseif chroma_count == -1 then |
| -- The encoded quality should always skip 0
| | color = p.cell_color_small_size |
| if number_of_chromas >= 1 then | | elseif chroma_count < -1 then |
| encoded_quality = number_of_chromas + 1 | | color = p.cell_color_sm_altered_size |
| elseif number_of_chromas == 0 then | |
| encoded_quality = 1 | |
| elseif number_of_chromas == -1 then | |
| encoded_quality = -1 | |
| elseif number_of_chromas <= -2 then | |
| encoded_quality = number_of_chromas | |
| end | | end |
| end | | end |
|
| | return color |
| return encoded_quality | |
| end | | end |
|
| |
|
| -- Helper function | | -- Create a table of a mos's degrees |
| -- Given a quality (and only a quality), decode it from a numeric value to text. | | -- If a step pattern is provided, it's assumed to be that of a modmos |
| -- Encoding follows the rules as found in the module mos notation, where:
| | function p._mos_mode_degrees(input_mos, mos_prefix, is_collapsed, step_pattern) |
| -- - 3 = 2x augmented
| | local is_true_mos = step_pattern == nil |
| -- - 2 = 1x augmented
| |
| -- - 1 = major
| |
| -- - 0 = perfect (used for generators, roots, and periods)
| |
| -- - -1 = minor
| |
| -- - -2 = 1x diminished
| |
| -- - -3 = 2x diminished
| |
| -- That encoded value should be converted back to text
| |
| function p.decode_quality(encoded_quality) | |
| | |
| local quality_as_text = "" | |
| if encoded_quality == 0 then
| |
| quality_as_text = "Perf."
| |
| elseif encoded_quality == 1 then
| |
| quality_as_text = "Maj."
| |
| elseif encoded_quality == 2 then
| |
| quality_as_text = "Aug."
| |
| elseif encoded_quality > 2 then
| |
| quality_as_text = (encoded_quality - 1) .. "× Aug."
| |
| elseif encoded_quality == -1 then
| |
| quality_as_text = "Min."
| |
| elseif encoded_quality == -2 then
| |
| quality_as_text = "Dim."
| |
| elseif encoded_quality < -2 then
| |
| quality_as_text = (math.abs(encoded_quality) - 1) .. "× Dim."
| |
| end
| |
| | |
| return quality_as_text
| |
| end
| |
| | |
| -- Helper function
| |
| -- Calcualtes the qualities of each scale degree given a mosstep pattern and input mos
| |
| -- Input mos is necessary for comparing step patterns with the true mos pattern, esp. with modmosses.
| |
| function p.calculate_mode_degrees(input_mos, mosstep_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2) | | local input_mos = input_mos or mos.new(5, 2) |
| local mosstep_pattern = mosstep_pattern or "LLsLLLs" | | local mos_prefix = mos_prefix or "mos" |
| | local is_collapsed = is_collapsed == true |
| | | |
| -- Get the number of mossteps per period | | -- Get the modes as strings and step vectors |
| local mossteps_per_equave = input_mos.nL + input_mos.ns | | local step_patterns = {} |
|
| | local step_matrices = {} |
| local mode_degrees = {} | | if is_true_mos then |
| for i = 1, mossteps_per_equave + 1 do | | step_patterns = mos.modes_by_brightness(input_mos) |
| local mossteps = i - 1 | | step_matrices = mos.modes_to_step_matrices(input_mos) |
|
| | else |
| local mosdegree_vector = p.convert_mosstep_pattern_to_mosstep_vector(mosstep_pattern, mossteps) | | step_patterns = mos.mode_rotations(step_pattern) |
| local encoded_mosdegree = p.calculate_mosstep_quality(input_mos, mosdegree_vector) | | step_matrices = mos.mode_rotations_to_step_matrices(step_pattern) |
| table.insert(mode_degrees, encoded_mosdegree) | |
| end | | end |
| | | |
| return mode_degrees | | -- Get the scale sig |
| end
| | local scale_sig = mos.as_string(input_mos) |
| | |
| -- Helper function
| |
| -- Calculate the UDP for each mode, given the modes are for the true
| |
| -- mos pattern and start at the brightest mode | |
| function p.calculate_mos_mode_brightness_order(input_mos)
| |
| local input_mos = input_mos or mos.new(5, 2) | |
|
| |
|
| -- Get the number of mossteps per period and equave, and periods per equave | | -- Equave step count; needed for degree column count |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns) | | local equave_step_count = mos.equave_step_count(input_mos) |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
| | | |
| -- Get the number of mossteps in the bright gen and dark gen | | -- Get the brightness (UDP) and rotational orderings (CPOs). |
| local bright_gen = mos.bright_gen(input_mos)
| | -- Also produce default mode names if set to do so. |
| local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s']
| | local udps = {} |
| | | local cpos = {} |
| -- For each scale degree within a single period of a step pattern,
| | if is_true_mos then |
| -- there is a unique mode. | | -- Get UDPs and CPOs |
| -- If the mos is single-period, then there are x+y unique modes.
| | udps = tamnams.mos_mode_udps(input_mos) |
| -- If the mos is multi-period nxL nys, then there are x+y modes instead
| | cpos = tamnams.mos_mode_cpos(input_mos) |
| -- of nx+ny modes due to repetition.
| | else |
| local number_of_modes = mossteps_per_period | | -- 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 |
| local number_of_gens_down = 0
| | -- closest-dark mode. If they're the same, only one name will be used; |
| local number_of_gens_up = mossteps_per_equave - periods_per_equave
| | -- if not, both are used. |
| local brightness_order = {} | | -- The CPOs of a modmos are simply 1 to n (n is the mode count). |
| for i = 1, mossteps_per_period do | | local udps_closest_bright = tamnams.mode_rotation_udps(step_pattern, input_mos, "m", true) |
| local current_udp = number_of_gens_up .. '|' .. number_of_gens_down
| | local udps_closest_dark = tamnams.mode_rotation_udps(step_pattern, input_mos, "m", false) |
| if periods_per_equave ~= 1 then
| | for i = 1, #udps_closest_bright do |
| current_udp = current_udp .. string.format("(%d)", periods_per_equave)
| | if udps_closest_bright[i] == udps_closest_dark[i] then |
| end
| | table.insert(udps, udps_closest_bright[i]) |
|
| | else |
| table.insert(brightness_order, current_udp)
| | table.insert(udps, string.format("%s<br />%s", udps_closest_bright[i], udps_closest_dark[i])) |
| number_of_gens_up = number_of_gens_up - periods_per_equave
| |
| number_of_gens_down = number_of_gens_down + periods_per_equave | |
| end
| |
| | |
| return brightness_order
| |
| end
| |
| | |
| -- Helper function
| |
| -- Calculate the rotational order for each mode, given the modes are
| |
| -- for the true mos pattern and start at the brightest mode
| |
| function p.calculate_mos_mode_rotational_order(input_mos)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| | |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps in the bright gen and dark gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s'] | |
| | |
| -- For each scale degree within a single period of a step pattern,
| |
| -- there is a unique mode.
| |
| -- If the mos is single-period, then there are x+y unique modes.
| |
| -- If the mos is multi-period nxL nys, then there are x+y modes instead
| |
| -- of nx+ny modes due to repetition.
| |
| local number_of_modes = mossteps_per_period
| |
| | |
| local bright_gens_up = 0
| |
| local rotational_order = {}
| |
| for i = 1, mossteps_per_period do
| |
| local current_mode_order = bright_gens_up % mossteps_per_period + 1
| |
| bright_gens_up = bright_gens_up + mossteps_per_bright_gen
| |
| table.insert(rotational_order, current_mode_order) | |
| end
| |
| | |
| return rotational_order
| |
| end
| |
| | |
| -- Calculate the rotations of a step pattern | |
| -- Modes can either be sorted by decreasing brightness or by leftward shifts (rotation)
| |
| -- This is meant to be used as a helper function for the following functions:
| |
| -- - calculate_mos_mode_degrees
| |
| -- - calculate_modmos_mode_degrees
| |
| function p.calculate_step_pattern_rotations(input_mos, mosstep_pattern, rotate_by_generator)
| |
| local input_mos = input_mos or mos.new(6, 4)
| |
| local mosstep_pattern = mosstep_pattern or "LLsLsLLsLs"
| |
| local rotate_by_generator = rotate_by_generator == true
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the amount to shift by
| |
| -- Shifting by the number of mossteps in the generator produces modes by
| |
| -- descending brightness; shifting by 1 produces them in rotational order
| |
| local shift_amount = 1
| |
| if rotate_by_generator then
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s']
| |
| shift_amount = mossteps_per_bright_gen
| |
| end
| |
|
| |
| local current_mode = mosstep_pattern
| |
| local rotations = {}
| |
| for i = 1, mossteps_per_equave do
| |
| if not p.find_item_in_table(rotations, current_mode) then | |
| table.insert(rotations, current_mode)
| |
| end
| |
|
| |
| -- Rotate current mode | |
| local first_substr = string.sub(current_mode, 1, shift_amount)
| |
| local second_substr = string.sub(current_mode, shift_amount + 1, mossteps_per_equave)
| |
| current_mode = second_substr .. first_substr | |
| end
| |
|
| |
| return rotations
| |
| end
| |
| | |
| -- Helper function
| |
| -- Calculate the scale degrees given an input mos and its modes
| |
| -- Modes can also be modmos modes
| |
| function p.calculate_mos_mode_degrees(input_mos, modes)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local modes = modes or p.calculate_step_pattern_rotations(input_mos, "LLLsLLs", true)
| |
|
| |
| -- Get the number of mossteps per period and equave
| |
| local mossteps_per_equave = input_mos.nL + input_mos.ns
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps per bright gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s']
| |
|
| |
| local mode_degrees = {}
| |
| for i = 1, #modes do
| |
| local current_mode_degrees = p.calculate_mode_degrees(input_mos, modes[i])
| |
| table.insert(mode_degrees, current_mode_degrees)
| |
| end
| |
|
| |
| return mode_degrees
| |
| end
| |
| | |
| -- Helper function
| |
| -- For a given modmos step pattern, find the closest true-mos mode and alterations
| |
| -- The mos and its modes in rotational order should also be passed in
| |
| -- This finds the closest mode for only the modmos's step pattern, not all rotations
| |
| -- Alterations are denoted as a UDP followed by which scale degrees are altered from the original mode
| |
| -- If multiple true-mos modes are tied with being closest, use the darkest mode instead
| |
| function p.compare_modmos_with_true_mos_modes(input_mos, true_mos_modes, modmos_step_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local true_mos_modes = true_mos_modes or p.calculate_step_pattern_rotations(mos.new(5, 2), "LLLsLLs", true)
| |
| local modmos_step_pattern = modmos_step_pattern or "sLsLLsA"
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the modmos's mosstep vectors to compare
| |
| local modmos_vector = p.calculate_mode_degrees(input_mos, modmos_step_pattern)
| |
| | |
| -- Compare each mode in the array of mos modes.
| |
| -- For each mode compared, count how many alterations there are. The mode
| |
| -- with the fewest alterations is the closest true mos mode.
| |
| local index_of_closest_mode = 1
| |
| local lowest_number_of_alterations = mossteps_per_equave
| |
| for i = 1, #true_mos_modes do
| |
| local number_of_alterations = 0
| |
|
| |
| -- Get the current mode's degree vector
| |
| local mode_vector = p.calculate_mode_degrees(input_mos, true_mos_modes[i])
| |
|
| |
| -- Compare the vectors
| |
| for j = 1, #true_mos_modes[i] do
| |
| if mode_vector[j] ~= modmos_vector[j] then
| |
| number_of_alterations = number_of_alterations + 1
| |
| end | | end |
| | table.insert(cpos, i) |
| end | | end |
|
| |
| -- If the current mode had fewer alterations, update
| |
| if number_of_alterations < lowest_number_of_alterations then
| |
| index_of_closest_mode = i
| |
| lowest_number_of_alterations = number_of_alterations
| |
| end
| |
|
| |
| -- If the current mode had the same number of alterations but is of a darker mode, update
| |
| --if number_of_alterations == lowest_number_of_alterations then
| |
| -- index_of_closest_mode = i
| |
| --end
| |
| end | | end |
| | | |
| -- Calculate the UDP of the closest mode | | -- Create table |
| local gens_down = (index_of_closest_mode - 1) * periods_per_equave | | local result = "{| class=\"wikitable sortable mw-collapsible center-2 center-3" |
| local gens_up = (mossteps_per_period - index_of_closest_mode) * periods_per_equave
| | .. (is_collapsed and " mw-collapsed\"" or "\"") .. "\n" |
| local udp_of_closest_mode = gens_up .. '|' .. gens_down
| |
| if periods_per_equave ~= 1 then
| |
| udp_of_closest_mode = udp_of_closest_mode .. string.format("(%d)", periods_per_equave) | |
| end
| |
|
| |
| -- Calculate alterations by comparing the modmos and the closest mode's degrees
| |
| local mode_vector = p.calculate_mode_degrees(input_mos, true_mos_modes[index_of_closest_mode])
| |
| local alterations = ""
| |
| for i = 1, #mode_vector do
| |
| if mode_vector[i] ~= modmos_vector[i] then
| |
| local encoded_degree = { ['Mossteps'] = i - 1, ['Quality'] = modmos_vector[i] }
| |
| local decoded_degree = mosnot.decode_mosstep_quality(encoded_degree, "m", "mosdegree", "abbreviated")
| |
| alterations = string.format("%s %s", alterations, decoded_degree)
| |
| end
| |
| end
| |
|
| |
| return udp_of_closest_mode .. alterations
| |
| end
| |
| | |
| -- Helper function
| |
| -- For a given modmos step pattern, find the closest true-mos mode and alterations for each modmos mode
| |
| function p.calculate_modmos_mode_alterations(input_mos, modmos_step_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local modmos_step_pattern = modmos_step_pattern or "LLLsLLs"
| |
| | | |
| -- Calculate the modes for the truemos and modmos | | -- Table's title |
| local true_mos_modes = p.calculate_step_pattern_rotations(input_mos, mos.brightest_mode(input_mos), true)
| | -- If it's for a modmos, add the step pattern |
| local modmos_modes = p.calculate_step_pattern_rotations(input_mos, modmos_step_pattern, false)
| | result = result .. "|+ style=\"font-size: 105%; white-space: nowrap;\" | " .. string.format("Scale degrees of the modes of %s", scale_sig) |
|
| | .. (is_true_mos and "\n" or string.format(" (%s)\n", step_pattern)) |
| -- Get each mode's alterations | | .. "|-\n" |
| local alterations = {}
| |
| for i = 1, #modmos_modes do
| |
| local alteration = p.compare_modmos_with_true_mos_modes(input_mos, true_mos_modes, modmos_modes[i])
| |
| table.insert(alterations, alteration)
| |
| end | |
|
| |
| return alterations
| |
| end
| |
| | |
| -- Helper function
| |
| -- Calculates row colors given precalculated degree vectors for each mode
| |
| function p.calculate_row_colors(input_mos, input_mode_vectors)
| |
| -- Default input mos and brightest/darkest true mos modes
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local brightest_true_mode = mos.brightest_mode(input_mos)
| |
| local darkest_true_mode = string.reverse(brightest_true_mode)
| |
|
| |
| -- Default input mode vectors
| |
| local input_mode_vectors = input_mode_vectors or p.calculate_mos_mode_degrees(input_mos, p.calculate_step_pattern_rotations(input_mos, brightest_true_mode, true))
| |
|
| |
| -- Brightest and darkest vectors
| |
| local brightest_vector = p.calculate_mode_degrees(input_mos, brightest_true_mode)
| |
| local darkest_vector = p.calculate_mode_degrees(input_mos, darkest_true_mode)
| |
|
| |
| local row_colors = {}
| |
| for i = 1, #input_mode_vectors do
| |
| local cell_colors = {}
| |
| for j = 1, #input_mode_vectors[i] do
| |
| if input_mode_vectors[i][j] == brightest_vector[j] and input_mode_vectors[i][j] == darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_perfect_size)
| |
| elseif input_mode_vectors[i][j] == brightest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_large_size)
| |
| elseif input_mode_vectors[i][j] == darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_small_size)
| |
| elseif input_mode_vectors[i][j] > brightest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_lg_altered_size)
| |
| elseif input_mode_vectors[i][j] < darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_sm_altered_size)
| |
| end
| |
| end
| |
| table.insert(row_colors, cell_colors)
| |
| end
| |
|
| |
| return row_colors
| |
| end
| |
| | |
| -- Create a table of a mos's degrees
| |
| function p._mos_mode_degrees(input_mos, mos_prefix, mode_names, use_default_mode_names)
| |
| 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
| |
| local step_patterns = mos.modes_by_brightness(input_mos)
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the scale sig
| |
| local scale_sig = mos.as_string(input_mos)
| |
|
| |
| -- Get the brightness and rotational orderings
| |
| -- UDP and rotational order
| |
| local brightness_order = p.calculate_mos_mode_brightness_order(input_mos)
| |
| local rotational_order = p.calculate_mos_mode_rotational_order(input_mos)
| |
|
| |
| -- Get step matrices for every mode
| |
| local step_matrices = mos.modes_to_step_matrices(input_mos)
| |
|
| |
| -- Get row colors
| |
| --local row_colors = p.calculate_row_colors(input_mos, step_matrices)
| |
|
| |
| -- Create table
| |
| local result = '{| class="wikitable sortable"\n'
| |
| local result = result .. string.format("|+ Scale degree qualities of %s modes\n", scale_sig)
| |
| | | |
| -- Add table headers for first row | | -- Add table headers for first row |
| result = result .. '! rowspan="2" | UDP\n' | | result = result |
| result = result .. '! rowspan="2" | Rotational Order\n'
| | .. "! rowspan=\"2\" | UDP" .. (is_true_mos and "\n" or " and<br />alterations\n") -- If modmos, add "and alterations" string |
| result = result .. '! rowspan="2" | Step pattern\n'
| | .. "! rowspan=\"2\" | Cyclic<br />order\n" |
|
| | .. "! rowspan=\"2\" | Step<br />pattern\n" |
| -- Add mode names if present
| |
| local mode_names_given = (mode_names ~= nil and #mode_names == #modes) or use_default_mode_names
| |
| if mode_names_given then
| |
| result = result .. '! rowspan="2" class="unsortable" | Mode names\n' | |
| end
| |
| | | |
| -- Add header for scale degrees | | -- Add header for scale degrees |
| result = result .. string.format('! colspan="%d" class="unsortable" | Scale degree (%sdegree)\n', mossteps_per_equave + 1, mos_prefix) | | result = result .. string.format("! colspan=\"%d\" class=\"unsortable\" | Scale degree (%sdegree)\n", #step_matrices[1], mos_prefix) |
| | | |
| -- Add second row of headers | | -- Add second row of headers |
| result = result .. "|-\n" | | result = result .. "|- class=\"unsortable\"\n" |
| for i = 1, mossteps_per_equave + 1 do | | .. "! 0" |
| result = result .. string.format('! class="unsortable" |%d\n', i-1) | | for i = 1, #step_patterns[1] do |
| | result = result .. string.format("\n! %d", i) |
| end | | end |
| | |
| | result = result .. "\n" |
| | | |
| -- Add table contents | | -- Add table contents |
| Line 609: |
Line 139: |
| | | |
| -- Add brightness order (as UDP), rotational order, and step pattern | | -- Add brightness order (as UDP), rotational order, and step pattern |
| result = result .. string.format('| %s\n| %s\n| %s\n', brightness_order[i], rotational_order[i], step_patterns[i])
| | .. string.format("| %s\n| %s\n| %s\n", 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\n', scale_sig, brightness_order[i])
| |
| else
| |
| result = result .. string.format('| %s\n', mode_names[i])
| |
| end
| |
| end
| |
|
| |
| -- Add scale degrees with cell coloring | | -- Add scale degrees with cell coloring |
| -- This includes period intervals bold and alterations italicized
| |
| for j = 1, #step_matrices[i] do | | for j = 1, #step_matrices[i] do |
| local degree_quality = tamnams.decode_quality(step_matrices[i][j], input_mos, "shortened") | | local current_interval = step_matrices[i][j] |
| result = result .. string.format('| %s\n', degree_quality) | | 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\n", style_code, degree_quality) |
| if row_colors[i][j] == p.cell_color_none then
| |
| result = result .. string.format('| %s\n', degree_quality)
| |
| elseif row_colors[i][j] == p.cell_color_lg_altered_size or row_colors[i][j] == p.cell_color_sm_altered_size then
| |
| result = result .. string.format('| style="background: #%s" | \'\'%s\'\'\n', row_colors[i][j], degree_quality)
| |
| else
| |
| result = result .. string.format('| style="background: #%s" | %s\n', row_colors[i][j], degree_quality)
| |
| end
| |
| ]]--
| |
| end
| |
| end
| |
|
| |
| -- End of table
| |
| result = result .. "|}"
| |
|
| |
| return result
| |
| end
| |
| | |
| -- Create a table of a modmos's degrees
| |
| function p._modmos_mode_degrees(input_mos, mos_prefix, step_pattern, mode_names, use_default_mode_names)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local mos_prefix = mos_prefix or "mos"
| |
| local step_pattern = step_pattern or "LsLLsAs"
| |
| local mode_names = mode_names or nil
| |
| local use_default_mode_names = use_default_mode_names == 1
| |
|
| |
| -- Get the modes
| |
| local modes = p.calculate_step_pattern_rotations(input_mos, step_pattern, false)
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the scale sig
| |
| local scale_sig = mos.as_string(input_mos)
| |
|
| |
| -- Get rotational orderings; modmossses shouldn't be ordered by brightness
| |
| local rotational_order = p.calculate_mos_mode_rotational_order(input_mos)
| |
|
| |
| -- Get closest mode and alterations
| |
| local alterations = p.calculate_modmos_mode_alterations(input_mos, step_pattern)
| |
|
| |
| -- Get mosstep vectors for all modes
| |
| local mosstep_vectors = p.calculate_mos_mode_degrees(input_mos, modes)
| |
|
| |
| -- Get row colors
| |
| local row_colors = p.calculate_row_colors(input_mos, mosstep_vectors)
| |
|
| |
| -- Create table
| |
| local result = '{| class="wikitable sortable"\n'
| |
| local result = result .. string.format("|+ Scale degree qualities of %s modes (step pattern of %s)\n", scale_sig, step_pattern)
| |
|
| |
| -- Add table headers for first row
| |
| result = result .. '! rowspan="2" | UDP and alterations\n'
| |
| result = result .. '! rowspan="2" | Rotational Order\n'
| |
| result = result .. '! rowspan="2" | Step pattern\n'
| |
|
| |
| -- Add mode names if present
| |
| local mode_names_given = (mode_names ~= nil and #mode_names == #modes) or use_default_mode_names
| |
| if mode_names_given then
| |
| result = result .. '! rowspan="2" class="unsortable" | Mode names\n'
| |
| end
| |
|
| |
| -- Add header for scale degrees
| |
| result = result .. string.format('! colspan="%d" class="unsortable" | Scale degree (%sdegree)\n', mossteps_per_equave + 1, mos_prefix)
| |
|
| |
| -- Add second row of headers
| |
| result = result .. "|-\n"
| |
| for i = 1, mossteps_per_equave + 1 do
| |
| result = result .. string.format('! class="unsortable" |%d\n', i-1)
| |
| end
| |
|
| |
| -- Add table contents
| |
| for i = 1, #modes do
| |
| result = result .. "|-\n"
| |
|
| |
| -- Add brightness order (as UDP), rotational order, and step pattern
| |
| result = result .. string.format('| %s\n| %s\n| %s\n', alterations[i], i, modes[i])
| |
|
| |
| -- Add mode name if given
| |
| if mode_names_given then
| |
| if use_default_mode_names then
| |
| result = result .. string.format('| %s %s\n', scale_sig, alterations[i])
| |
| else
| |
| result = result .. string.format('| %s\n', mode_names[i])
| |
| end
| |
| end
| |
|
| |
| -- Add scale degrees with cell coloring
| |
| -- This includes period intervals bold and alterations italicized
| |
| for j = 1, #mosstep_vectors[i] do
| |
| if row_colors[i][j] == p.cell_color_none then
| |
| result = result .. string.format('| %s\n', p.decode_quality(mosstep_vectors[i][j]))
| |
| elseif row_colors[i][j] == p.cell_color_lg_altered_size or row_colors[i][j] == p.cell_color_sm_altered_size then
| |
| result = result .. string.format('| style="background: #%s" | \'\'%s\'\'\n', row_colors[i][j], p.decode_quality(mosstep_vectors[i][j]))
| |
| else
| |
| result = result .. string.format('| style="background: #%s" | %s\n', row_colors[i][j], p.decode_quality(mosstep_vectors[i][j]))
| |
| end
| |
| end | | end |
| end | | end |
| Line 733: |
Line 157: |
| | | |
| return result | | return result |
|
| |
| end | | end |
|
| |
|
| -- Function to be called as part of a template | | -- Function to be called as part of a template |
| -- Note that there are two "main" functions: one for mosses, one for modmosses
| |
| -- Whichever is called is based on the step pattern entered
| |
| function p.mos_mode_degrees(frame) | | function p.mos_mode_degrees(frame) |
| -- Default param for input mos is 5L 2s | | -- Get args |
| local input_mos = mos.parse(frame.args['Scale Signature']) or mos.new(2, 5, 2) | | local input_mos = mos.parse(frame.args["Scale Signature"]) |
| | local mos_prefix = frame.args["MOS Prefix"] |
| | local step_pattern = frame.args["MODMOS Step Pattern"] |
| | local mode_names_unparsed = frame.args["Mode Names"] |
| | |
| | -- Parse debugging option |
| | local debugg = yesno(frame.args["debug"]) |
| | | |
| -- Get the scale sig; for calculating the mos prefix | | -- Get the scale sig; for calculating the mos prefix |
| local scale_sig = mos.as_string(input_mos) | | local scale_sig = mos.as_string(input_mos) |
| | | |
| -- Default param for mos prefix | | -- Verify mosprefix |
| -- If "NONE" is given, no prefix will be used | | mos_prefix = tamnams.verify_prefix(input_mos, mos_prefix) |
| -- 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 | | -- Get the mode names |
| local mode_names = nil | | local mode_names = nil |
| -- Default names for 5L 2s modes | | -- Default names for 5L 2s modes and select modmosses. |
| if scale_sig == "5L 2s" and step_pattern == "LsLLsAs" then | | -- Names are based on whichever mode is returnd by UDP closest-mode search, |
| mode_names = { "Harmonic minor", "Locrian #6", "Ionian augmented", "Dorian #4", "Phrygian dominant", "Lydian #2", "Locrian b4 bb7" }
| | -- with common names added wherever applicable. Sources include: |
| elseif scale_sig == "5L 2s" and #step_pattern == 0 then
| | -- - https://www.jazz-guitar-licks.com/ and likely others |
| mode_names = { "Lydian", "Ionian (major)", "Mixolydian", "Dorian", "Aeolian (minor)", "Phrygian", "Locrian" }
| | -- - 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 |
| | -- Closest-mode search always returns one name |
| | 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 ♭4 𝄫7)", |
| | } |
| | elseif step_pattern == "LLsLsAs" then |
| | -- Modes of harmonic major |
| | -- Closest-mode search always returns one name |
| | mode_names = { |
| | "Harmonic major<br />(Ionian ♭6)", |
| | "Dorian ♭5", |
| | "Phrygian ♭4", |
| | "Lydian ♭3", |
| | "Mixolydian ♭2", |
| | "Lydian augmented ♯2<br />(Lydian ♯2 ♯5)", |
| | "Locrian 𝄫7", |
| | } |
| | elseif step_pattern == "LsLLLLs" then |
| | -- Modes of melodic minor |
| | -- Closest-mode search sometimes returns two names |
| | mode_names = { |
| | "Melodic minor<br />(Ionian ♭3, Dorian ♮7)", |
| | "Dorian ♭2, Phrygian ♮6", |
| | "Lydian augmented<br />(Lydian ♯5)", |
| | "Lydian dominant<br />(Lydian ♭7, Mixolydian ♯4)", |
| | "Mixolydian ♭6, Aeolian ♮3", |
| | "Half-diminished<br />(Aeolian ♭5, Locrian ♮2)", |
| | "Altered, Altered dominant<br />(Locrian ♭4)", |
| | } |
| | elseif step_pattern == "sLLLLLs" then |
| | -- Modes of Neapolitan major |
| | -- Closest-mode search sometimes returns two names |
| | mode_names = { |
| | "Neapolitan major<br />(Ionian ♭2 ♭3, Phrigian ♮6 ♮7)", |
| | "Lydian augmented ♯6<br />(Lydian ♯5 ♯6)", |
| | "Lydian augmented dominant<br />(Lydian ♯5 ♭7, Mixolydian ♯4 ♯5)", |
| | "Lydian minor<br />(Lydian ♭6 ♭7, Aeolian ♮3 ♯4)", |
| | "Major locrian<br />(Mixolydian ♭5 ♭6, Locrian ♮2 ♮3)", |
| | "Altered dominant ♮2<br />(Aeolian ♭4 ♭5, Locrian ♮2, ♭4)", |
| | "Altered dominant 𝄫3<br />(Locrian 𝄫3 ♭4)", |
| | } |
| | elseif step_pattern == "sLLLsAs" then |
| | -- Modes of Neapolitan minor |
| | -- Closest-mode search always returns one name |
| | 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 𝄫3<br />(Locrian 𝄫3 ♭4 𝄫7)", |
| | } |
| | elseif step_pattern == "sAsLsAs" then |
| | -- Modes of double harmonic |
| | -- Closest-mode search sometimes returns two names |
| | mode_names = { |
| | "Double harmonic<br />(Ionian ♭2 ♭6, Phrygian ♮3 ♮7)", |
| | "Lydian ♯2 ♯6", |
| | "Altered ♮5 𝄫6<br />(Phrygian ♭4 𝄫7)", |
| | "Double harmonic minor<br />(Lydian ♭3 ♭6, Aeolian ♯4 ♮7)", |
| | "Mixolydian ♭2 ♭5, Locrian ♮3 ♮6", |
| | "Ionian augmented ♯2<br />(Ionian ♯2 ♯5)", |
| | "Locrian 𝄫3 𝄫7", |
| | } |
| | elseif #step_pattern == 0 then |
| | -- True-mos modes |
| | mode_names = { |
| | "Lydian", |
| | "Ionian (major)", |
| | "Mixolydian", |
| | "Dorian", |
| | "Aeolian (minor)", |
| | "Phrygian", |
| | "Locrian" |
| | } |
| | end |
| end | | end |
| | | |
| -- If mode names are given, use those instead | | -- If mode names are given, use those instead |
| -- If using default mode names (scalesig+udp), those names are auto-added by the relevant function | | -- If using default mode names (scalesig+udp), those names are auto-added by the relevant function |
| local use_default_names = 0 | | local use_default_names = false |
| if #frame.args['Mode Names'] ~= 0 then | | if #mode_names_unparsed ~= 0 then |
| if frame.args['Mode Names'] == "Default" then | | if mode_names_unparsed == "Default" then |
| use_default_names = 1 | | use_default_names = true |
| else | | else |
| mode_names = p.parse_entries(frame.args['Mode Names']) | | mode_names = tip.parse_entries(mode_names_unparsed) |
| end | | end |
| end | | end |
| | |
| | -- Check if the table should start collapsed |
| | local is_collapsed = yesno(frame.args["Collapsed"], false) |
| | | |
| -- If a modmos step pattern was never provided, call the function mos_mode_degrees | | -- If a modmos step pattern was never provided, call the function mos_mode_degrees |
| Line 789: |
Line 289: |
| local result = "" | | local result = "" |
| if step_pattern == "" then | | if step_pattern == "" then |
| result = p._mos_mode_degrees(input_mos, mos_prefix, mode_names, use_default_names) | | result = p._mos_mode_degrees(input_mos, mos_prefix, is_collapsed) |
| elseif #step_pattern == input_mos.nL + input_mos.ns then | | --elseif #step_pattern == input_mos.nL + input_mos.ns then |
| result = p._modmos_mode_degrees(input_mos, mos_prefix, step_pattern, mode_names, use_default_names) | | else |
| | result = p._mos_mode_degrees(input_mos, mos_prefix, is_collapsed, step_pattern) |
| | end |
| | |
| | -- Debugger option |
| | if debugg == true then |
| | result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" |
| end | | end |
| | | |
| return result | | return frame:preprocess(result) |
| end | | end |
|
| |
|
| return p | | return p |