Module:ED intro: Difference between revisions
Rewrote code for better handling of ed types; added edo compare function (for outputting things like "12edf corresponds to 20.5edo"), but requires further rewriting/testing |
Address Template talk: ED intro #Square/cube root of 2. Now square/cube root are displayed instead of 2nd/3rd root |
||
| (25 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
local ord = require( | local ord = require("Module:Ordinal") | ||
local utils = require( | local rat = require("Module:Rational") | ||
local | local utils = require("Module:Utils") | ||
local yesno = require("Module:Yesno") | |||
local p = {} | local p = {} | ||
-- TODO: Add support for the following | -- TODO: Add support for the following | ||
-- - | -- - Make it clear what text is being swapped in string.gsub | ||
-- Notes: | -- Notes: | ||
-- - Edo and edt are technically | -- - Edo and edt are technically equal divisions of a harmonic, and edf an equal | ||
-- division of a ratio; these are their own types because their intros have | |||
-- - | -- specific wording. | ||
-- - | -- - An equal division of a harmonic is a special case of an equal division of a | ||
-- ( | -- ratio, where the ratio is h/1. | ||
-- | -- - An equal division of a ratio and an equal division of a non-integer | ||
-- constant or cent value are also called AS (ambitonal sequence) and APS | |||
-- (arithmetic pitch sequence), respectively. | |||
-- - All of these are equal-step tunings. We've adopted the 1ed-p notation where | |||
-- possible. | |||
-- - Equal divisions of irrational constants (such as pi and e) are not very | -- - Equal divisions of irrational constants (such as pi and e) are not very | ||
-- common, but count as equal divisions of arbitrary cent values. | -- common, but count as equal divisions of arbitrary cent values. | ||
| Line 20: | Line 25: | ||
local ED_TYPE_EDT = "EDT" | local ED_TYPE_EDT = "EDT" | ||
local ED_TYPE_EDF = "EDF" | local ED_TYPE_EDF = "EDF" | ||
local ED_TYPE_EDH = "EDH" | local ED_TYPE_EDH = "EDH" -- "equal division of a harmonic" | ||
local ED_TYPE_EDR = "EDR" | local ED_TYPE_EDR = "EDR" -- "equal division of a ratio" | ||
local ED_TYPE_EDC = "EDC" | local ED_TYPE_EDC = "EDC" -- "equal division of a cent value" | ||
local ED_TYPE_DEFAULT = "UNKNOWN_TYPE" | local ED_TYPE_DEFAULT = "UNKNOWN_TYPE" | ||
| Line 29: | Line 34: | ||
local ed = ed or 12 | local ed = ed or 12 | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local edstep_size = 1200 / ed | local edstep_size = 1200 / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 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]] that uses [[equal]] steps of 2/1 (one [[octave]]), or exactly/about ''s'' | 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]] that uses [[equal]] steps of 2/1 (one [[octave]]), or exactly/about ''s''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of the octave''' (abbreviated '''''k''edo''' or '''''k''ed2'''), also called '''''k''-tone equal temperament''' ('''''k''tet''') or '''''k'' equal temperament''' ('''''k''et''') when viewed under a [[regular temperament]] perspective, is the [[tuning system]] that divides the [[octave]] into ''k'' [[equal]] parts of exactly/about ''s'' | intro_text = "'''''k'' equal divisions of the octave''' (abbreviated '''''k''edo''' or '''''k''ed2'''), also called '''''k''-tone equal temperament''' ('''''k''tet''') or '''''k'' equal temperament''' ('''''k''et''') when viewed under a [[regular temperament]] perspective, is the [[tuning system]] that divides the [[octave]] into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each. Each step represents a [[frequency ratio]] of 2<sup>1/''k''</sup>, or the ''kth'' root of 2." | ||
end | end | ||
| Line 46: | Line 49: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''kth''", | intro_text = string.gsub(intro_text, "''kth''", p.root_ordinal(ed)) | ||
return intro_text | return intro_text | ||
| Line 56: | Line 59: | ||
local ed = ed or 13 | local ed = ed or 13 | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local equave_in_cents = math.log(3) * 1200 | local equave_in_cents = math.log(3) * 1200 | ||
local edstep_size = equave_in_cents / math.log(2) / ed | local edstep_size = equave_in_cents / math.log(2) / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 then | ||
intro_text = "'''1 equal division of the tritave''', '''perfect twelfth''', or '''3rd harmonic''' (abbreviated '''1edt''' or '''1ed3'''), is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[3/1]] (one tritave), or exactly/about ''s'' | intro_text = "'''1 equal division of the tritave''', '''perfect twelfth''', or '''3rd harmonic''' (abbreviated '''1edt''' or '''1ed3'''), is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[3/1]] (one tritave), or exactly/about ''s''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of the tritave''', '''perfect twelfth''', or '''3rd harmonic''' (abbreviated '''''k''edt''' or '''''k''ed3'''), is a [[nonoctave]] [[tuning system]] that divides the interval of [[3/1]] into ''k'' [[equal]] parts of exactly/about ''s'' | intro_text = "'''''k'' equal divisions of the tritave''', '''perfect twelfth''', or '''3rd harmonic''' (abbreviated '''''k''edt''' or '''''k''ed3'''), is a [[nonoctave]] [[tuning system]] that divides the interval of [[3/1]] into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each. Each step represents a [[frequency ratio]] of 3<sup>1/''k''</sup>, or the ''kth'' root of 3." | ||
end | end | ||
| Line 74: | Line 75: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''kth''", | intro_text = string.gsub(intro_text, "''kth''", p.root_ordinal(ed)) | ||
return intro_text | return intro_text | ||
| Line 84: | Line 85: | ||
local ed = ed or 7 | local ed = ed or 7 | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local equave_in_cents = math.log(3/2) * 1200 | local equave_in_cents = math.log(3/2) * 1200 | ||
local edstep_size = equave_in_cents / math.log(2) / ed | local edstep_size = equave_in_cents / math.log(2) / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 then | ||
intro_text = "'''1 equal division of the perfect fifth''' (abbreviated '''1edf''' or '''1ed3/2''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[3/2]] (one perfect fifth), or exactly/about ''s'' | intro_text = "'''1 equal division of the perfect fifth''' (abbreviated '''1edf''' or '''1ed3/2''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[3/2]] (one perfect fifth), or exactly/about ''s''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of the perfect fifth''' (abbreviated '''''k''edf''' or '''''k''ed3/2''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[3/2]] into ''k'' [[equal]] parts of exactly/about ''s'' | intro_text = "'''''k'' equal divisions of the perfect fifth''' (abbreviated '''''k''edf''' or '''''k''ed3/2''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[3/2]] into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each. Each step represents a [[frequency ratio]] of (3/2)<sup>1/''k''</sup>, or the ''kth'' root of 3/2." | ||
end | end | ||
| Line 102: | Line 101: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''kth''", | intro_text = string.gsub(intro_text, "''kth''", p.root_ordinal(ed)) | ||
return intro_text | return intro_text | ||
| Line 113: | Line 112: | ||
local harmonic = harmonic or 4 | local harmonic = harmonic or 4 | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local equave_in_cents = math.log(harmonic) * 1200 | local equave_in_cents = math.log(harmonic) * 1200 | ||
local edstep_size = equave_in_cents / math.log(2) / ed | local edstep_size = equave_in_cents / math.log(2) / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 then | ||
intro_text = "'''1 equal division of the hth harmonic''' (abbreviated '''1ed''h''''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[''h''/1]], or exactly/about ''s'' | intro_text = "'''1 equal division of the hth harmonic''' (abbreviated '''1ed''h''''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[''h''/1]], or exactly/about ''s''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of the hth harmonic''' (abbreviated '''''k''ed''h''''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[''h''/1]] into ''k'' [[equal]] parts of exactly/about ''s'' | intro_text = "'''''k'' equal divisions of the hth harmonic''' (abbreviated '''''k''ed''h''''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[''h''/1]] into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each. Each step represents a [[frequency ratio]] of ''h''<sup>1/''k''</sup>, or the ''kth'' root of ''h''." | ||
end | end | ||
| Line 131: | Line 128: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''kth''", | intro_text = string.gsub(intro_text, "''kth''", p.root_ordinal(ed)) | ||
intro_text = string.gsub(intro_text, "hth", ord._ordinal(harmonic)) | intro_text = string.gsub(intro_text, "hth", ord._ordinal(harmonic)) | ||
intro_text = string.gsub(intro_text, "''h''", harmonic) | intro_text = string.gsub(intro_text, "''h''", harmonic) | ||
| Line 144: | Line 141: | ||
local ratio = ratio or rat.new(9,4) | local ratio = ratio or rat.new(9,4) | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local equave_in_cents = rat.cents(ratio) | local equave_in_cents = rat.cents(ratio) | ||
local edstep_size = equave_in_cents / ed | local edstep_size = equave_in_cents / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 then | ||
intro_text = "'''1 equal division of ''p/q''''' (abbreviated '''1ed''p/q''''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[''p/q'']], or exactly/about ''s'' | intro_text = "'''1 equal division of ''p/q''''' (abbreviated '''1ed''p/q''''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of [[''p/q'']], or exactly/about ''s''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of ''p/q''''' (abbreviated '''''k''ed''p/q''''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[''p/q'']] into ''k'' [[equal]] parts of exactly/about ''s'' | intro_text = "'''''k'' equal divisions of ''p/q''''' (abbreviated '''''k''ed''p/q''''') is a [[nonoctave]] [[tuning system]] that divides the interval of [[''p/q'']] into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each. Each step represents a [[frequency ratio]] of (''p/q'')<sup>1/''k''</sup>, or the ''kth'' root of ''p/q''." | ||
end | end | ||
| Line 162: | Line 157: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''kth''", | intro_text = string.gsub(intro_text, "''kth''", p.root_ordinal(ed)) | ||
intro_text = string.gsub(intro_text, "''p/q''", rat.as_ratio(ratio)) | intro_text = string.gsub(intro_text, "''p/q''", rat.as_ratio(ratio)) | ||
| Line 174: | Line 169: | ||
local cents = cents or 97.5 | local cents = cents or 97.5 | ||
-- Exactly or about? | -- Exactly or about? Check up to three significant figures | ||
local edstep_size = cents / ed | local edstep_size = cents / ed | ||
local edstep_size_rounded = utils._round(edstep_size, 3) | local edstep_size_rounded = utils._round(edstep_size, 3) | ||
local is_exact = edstep_size - edstep_size_rounded == 0 | local is_exact = edstep_size - edstep_size_rounded == 0 | ||
local intro_text = "" | local intro_text = "" | ||
if ed == 1 then | if ed == 1 then | ||
intro_text = "'''1 equal division of ''c'' | intro_text = "'''1 equal division of ''c''{{c}}''' (abbreviated '''1ed''c''{{c}}''') is a [[nonoctave]] [[tuning system]] that uses [[equal]] steps of ''c''{{cent}}." | ||
else | else | ||
intro_text = "'''''k'' equal divisions of ''c'' | intro_text = "'''''k'' equal divisions of ''c''{{c}}''' (abbreviated '''''k''ed''c''{{c}}''') is a [[nonoctave]] [[tuning system]] that divides the interval of ''c''{{c}} into ''k'' [[equal]] parts of exactly/about ''s''{{cent}} each." | ||
end | end | ||
| Line 191: | Line 184: | ||
intro_text = string.gsub(intro_text, "''k''", ed) | intro_text = string.gsub(intro_text, "''k''", ed) | ||
intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | intro_text = string.gsub(intro_text, "exactly/about", (is_exact and "exactly" or "about")) | ||
intro_text = string.gsub(intro_text, "''s''", | intro_text = string.gsub(intro_text, "''s''", utils._round (edstep_size, 3)) | ||
intro_text = string.gsub(intro_text, "''c''", cents) | intro_text = string.gsub(intro_text, "''c''", cents) | ||
return intro_text | return intro_text | ||
end | |||
-- ord._ordinal but for roots | |||
function p.root_ordinal(n) | |||
local result = ord._ordinal(n) | |||
if n == 2 then | |||
result = "square" | |||
elseif n == 3 then | |||
result = "cube" | |||
end | |||
return result | |||
end | end | ||
| Line 207: | Line 211: | ||
-- Parse the step count, the suffix, and the equave | -- Parse the step count, the suffix, and the equave | ||
local steps, equave = unparsed:match( | local steps, equave = unparsed:match("^(%d+)[Ee][Dd](.+)$") | ||
-- Determine if the ed is for a cent value | -- Determine if the ed is for a cent value | ||
local is_cents = string.match(equave, | local is_cents = string.match(equave, "%d*%.?%d+[Cc¢]$") ~= nil | ||
-- Parse equave | -- Parse equave | ||
| Line 227: | Line 231: | ||
parsed_equave = rat.new(3,2) | parsed_equave = rat.new(3,2) | ||
ed_type = ED_TYPE_EDF | ed_type = ED_TYPE_EDF | ||
elseif string.match(equave, | elseif string.match(equave, "^%d+$") ~= nil then | ||
-- Equave is arbitrary harmonic (not 2/1 or 3/1) | -- Equave is arbitrary harmonic (not 2/1 or 3/1) | ||
parsed_equave = tonumber(equave) | parsed_equave = tonumber(equave) | ||
ed_type = ED_TYPE_EDH | ed_type = ED_TYPE_EDH | ||
elseif string.match(equave, | elseif string.match(equave, "^%d+/%d+$") ~= nil then | ||
-- Equave is arbitrary ratio (not 3/2) | -- Equave is arbitrary ratio (not 3/2) | ||
local num, den = equave:match( | local num, den = equave:match("^(%d+)/(%d+)$") | ||
parsed_equave = rat.new(tonumber(num), tonumber(den)) | parsed_equave = rat.new(tonumber(num), tonumber(den)) | ||
ed_type = ED_TYPE_EDR | ed_type = ED_TYPE_EDR | ||
elseif is_cents then | elseif is_cents then | ||
-- Equave is arbitrary cent value | -- Equave is arbitrary cent value | ||
parsed_equave = tonumber(equave:match( | parsed_equave = tonumber(equave:match("^(%d*%.?%d+)[Cc¢]$")) | ||
ed_type = ED_TYPE_EDC | ed_type = ED_TYPE_EDC | ||
else | else | ||
| Line 294: | Line 298: | ||
if ed_type == ED_TYPE_DEFAULT then | if ed_type == ED_TYPE_DEFAULT then | ||
return "Equave type not supported or entered incorrectly." | return "{{error|Error: Equave type not supported or entered incorrectly.}}" | ||
elseif ed_type == ED_TYPE_EDO then | elseif ed_type == ED_TYPE_EDO then | ||
return p.edo_intro(parsed_ed) | return p.edo_intro(parsed_ed) | ||
| Line 329: | Line 333: | ||
-- Wrapper function; for use with a template | -- Wrapper function; for use with a template | ||
function p.ed_intro(frame) | function p.ed_intro(frame) | ||
local ed = frame.args[ | local ed = frame.args["ED"] | ||
local edo = frame.args[ | local edo = frame.args["EDO"] -- For backwards compatibility with edo intro | ||
local debugg = yesno(frame.args["debug"]) | |||
local result = p._ed_intro((edo == nil) and ed or edo) | |||
if debugg == true then | |||
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" | |||
end | end | ||
return frame:preprocess(result) | |||
end | end | ||
return p | return p | ||