Module:MOS: Difference between revisions

Ganaram inukshuk (talk | contribs)
Review code+comments as being its own documentation
Ganaram inukshuk (talk | contribs)
comment review
Line 10: Line 10:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Helper function
function p.find_item_in_table(table, item)
function p.find_item_in_table(table, item)
local item_found = false
local item_found = false
Line 26: Line 27:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Create a new mos. (Contains the number of large and small steps, and equave.)
-- Create a new mos as a table containing the counts for large and small steps,
-- plus the equave.
function p.new(nL, ns, equave)
function p.new(nL, ns, equave)
local nL = nL or 5
local nL = nL or 5
Line 35: Line 37:
end
end


-- Parse a mos from its scalesig.
-- Parse a mos from its scalesig "xL ys<p/q>" or "xL ys (p/q-equivalent)".
-- If no equave "p/q" is provided, it's assumed to be 2/1-equivalent.
function p.parse(unparsed)
function p.parse(unparsed)
local nL, ns, equave = unparsed:match("^(%d+)[Ll]%s*(%d+)[Ss]%s*(.*)$")
local nL, ns, equave = unparsed:match("^(%d+)[Ll]%s*(%d+)[Ss]%s*(.*)$")
Line 77: Line 80:
-- Degenerate mosses (nL 0s or 0L ns) produce a string for its corresponding
-- Degenerate mosses (nL 0s or 0L ns) produce a string for its corresponding
-- et (n-ed-p/q).
-- et (n-ed-p/q).
-- Option to use nbsp is provided using the second param; default is nbsp
-- Option to use nbsp is provided using the second param; default is nbsp.
function p.as_string(mos, use_nbsp)
function p.as_string(mos, use_nbsp)
if p.is_valid(mos) then
if p.is_valid(mos) then
Line 95: Line 98:
-- Degenerate mosses (nL 0s or 0L ns) produce a string for its corresponding
-- Degenerate mosses (nL 0s or 0L ns) produce a string for its corresponding
-- et (n-ed-p/q).
-- et (n-ed-p/q).
-- Option to use nbsp is provided using the second param; default is nbsp
-- Option to use nbsp is provided using the second param; default is nbsp.
function p.as_long_string(mos, use_nbsp)
function p.as_long_string(mos, use_nbsp)
if p.is_valid(mos) then
if p.is_valid(mos) then
Line 178: Line 181:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Find the parent mos of a mos. May return invalid mosses (nL 0s), meant
-- Find the parent mos of a mos. May return invalid mosses (nL 0s), meant to
-- to represent equal divisions of the octave (or arbitrary equave).
-- represent equal divisions of the octave (or arbitrary equave).
function p.parent(mos)
function p.parent(mos)
return p.new(math.min(mos.nL, mos.ns), math.abs(mos.nL-mos.ns), mos.equave)
return p.new(math.min(mos.nL, mos.ns), math.abs(mos.nL-mos.ns), mos.equave)
Line 292: Line 295:
end
end


-- List all unique rotations for a mode, by order of leftward shifts.
-- List all unique rotations for a mode, by order of leftward shifts. Order by
-- rotation will usually give a different order compared to order by brightness,
-- but this is expected if the order isn't by brightness (EG, modmosses).
-- Note: there will always be s/p modes, where s is the number of steps in the
-- Note: there will always be s/p modes, where s is the number of steps in the
-- entered mode, and p is the period of repetition. At most, there will be s
-- entered mode, and p is the period of repetition. At most, there will be s
Line 395: Line 400:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Compute the bright gen as a vector of L's and s's.
-- Compute the bright gen as a vector of L's and s's. Since all mosstep
-- Bright gen has two sizes: perfect (large) and diminished (small). The size
-- intervals (excluding the root and period) have two sizes, this returns the
-- given by this function is the large size.
-- large/perfect size.
function p.bright_gen(mos)
function p.bright_gen(mos)
local nL = mos.nL
local nL = mos.nL
Line 428: Line 433:
end
end


-- Compute the dark gen as a vector of L's and s's.
-- Compute the dark gen as a vector of L's and s's. Since all mosstep
-- Dark gen has two sizes: augmented (large) and perfect (small). The size given
-- intervals (excluding the root and period) have two sizes, this returns the
-- by this function is the small size and is equal to the period complement of the
-- small/perfect size.
-- bright gen.
function p.dark_gen(mos)
function p.dark_gen(mos)
local bright_gen = p.bright_gen(mos)
local bright_gen = p.bright_gen(mos)
Line 437: Line 441:
end
end


-- Compute the period as a vector of L's and s's. Period intervals only have one size: perfect.
-- Compute the period as a vector of L's and s's.
-- Period intervals as mossteps only appear as one size.
function p.period(mos)  
function p.period(mos)  
local gcd = utils._gcd(mos.nL, mos.ns)
local gcd = utils._gcd(mos.nL, mos.ns)
Line 447: Line 452:


