Module:MOS degrees: Difference between revisions
mNo edit summary |
Added a new function as part of a future rewrite |
||
| Line 47: | Line 47: | ||
return { num, den } | return { num, den } | ||
end | |||
-- Function that produces a chain of scale degrees. If the genchain function | |||
-- from the module mos gamut were read as scale degrees, what would they be? | |||
-- (EG, major 2nd, augmented 2nd, etc) | |||
-- TODO: part of a rewrite for the mos degrees function | |||
function p.mos_degreechain(input_mos, genchain_length_per_period, going_up) | |||
-- Default parameters for testing | |||
local input_mos = input_mos or mos.new(6, 2, 2) | |||
local genchain_length_per_period = genchain_length_per_period or 10 | |||
local going_up = true | |||
-- Get the number of mossteps per period and equave | |||
local mossteps_per_equave = input_mos.nL + input_mos.ns | |||
local periods_per_equave = rat.gcd(input_mos.nL, input_mos.ns) | |||
local mossteps_per_period = mossteps_per_equave / periods_per_equave | |||
-- The easiest way to get scale degrees is through the following method: | |||
-- - Get the genchain corresponding to the second-brightest mode and | |||
-- interpret the result as scale degrees. | |||
-- - If this is the ascending chain, then this represents every interval | |||
-- class' large size. For each period, the first two elements represent | |||
-- the root (perfect) and bright generator (large size is perfect). | |||
-- - If this is the descending chain, then find the period complement of | |||
-- each element, which represents every interval class's small size. | |||
-- For each period, the first two elements represent the root (perfect) | |||
-- and dark generator (small size is perfect). | |||
-- - Since the root and generators start as perfect, anything beyond that | |||
-- represents augmented/diminished unisons/generators. | |||
-- Note that this is agnostic of notation, so only the genchain length is | |||
-- needed. The UDP for the second-brightest mode is auto-calculated and is | |||
-- used regardless of whether the chain is going up or down. | |||
local genchain = mosg.mos_genchain(input_mos, mossteps_per_period - 2, genchain_length_per_period, true) | |||
-- Interpret as scale degrees | |||
-- The first two elements are always perfect. | |||
-- 0 chromas are major (or minor if descending) | |||
-- 1 chroma is augmented, negative for diminished | |||
-- n chromas is n-times augmented, negative for diminished | |||
local degreechain = {} | |||
for j = 1, periods_per_equave do | |||
local chain_for_period = {} | |||
for i = 1, #genchain[j] do | |||
local note = genchain[j][i] | |||
local mossteps = note['mossteps'] | |||
local chromas = note['chromas'] | |||
-- If not going up, use the period complements instead | |||
-- Period complements of the root will end up being the note one | |||
-- period up, so use modular arithmetic to keep the starting point | |||
-- constrained to the root | |||
local aug_or_dim = "augmented" | |||
local maj_or_min = "major" | |||
if not going_up then | |||
mossteps = (j - 1) * mossteps_per_period + (mossteps_per_period - mossteps) % mossteps_per_period | |||
aug_or_dim = "diminished" | |||
maj_or_min = "minor" | |||
end | |||
local quality = "" | |||
if i == 1 then | |||
quality = "perfect" | |||
elseif i == 2 then | |||
quality = "perfect" | |||
else | |||
if chromas == 0 then | |||
quality = maj_or_min | |||
elseif chromas == 1 then | |||
quality = aug_or_dim | |||
else | |||
quality = chromas .. "×" .. aug_or_dim | |||
end | |||
end | |||
local degree = quality .. " " .. mossteps .. "-mosstep" | |||
table.insert(chain_for_period, degree) | |||
end | |||
table.insert(degreechain, chain_for_period) | |||
end | |||
return degreechain | |||
end | end | ||