Module:ED intro: Difference between revisions

Ganaram inukshuk (talk | contribs)
Still work-in-progress; includes todo on what to bugfix
Ganaram inukshuk (talk | contribs)
Bugfixed; rewritten to support edo, edt, edf, edh (harmonics), edr (arbitrary ratios), and edc (arbitrary cents)
Line 4: Line 4:
local p = {}
local p = {}


-- TODO:
-- Notes on supported types:
-- - Enforce ED types: edo, edt, edf, edh, edr, edc for octave, tritave/twelfth,
-- - Supported types: edo, edt, edf, edh, edr, edc (for octave, tritave/twelfth,
--  fifth, arbitrary harmonic h, arbitrary ratio r, and arbitrary cent value c.
--  fifth, arbitrary harmonic h, arbitrary ratio r, and arbitrary cents c).
--   Note that EDs of named constants, like pi, are currently not included, as
-- - Note that EDs of irrational numbers (edir) aren't supported since some of
--  they probably need their own typing (ednc) separate from edc.
--  these constants have names (e, pi, phi) or are formatted in special ways
-- - Bugfix edr not reporting the correct equave
--  (sqrt(2)). These aren't very common and can be expressed as edc's if need
--  be (edsqrt(2) is ed600c), or as an ed of a non-integer number (ed1.41421).
-- - Also note that, under harmontonic tuning, edc and edr are the same as ASp
--  and APSp (ambitonal sequence and arithmetic pitch sequence); these were
--  recently reclassified as edr and edc, however.


