Module:MOS: Difference between revisions

Inthar (talk | contribs)
No edit summary
Inthar (talk | contribs)
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(mos)
function p.brightest_mode(n_L, n_s)
local nL, ns, equave = mos.nL, mos.ns, mos.equave
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
return string.rep(p.brightest_mode(MOS.new(nL/d, ns/d, p.backslash_ratio(ET.new(d, equave, nil), 1))), d)
nL = round(nL/d)
else
ns = round(ns/d)
current_nL, current_ns = nL, ns
end
local path_to_root = {}
current_nL, current_ns = nL, ns
local i = 1 -- for indexing into path_to_root while building it
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
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")
assert(current_nL ~= current_ns, "current_nL == current_ns")
path_to_root[i] = {[1] = current_nL, [2] = current_ns}
table.insert(path_to_root, {[1] = current_nL, [2] = current_ns})
i = i + 1
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
current_nL = math.min(nL, ns) -- parent's nL
end
current_ns = math.max(nL, ns)-math.min(nL, ns) -- parent's ns
assert(current_nL == 1 and current_ns == 1, "Did not reach root successfully")
end
local len_of_path = table.getn(path_to_root)
local len_of_path = table.getn(path_to_root)
assert(len_of_path >= 0)
local result = 'Ls'
local result = 'Ls'
for j in len_of_path, 1, -1 do
for j = len_of_path, 1, -1 do
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2]
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2]
local L_becomes = ''
if child_nL > child_ns then -- this will give darkest mode, reverse for brightest mode
local s_becomes = ''
result = string.gsub(result, '[Ls]', {['L'] = 'sL', ['s'] = 'L'})
if child_nL > child_ns then -- this will give darkest mode
result = string.reverse(result)
L_becomes = 'sL'
else
s_becomes = 'L'
result = string.gsub(result, '[Ls]', {['L'] = 'Ls', ['s'] = 's'})
else
L_becomes = 'Ls'
s_becomes = 's'
end
local replace_with = {['L'] = L_becomes, ['s'] = s_becomes}
result = string.gsub(result, '[Ls]', replace_with)
if child_nL > child_ns then -- reverse for brightest mode
result = string.reverse(result)
end
end
end
return result
end
end
return string.rep(result, d)
end
end


function p.bright_gen(mos) -- Compute the abstract bright generator as a "vector" of L and s steps.
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, ns, equave = mos.nL, mos.ns, mos.equave
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
return string.rep(p.bright_gen(MOS.new(nL/d, ns/d, p.backslash_ratio(ET.new(d, equave, nil), 1))), d)
nL = round(nL/d)
else
ns = round(ns/d)
current_nL, current_ns = nL, ns
end
local path_to_root = {}
current_nL, current_ns = nL, ns
local i = 1 -- for indexing into path_to_root while building it
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
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")
assert(current_nL ~= current_ns, "current_nL == current_ns")
path_to_root[i] = {[1] = current_nL, [2] = current_ns}
table.insert(path_to_root, {[1] = current_nL, [2] = current_ns})
i = i + 1
current_nL, current_ns = math.min(current_nL, current_ns), math.max(current_nL, current_ns)-math.min(current_nL, current_ns)
current_nL = math.min(nL, ns) -- parent's nL
end
current_nL = math.max(nL, ns)-math.min(nL, ns) -- parent's ns
local len_of_path = table.getn(path_to_root)
end
local result = {['L'] = 1, ['s'] = 0} -- Record the previous bright gen; the bright gen of 1L 1s is 1L + 0s.
local len_of_path = table.getn(path_to_root)
for j = len_of_path, 1, -1 do
local result = {['L'] = 1, ['s'] = 0, ['equave'] = equave} -- Record the previous bright gen; the bright gen of 1L 1s is 1L + 0s.
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2]
for j in len_of_path, 1, -1 do
if child_nL > child_ns then  
local child_nL, child_ns = path_to_root[j][1], path_to_root[j][2]
-- The old bright gen will now be the dark gen, take equave complement for the new bright gen.
if child_nL > child_ns then  
-- new L = old s.
-- The old bright gen will now be the dark gen, take equave complement for the new bright gen.
-- The # of new L's in (now dark) generator is # of old L's + # of old s's;
-- new L = old s.
-- the # of new s's in it is the # of old L's.
-- The # of new L's in (now dark) generator is # of old L's + # of old s's;
result = {['L'] = child_nL - (result['L'] + result['s']), ['s'] = child_ns - result['L']}
-- the # of new s's in it is the # of old L's.
else -- The old bright gen will stay bright.
result = {['L'] = child_nL - (result['L'] + result['s']), ['s'] = child_ns - result['L'], equave}
-- new s = old s.
else -- The old bright gen will stay bright.
-- The # of new L's in the generator is # of old L's;
-- new s = old s.
-- the # of new s's in it is # of old L's + # of new s's.
-- The # of new L's in the generator is # of old L's;
result = {['L'] = result['L'], ['s'] = result['L'] + result['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'], equave}
end
end
end
return result
end
end
return result
end
end


return p
return p