-- Compute the equave as a vector of L's and s's.
-- Compute the equave as a vector of L's and s's.
-- Equave intervals only have one size: perfect. Equave and period intervals are
-- Equaves as mossteps only appear as one size. For a single-period mos, this
-- the same for single-period mosses.
-- is the same as p.period().
function p.equave(mos)  
function p.equave(mos)  
return {
return {
Line 460: Line 465:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Compute the unison as a vector of L's and s's.
-- Return the unison as a vector of L's and s's.
-- The unison is denoted by moving up from the root by zero steps, and thus does
-- The unison is denoted by moving up from the root by zero steps, and thus does
-- not need a mos as input. It's basically a zero vector.
-- not need a mos as input. It's basically a zero vector.
Line 468: Line 473:
end
end


-- Compute the vector for a single chroma. It's a large step minus a small step.
-- Return the vector for a single chroma. It's a large step minus a small step.
-- Adding or subtracting any interval by this interval changes its "size".
-- Adding or subtracting any interval by this interval changes its "size".
function p.chroma()
function p.chroma()
Line 474: Line 479:
end
end


-- Compute the vector for an augmented step. It's a large step plus a chroma.
-- Return the vector for an augmented step. It's a large step plus a chroma.
function p.augmented_step()
function p.augmented_step()
return { ["L"] = 2, ["s"] = -1 }
return { ["L"] = 2, ["s"] = -1 }
end
end


-- Compute the vector for a single large step.
-- Return the vector for a single large step.
function p.large_step()
function p.large_step()
return { ["L"] = 1, ["s"] = 0 }
return { ["L"] = 1, ["s"] = 0 }
end
end


-- Compute the vector for a single small step.
-- Return the vector for a single small step.
function p.small_step()
function p.small_step()
return { ["L"] = 0, ["s"] = 1 }
return { ["L"] = 0, ["s"] = 1 }
end
end


-- Compute the vector for a diminished step. It's a small step minus a chroma.
-- Return the vector for a diminished step. It's a small step minus a chroma.
function p.diminished_step()
function p.diminished_step()
return { ["L"] = -1, ["s"] = 2 }
return { ["L"] = -1, ["s"] = 2 }
Line 503: Line 508:
end
end


-- Compute an arbitrary mos interval as a vector of L's and s's.
-- Compute an arbitrary mos interval as a vector of L's and s's. Params:
-- The step_count param is the number of mossteps in the interval. EG, in 5L 2s,
-- - step_count: the number of steps subtended by the mosstep.
-- the large 2-mosstep is "LL", so the corresponding vector has L=2, s=0.
-- - size_offset: denotes whether to return the large size (0) or the small
-- Mossteps larger than the equave (eg, the minor 9th in non-xen music theory)
--   size (-1) (or if this is a period interval, the diminished size). Values
-- are allowed.
--   other than 0 or 1 represent alterations by multiple chromas, such as
-- The size_offset denotes whether the interval is the large size (0) or the
--   augmented (1) or diminished (-2).
-- small size (-1). This can exceed the range of [-1, 0] to represent intervals
-- raised/lowered by multiple chromas (augmented, diminished, etc).
-- Note that for period intervals (eg, the root and equave), there is only one
-- size (0 = perfect), so -1 is diminished and 1 is augmented.
-- E.G., a perfect 4-diastep (perf. 5th) is 4 steps. Since it's the large size,
-- the offset is 0, but to get the diminished 5th, the offset should be -1.
function p.interval_from_mos(mos, step_count, size_offset)
function p.interval_from_mos(mos, step_count, size_offset)
local size_offset = size_offset or 0 -- Optional param; defaults to large size
local size_offset = size_offset or 0 -- Optional param; defaults to large size
Line 599: Line 598:
-- perfect size (for period/root/equave intervals). This requires the mos as
-- perfect size (for period/root/equave intervals). This requires the mos as
-- input.
-- input.
-- If the number of chromas from a small (EG minor) interval is desired, then
-- size_offset denotes whether to count chromas from the large size; changing
-- using the param size_offset can be used: 0 for chromas from large size, -1
-- this to -1 counts chromas from the small size. Like size_offset for
-- for chromas from small size. This can exceed the range [-1, 0] if needed.
-- interval_from_mos, this can be used to denote altered mossteps (augmented,
-- E.G., a diminished 2-diastep (dim. 3rd) has the vector {0,2}. It's reached by
-- diminished, etc).
-- either lowering the major 2-step by 2 chromas, or lowering the minor 2-step
-- by 1 chroma.
function p.interval_chroma_count(interval, mos, size_offset)
function p.interval_chroma_count(interval, mos, size_offset)
local size_offset = size_offset or 0 -- Default of 0.
local size_offset = size_offset or 0 -- Default of 0.
Line 633: Line 630:
end
end


-- Repeatedly add the same interval to itself.
-- Stack an interval, or repeatedly add the same interval to itself.
function p.interval_mul(interval, amt)
function p.interval_mul(interval, amt)
return {  
return {