Module:MOS: Difference between revisions

Ganaram inukshuk (talk | contribs)
Added function for making arbitrary intervals; renamed interval() to interval_from_mos() to be more descriptive
Ganaram inukshuk (talk | contribs)
Reclassify functions; added mode rotation function; added arbitrary mode function; added function to negate an interval; simplified code for a few cent functions
Line 117: Line 117:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Find the brightest (true-mos) mode of a mos.
-- Find the brightest (true-mos) mode of a mos, as a string of L's and s's.
-- Calculation is based on the definition of a Christoffel word, as the closest
-- Calculation is based on the definition of a Christoffel word, as the closest
-- integer approximation to line y = #s/#L*x.
-- integer approximation to line y = #s/#L*x.
Line 164: Line 164:
end
end
return string.rep(result, d)
return string.rep(result, d)
end
-- Given a mos, return a mode based on how it's ranked by modal brightness.
-- 0 is brightest, 1 is 2nd-brightest, 2 is 3rd-brightest, etc... These values
-- can be thought of as rotate amounts (for p.rotate_mode()), where the size of
-- the bright gen is a multiplier, so the kth brightest mode rotates the
-- brightest mode k * g times (where g is the size of the generator).
function p.mode_from_mos(mos, brightness)
return p.rotate_mode(p.brightest_mode(mos), brightness * p.bright_gen_step_count(mos))
end
-- Rotate a mode by shifting the step sequence to the left. Negative values
-- shift it to the right. Helper function for mode_from_mos().
function p.rotate_mode(mode_string, shift_amt)
local shift_amt = shift_amt % #mode_string
local first = string.sub(mode_string, 1, shift_amt)
local second = string.sub(mode_string, shift_amt + 1, #mode_string)
return second .. first
end
end


Line 332: Line 350:
return interval_vector
return interval_vector
end
-- Intervals usually denote distances between two scale degrees and should be
-- positive values. Normalizing makes a negative interval positive again.
function p.normalize_interval(interval)
return p.interval_step_count(interval) < 0 and p.interval_mul(interval, -1) or interval
end
end


Line 424: Line 436:


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
---------------------- COMPLEMENT AND REDUCE FUNCTIONS -------------------------
---------------------- INTERVAL MANIPULATION FUNCTIONS -------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


Line 461: Line 473:
return p.interval_sub(interval, equaves)
return p.interval_sub(interval, equaves)
end
-- Invert an interval. This makes an interval negative.
function p.invert_interval(interval)
return p.interval_mul(interval, -1)
end
-- Intervals usually denote distances between two scale degrees and should be
-- positive values. Normalizing makes a negative interval positive again.
function p.normalize_interval(interval)
return p.interval_step_count(interval) < 0 and p.interval_mul(interval, -1) or interval
end
end


Line 508: Line 531:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


-- Given a mos and a step ratio, return the number of cents for its bright
-- Given a mos and a step ratio, return the number of cents for its bright gen.
-- generator.
function p.bright_gen_to_cents(mos, step_ratio)
function p.bright_gen_to_cents(mos, step_ratio)
local interval_steps = p.interval_to_et_steps(p.bright_gen(mos), step_ratio)
local interval_steps = p.interval_to_et_steps(p.bright_gen(mos), step_ratio)
Line 516: Line 538:
end
end


-- Given a mos and a step ratio, return the number of cents for its dark
-- Given a mos and a step ratio, return the number of cents for its dark gen.
-- generator.
function p.dark_gen_to_cents(mos, step_ratio)
function p.dark_gen_to_cents(mos, step_ratio)
local interval_steps = p.interval_to_et_steps(p.dark_gen(mos), step_ratio)
local interval_steps = p.interval_to_et_steps(p.dark_gen(mos), step_ratio)
Line 525: Line 546:


-- Given a mos and a step ratio, return the number of cents for its period.
-- Given a mos and a step ratio, return the number of cents for its period.
function p.period_to_cents(mos, step_ratio)
-- The period is the interval at which the step pattern repeats, so no step
local interval_steps = p.interval_to_et_steps(p.period(mos), step_ratio)
-- ratio is needed.
local equave_steps = p.equave_to_et_steps(mos, step_ratio)
function p.period_to_cents(mos)
return interval_steps * rat.cents(mos.equave) / equave_steps
return rat.cents(mos.equave) / p.period_count(mos)
end
end


-- Given a mos and a step ratio, return the number of cents for its equave.
-- Given a mos and a step ratio, return the number of cents for its equave.
function p.equave_to_cents(mos, step_ratio)
-- The period is the interval at which the step pattern repeats, and the equave
local interval_steps = p.interval_to_et_steps(p.equave(mos), step_ratio)
-- is a multiple of that (at least for multi-period mosses), so no step ratio is
local equave_steps = p.equave_to_et_steps(mos, step_ratio)
-- needed.
return interval_steps * rat.cents(mos.equave) / equave_steps
function p.equave_to_cents(mos)
return rat.cents(mos.equave)
end
end


-- Given an interval vector and step ratio, compute the number of cents it
-- Given an interval vector and step ratio, convert it to cents. This requires
-- corresponds to.
-- info about the mos itself.
function p.interval_to_cents(interval, mos, step_ratio)
function p.interval_to_cents(interval, mos, step_ratio)
local interval_steps = p.interval_to_et_steps(interval, step_ratio)
local interval_steps = p.interval_to_et_steps(interval, step_ratio)
Line 586: Line 608:
--return p.interval_from_mos(p.new(5,2), 4, 1)
--return p.interval_from_mos(p.new(5,2), 4, 1)
--return p.interval_from_step_sequence("LLLdLLc")
--return p.interval_from_step_sequence("LLLdLLc")
return p.interval_as_string({['L']=5,['s']=0})
return p.mode_from_mos(p.new(5,2), -90673)
end
end


return p
return p