Module:ED intro: Difference between revisions
Still work-in-progress; includes todo on what to bugfix |
Bugfixed; rewritten to support edo, edt, edf, edh (harmonics), edr (arbitrary ratios), and edc (arbitrary cents) |
||
| Line 4: | Line 4: | ||
local p = {} | local p = {} | ||
-- | -- Notes on supported types: | ||
-- - | -- - Supported types: edo, edt, edf, edh, edr, edc (for octave, tritave/twelfth, | ||
-- fifth, arbitrary harmonic h, arbitrary ratio r, and arbitrary | -- fifth, arbitrary harmonic h, arbitrary ratio r, and arbitrary cents c). | ||
-- | -- - Note that EDs of irrational numbers (edir) aren't supported since some of | ||
-- | -- these constants have names (e, pi, phi) or are formatted in special ways | ||
-- - | -- (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 | ||
-- 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 | 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, '^ | local is_cents = string.match(equave, '^.+c$') ~= nil | ||
local | 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 | ||
ed_type = "edc" | ed_type = "edc" | ||
cents = tonumber(equave:match('^(.+)c$')) | |||
cents = | elseif is_harmonic then | ||
ed_type = "edh" | |||
local harmonic = tonumber(string.match(equave, '^%d+$')) | |||
cents = math.log(harmonic) * 1200 / math.log(2) | |||
ratio = string.format("%d/1", harmonic) | |||
elseif is_ratio then | elseif is_ratio then | ||
local | ed_type = "edr" | ||
cents = | local num, den = equave:match('^(%d+)/(%d+)$') | ||
equave = | 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 | ||
end | end | ||
end | end | ||
return { ['cents'] = cents, ['equave'] = equave, ['steps'] = steps, [' | 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 " | 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 | 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'' [[¢]] | 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 | ||