Module:MOS: Difference between revisions
Fleshed out module; basically redefining module:mos as a module for doing mos arithmetic, with tamnams-related things being moved to module:tamnams |
Comments; organization |
||
| Line 1: | Line 1: | ||
-- Module for working with mosses in code, | -- Module for working with mosses in lua code; this serves as a "library" for | ||
-- mos-related modules and thus does not have a corresponding template. | |||
-- Functionality includes: | |||
-- - Creating/parsing mosses | |||
-- - Creating scalesigs (string representations) of mosses | |||
-- - Finding certain modes of a mos | |||
-- - Finding generators for a mos | |||
-- - Interval arithmetic, in the form of adding vectors of L's and s's | |||
local rat = require('Module:Rational') | local rat = require('Module:Rational') | ||
local utils = require('Module:Utils') | local utils = require('Module:Utils') | ||
local et = require('Module:ET') | local et = require('Module:ET') -- Used for unused function | ||
local p = {} | local p = {} | ||
| Line 18: | Line 25: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Create a new mos. | ||
function p.new(nL, ns, equave) | function p.new(nL, ns, equave) | ||
local nL = nL or 5 | local nL = nL or 5 | ||
| Line 26: | Line 33: | ||
end | end | ||
-- | -- Pasre a mos from its scalesig. | ||
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 43: | Line 50: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Construct a string representation (scalesig) for a MOS structure | -- Construct a string representation (scalesig) for a MOS structure. | ||
-- Scalesig is "xL ys", or "xL ys<p/q>" for nonoctave scales | -- Scalesig is "xL ys", or "xL ys<p/q>" for nonoctave scales. | ||
function p.as_string(mos) | function p.as_string(mos) | ||
local suffix = '' | local suffix = '' | ||
| Line 53: | Line 60: | ||
end | end | ||
-- Construct a longer string representation for a MOS structure | -- Construct a longer string representation for a MOS structure. | ||
-- Scalesig is "xL ys", or "xL ys (p/q-equivalent)" for nonoctave scales | -- Scalesig is "xL ys", or "xL ys (p/q-equivalent)" for nonoctave scales. | ||
function p.as_long_string(mos) | function p.as_long_string(mos) | ||
local suffix = '' | local suffix = '' | ||
| Line 64: | Line 71: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
--------------- | ------------------------------- MODE FUNCTIONS --------------------------------- | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Find the brightest mode of a mos | -- Find the brightest true-mos mode of a mos. | ||
-- | -- Calculation is based on the definition of a Christoffel word, as the closest | ||
-- integer approximation to line y = #s/#L*x. | |||
function p.brightest_mode(mos) | function p.brightest_mode(mos) | ||
local nL = mos.nL | local nL = mos.nL | ||
| Line 92: | Line 99: | ||
end | end | ||
-- Find the darkest mode of a mos | -- Find the darkest true-mos mode of a mos. | ||
-- It's the reverse of the brightest mode | -- It's the reverse of the brightest mode. | ||
function p.darkest_mode(mos) | function p.darkest_mode(mos) | ||
local nL = mos.nL | local nL = mos.nL | ||
| Line 116: | Line 123: | ||
end | end | ||
-- | -------------------------------------------------------------------------------- | ||
--------------- INTERVAL FUNCTIONS FOR PERFECTABLE INTERVALS ------------------- | |||
------------------ (IE, GENERATORS AND PERIOD INTERVALS) ----------------------- | |||
-------------------------------------------------------------------------------- | |||
-- | |||
-- 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. | ||
| Line 174: | Line 167: | ||
} | } | ||
return dark_gen | return dark_gen | ||
end | |||
-- Compute the period as a vector of L's and s's. | |||
function p.period(mos) | |||
local gcd = utils._gcd(mos.nL, mos.ns) | |||
local result = { | |||
['L'] = mos.nL / gcd, | |||
['s'] = mos.ns / gcd | |||
} | |||
return result | |||
end | |||
-- Compute the equave as a vector of L's and s's. | |||
function p.equave(mos) | |||
local result = { | |||
['L'] = mos.nL, | |||
['s'] = mos.ns | |||
} | |||
return result | |||
end | end | ||
| Line 181: | Line 193: | ||
-- 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. | ||
-- The | -- The step_count param is the number of mossteps in the interval. EG, in 5L 2s, | ||
-- the large 2-mosstep is "LL", so the corresponding vector has L=2, s=0. | -- the large 2-mosstep is "LL", so the corresponding vector has L=2, s=0. | ||
-- Mossteps larger than the equave (analogous to the minor 9th in standard | -- Mossteps larger than the equave (analogous to the minor 9th in standard | ||
| Line 190: | Line 202: | ||
-- Note that for period intervals (eg, the root and equave), there is only one | -- 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. | -- size (0 = perfect), so -1 is diminished and 1 is augmented. | ||
function p.interval(mos, | function p.interval(mos, step_count, size) | ||
local size = size or 0 -- Optional param; defaults to large size, or perfect size | |||
local step_sequence = p.brightest_mode(mos) | local step_sequence = p.brightest_mode(mos) | ||
step_sequence = string.rep(step_sequence, math.ceil( | step_sequence = string.rep(step_sequence, math.ceil(step_count/(mos.nL + mos.ns))) | ||
step_sequence = string.sub(step_sequence, 1, | step_sequence = string.sub(step_sequence, 1, step_count) | ||
local interval_vector = p.interval_from_step_sequence(mos, step_sequence) | local interval_vector = p.interval_from_step_sequence(mos, step_sequence) | ||
| Line 203: | Line 216: | ||
-- Compute an arbitrary mos interval (as a string of steps) as a vector of L's | -- Compute an arbitrary mos interval (as a string of steps) as a vector of L's | ||
-- and s's. This also serves as a helper function for p.interval(). | -- and s's. This also serves as a helper function for p.interval(). | ||
-- This | -- This operates similarly to the above function, except arbitrary strings can | ||
-- be entered, such as with step sequences for certain modmosses. The step types | -- be entered, such as with step sequences for certain modmosses. The step types | ||
-- are as follows: | -- are as follows: | ||
| Line 268: | Line 281: | ||
} | } | ||
return interval_vector | return interval_vector | ||
end | |||
function p.period_complement(mos, v1) | |||
end | |||
function p.equave_complement(mos, v1) | |||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
--------- INTERVAL STEP COUNT FUNCTIONS | ----------------------- INTERVAL STEP COUNT FUNCTIONS -------------------------- | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Given a mos, compute the size of the bright gen in mossteps (L's plus s's). | ||
function p.bright_gen_step_count(mos) | |||
local interval = p.bright_gen(mos) | |||
return interval['L'] + interval['s'] | |||
end | |||
-- Given a mos, compute the size of the dark gen in mossteps (L's plus s's). | |||
function p.dark_gen_step_count(mos) | |||
local interval = p.dark_gen(mos) | |||
return interval['L'] + interval['s'] | |||
end | |||
-- Given a mos, compute the size of the period in mossteps (L's plus s's). | |||
function p.period_step_count(mos) | function p.period_step_count(mos) | ||
local interval = p.period(mos) | local interval = p.period(mos) | ||
| Line 280: | Line 311: | ||
end | end | ||
-- | -- Given a mos, compute the size of the equave in mossteps (L's plus s's). | ||
function p.equave_step_count(mos) | function p.equave_step_count(mos) | ||
local interval = p.equave(mos) | local interval = p.equave(mos) | ||
| Line 286: | Line 317: | ||
end | end | ||
-- Compute the | -- Compute the k-mosstep corresponding to a vector of L's and s's. | ||
-- This does not require the mos it corresponds to. | |||
function p.interval_step_count(interval) | |||
-- | |||
function p. | |||
return interval['L'] + interval['s'] | return interval['L'] + interval['s'] | ||
end | end | ||