-- Parse ed function
function p.parse_ed(unparsed)
function p.parse_ed(unparsed)
local unparsed = unparsed or "12edo"
local unparsed = unparsed or "12edo"
Line 20: Line 25:
-- Parse
-- Parse
local steps, equave = unparsed:match('^(%d+)[Ee][Dd](.+)$')
local steps, suffix, equave = unparsed:match('^(%d+)([Ee][Dd](.+))$')
steps = tonumber(steps)
steps = tonumber(steps)
Line 27: Line 32:
-- t: tritave or twelfth, 3/1 (3rd harmonic)
-- t: tritave or twelfth, 3/1 (3rd harmonic)
-- f: fifth, 3/2
-- f: fifth, 3/2
local ed_type = ""
-- Make sure these have the correct equave and suffix
local ratio = "n/a"
local ratio = "n/a"
local cents = 0
local cents = 0
if equave == "o" or equave == "O" or equave == "2" then
local ed_type = ""
if equave == "o" or equave == "O" or equave == "2" or equave == "2/1" then
equave = "2"
equave = "2"
ratio = "2/1"
ratio = "2/1"
cents = 1200
cents = 1200
suffix = "edo"
ed_type = "edo"
ed_type = "edo"
elseif equave == "t" or equave == "T" or equave == "3" then
elseif equave == "t" or equave == "T" or equave == "3" or equave == "3/1" then
equave = "3"
equave = "3"
ratio = "3/1"
ratio = "3/1"
cents = math.log(3) * 1200 / math.log(2)
cents = math.log(3) * 1200 / math.log(2)
suffix = "edt"
ed_type = "edt"
ed_type = "edt"
elseif equave == "f" or equave == "F" or equave == "3/2" then
elseif equave == "f" or equave == "F" or equave == "3/2" then
Line 44: Line 52:
ratio = "3/2"
ratio = "3/2"
cents = math.log(3/2) * 1200 / math.log(2)
cents = math.log(3/2) * 1200 / math.log(2)
suffix = "edf"
ed_type = "edf"
ed_type = "edf"
end
end
-- For equaves not 2/1, 3/1, or 3/2
-- For equaves not 2/1, 3/1, or 3/2
if ed_type == "" then
if suffix ~= "edo" and suffix ~= "edt" and suffix ~= "edf" then
-- If the equave is a number or ratio, convert it to cents
-- If the equave is a number or ratio, convert it to cents
-- If the equave is already a cent value, extract it
-- If the equave is already a cent value, extract it
local is_cents = string.match(equave, '^(.+)c') ~= nil
local is_cents = string.match(equave, '^.+c$') ~= nil
local is_numeric = tonumber(equave) ~= nil
local is_harmonic = string.match(equave, '^%d+$') ~= nil
local is_ratio = string.match(equave, '^%d+/%d+$') ~= nil
local is_ratio = string.match(equave, '^%d+/%d+$') ~= nil
if is_cents then
if is_cents then
cents = tonumber(equave:match('^(.+)c'))
ed_type = "edc"
ed_type = "edc"
elseif is_numeric then
cents = tonumber(equave:match('^(.+)c$'))
cents = math.log(tonumber(equave)) * 1200 / math.log(2)
elseif is_harmonic then
ed_type = "edh"
-- Classify ed type as either ed of a constant (if not a whole number)
local harmonic = tonumber(string.match(equave, '^%d+$'))
-- or ed of a harmonic (if it's a whole number); if it is a harmonic,
cents = math.log(harmonic) * 1200 / math.log(2)
-- write it as a ratio (h/1)
ratio = string.format("%d/1", harmonic)
if math.floor(tonumber(equave)) ~= tonumber(equave) then
ed_type = "edc"
else
ed_type = "edh"
ratio = equave .. "/1"
end
elseif is_ratio then
elseif is_ratio then
local ratio = rat.parse(equave)
ed_type = "edr"
cents = rat.cents(ratio)
local num, den = equave:match('^(%d+)/(%d+)$')
equave = rat.as_ratio(ratio) -- Ensures ratio is simplified
local gcd = utils._gcd(num, den)
num = num / gcd
den = den / gcd
cents = math.log(num / den) * 1200 / math.log(2)
equave = string.format("%d/%d", num, den)
ratio = equave
ratio = equave
ed_type = "edr"
end
end
end
end


return { ['cents'] = cents, ['equave'] = equave, ['steps'] = steps, ['ratio'] = ratio, ['type'] = ed_type }
return { ['cents'] = cents, ['equave'] = equave, ['ratio'] = ratio, ['steps'] = steps, ['suffix'] = suffix, ['type'] = ed_type }
end
end


-- Primary function
function p.ed_intro(ed)
function p.ed_intro(ed)
local ed = ed or "12ed19/13"
local ed = ed or "1ed5/4"
local parsed_ed = p.parse_ed(ed)
local parsed_ed = p.parse_ed(ed)
Line 95: Line 101:
-- - Equal-step tunings: 1edo, 1edt, 1edf, 1edh, 1edp/q, 1edc
-- - Equal-step tunings: 1edo, 1edt, 1edf, 1edh, 1edp/q, 1edc
local intro_text = ""
local intro_text = ""
if is_est then
if parsed_ed['steps'] == 1 then
if ed_type == "edo" then
if ed_type == "edo" then
intro_text = "'''1 equal division of the octave''' (abbreviated '''1edo''' or '''1ed2'''), also called '''1-tone equal temperament''' ('''1tet'''), or '''1 equal temperament''' ('''1et''') when viewed under a [[regular temperament]] perspective, is the [[tuning system]] where adjacent pitches are one [[octave]], or exactly/about ''s'' [[¢]], from each other."
intro_text = "'''1 equal division of the octave''' (abbreviated '''1edo''' or '''1ed2'''), also called '''1-tone equal temperament''' ('''1tet'''), or '''1 equal temperament''' ('''1et''') when viewed under a [[regular temperament]] perspective, is the [[tuning system]] where adjacent pitches are one [[octave]], or exactly/about ''s'' [[¢]], from each other."
Line 105: Line 111:
intro_text = "'''1 equal division of the ''hth'' harmonic''' (abbreviated '''1ed''h''''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''h''/1]], or exactly/about ''s'' [[¢]], apart from each other."
intro_text = "'''1 equal division of the ''hth'' harmonic''' (abbreviated '''1ed''h''''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''h''/1]], or exactly/about ''s'' [[¢]], apart from each other."
elseif ed_type == "edr" then
elseif ed_type == "edr" then
intro_text = "'''1 equal division of ''p''/''q''''' (abbreviated '''1ed''p''/''q''''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''p''/''q'']], or exactly/about ''s'' [[¢]], apart from each other."
intro_text = "'''1 equal division of ''p''/''q''''' (abbreviated '''1ed''p''/''q'''''), also called '''ambitonal sequence of '''''p''/''q''''''' ('''AS''p''/''q''''''') or '''''p''/''q'' equal-step tuning''', is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''p''/''q'']], or exactly/about ''s'' [[¢]], apart from each other."
elseif ed_type == "edc" then
elseif ed_type == "edc" then
intro_text = "'''1 equal division of ''c''¢''' (abbreviated '''1ed''c''''') is the [[non-octave]] [[tuning system]] where adjacent pitches are ''s'' [[¢]], apart from each other."
intro_text = "'''1 equal division of ''c''¢''' (abbreviated '''1ed''c'''''), also called '''arithmetic pitch sequence of ''c''¢''' ('''APS''c''¢'''), is the [[non-octave]] [[tuning system]] where adjacent pitches are ''s'' [[¢]] apart from each other."
end
end
else
else
Line 150: Line 156:
return intro_text
return intro_text
end
-- Wrapper function; for use with a template
function p.ed_intro_frame(frame)
local ed = frame.args['ED']
return ed_intro(ed)
end
end


return p
return p