Module:MOS: Difference between revisions
No edit summary |
No edit summary |
||
| Line 10: | Line 10: | ||
local equave = equave or 2 | local equave = equave or 2 | ||
return { nL = nL, ns = ns, equave = equave } | return { nL = nL, ns = ns, equave = equave } | ||
end | |||
function round(num, numDecimalPlaces) | |||
local mult = 10^(numDecimalPlaces or 0) | |||
return math.floor(num * mult + 0.5) / mult | |||
end | end | ||
| Line 36: | Line 41: | ||
-- Find the brightest mode of a mos. | -- Find the brightest mode of a mos. | ||
-- We go back to the root of the scale tree, then progressively construct descendants. | -- We go back to the root of the scale tree, then progressively construct descendants. | ||
function p.brightest_mode( | function p.brightest_mode(n_L, n_s) | ||
local nL | local nL = n_L | ||
local ns = n_s | |||
local d = rat.gcd(nL, ns) | local d = rat.gcd(nL, ns) | ||
if d > 1 then -- use single period mos, with period as new equave | if d > 1 then -- use single period mos, with period as new equave | ||
nL = round(nL/d) | |||
ns = round(ns/d) | |||
end | |||
current_nL, current_ns = nL, ns | |||
local path_to_root = {} | |||
while current_nL > 1 or current_ns > 1 do -- while current mos is not 1L 1s<equave>, record current mos and go up to parent | |||
assert(current_nL ~= current_ns, "current_nL == current_ns") | |||
table.insert(path_to_root, {[1] = current_nL, [2] = current_ns}) | |||
current_nL, current_ns = math.min(current_nL, current_ns), math.max(current_nL, current_ns)-math.min(current_nL, current_ns) -- parent's nL and ns | |||
end | |||
assert(current_nL == 1 and current_ns == 1, "Did not reach root successfully") | |||
local len_of_path = table.getn(path_to_root) | |||
assert(len_of_path >= 0) | |||
local result = 'Ls' | |||
for j = len_of_path, 1, -1 do | |||
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2] | |||
if child_nL > child_ns then -- this will give darkest mode, reverse for brightest mode | |||
result = string.gsub(result, '[Ls]', {['L'] = 'sL', ['s'] = 'L'}) | |||
result = string.reverse(result) | |||
else | |||
result = string.gsub(result, '[Ls]', {['L'] = 'Ls', ['s'] = 's'}) | |||
result = string.gsub(result, '[Ls]', | |||
end | end | ||
end | end | ||
return string.rep(result, d) | |||
end | end | ||
function p.bright_gen( | function p.bright_gen(n_L, n_s) -- Compute the abstract, equave-agnostic bright generator as a "vector" of L and s steps. | ||
local nL | local nL = n_L | ||
local ns = n_s | |||
local d = rat.gcd(nL, ns) | local d = rat.gcd(nL, ns) | ||
if d > 1 then -- use single period mos, with period as new equave | if d > 1 then -- use single period mos, with period as new equave | ||
nL = round(nL/d) | |||
ns = round(ns/d) | |||
end | |||
current_nL, current_ns = nL, ns | |||
local path_to_root = {} | |||
while current_nL > 1 or current_ns > 1 do -- while current mos is not 1L 1s, record current mos and go up to parent | |||
assert(current_nL ~= current_ns, "current_nL == current_ns") | |||
table.insert(path_to_root, {[1] = current_nL, [2] = current_ns}) | |||
current_nL, current_ns = math.min(current_nL, current_ns), math.max(current_nL, current_ns)-math.min(current_nL, current_ns) | |||
end | |||
local len_of_path = table.getn(path_to_root) | |||
local result = {['L'] = 1, ['s'] = 0} -- Record the previous bright gen; the bright gen of 1L 1s is 1L + 0s. | |||
for j = len_of_path, 1, -1 do | |||
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2] | |||
if child_nL > child_ns then | |||
-- The old bright gen will now be the dark gen, take equave complement for the new bright gen. | |||
-- new L = old s. | |||
-- The # of new L's in (now dark) generator is # of old L's + # of old s's; | |||
-- the # of new s's in it is the # of old L's. | |||
result = {['L'] = child_nL - (result['L'] + result['s']), ['s'] = child_ns - result['L']} | |||
else -- The old bright gen will stay bright. | |||
-- new s = old s. | |||
-- The # of new L's in the generator is # of old L's; | |||
-- the # of new s's in it is # of old L's + # of new s's. | |||
result = {['L'] = result['L'], ['s'] = result['L'] + result['s']} | |||
end | end | ||
end | end | ||
return result | |||
end | end | ||
return p | return p | ||