- This module primarily serves as a library for other modules and has no corresponding template.
This module provides helper functions for equal-step tunings.
| Introspection summary for Module:ET
|
Functions provided (13)
| Line
|
Function
|
Params
|
Description
|
| 23
|
new
|
(size, equave, suffix)
|
Returns an array consisting of the components of an equal-step tuning.
|
| 43
|
parse
|
(unparsed)
|
Converts an equal tuning as a string into a Lua table.
|
| 59
|
as_string
|
(et)
|
Returns the ET as a string.
|
| 64
|
backslash_ratio
|
(et, steps)
|
Converts steps to a proper ratio as a floating-point number.
|
| 71
|
backslash_display
|
(et, steps)
|
Displays an ET as steps\number-of-divisions.
|
| 78
|
backslash_modifier
|
(et)
|
|
| 86
|
cents
|
(et, steps)
|
Converts an interval of the ET into cents, ¢.
|
| 95
|
hekts
|
(et, steps)
|
Converts an interval of the ET into hekts, the relative cents of 13edt.
|
| 106
|
approximate
|
(et, ratio, towards)
|
Returns the floor, round, or ceiling of a particular ratio.
|
| 122
|
tempers_out
|
(et, ratio)
|
Determines whether an ET tempers out a provided rational number.
|
| 133
|
is_highly_composite
|
(et)
|
Determines whether an ET is highly composite.
|
| 139
|
is_zeta
|
(et)
|
Determines if an ET holds any zeta records.
|
| 147
|
why_zeta
|
(et)
|
Describes what specific properties an ET has if it is a zeta record ET.
|
|
Lua modules required (2)
| Variable
|
Module
|
Functions used
|
| rat
|
Module:Rational
|
new
as_pair
as_ratio
parse
as_float
eq
is_highly_composite
|
| seq
|
Module:Sequence
|
contains
|
|
local rat = require("Module:Rational")
local seq = require("Module:Sequence")
local p = {}
local common_suffix = {
["3/2"] = "f",
["2"] = "o",
["2/1"] = "o",
["3"] = "t",
["3/1"] = "t",
}
local common_ratio = {
["f"] = rat.new(3, 2),
["o"] = 2,
["t"] = 3,
["ϕ"] = (1 + math.sqrt(5)) / 2,
["n"] = math.exp(1),
["π"] = math.pi
}
-- create a ET structure <size>ed<equave>
function p.new(size, equave, suffix)
size = size or 12
equave = equave or 2
if suffix == nil then
local equave_n, equave_m = rat.as_pair(equave)
local equave_ratio = rat.as_ratio(equave)
equave_ratio = equave_ratio:lower()
suffix = "ed"
if common_suffix[equave_ratio] then
suffix = suffix .. common_suffix[equave_ratio]
elseif equave_m == 1 then
suffix = suffix .. equave_n
else
suffix = suffix .. equave_ratio
end
end
return { size = size, equave = equave, suffix = suffix }
end
-- parse a ET structure
function p.parse(unparsed)
local size, suffix, equave = unparsed:match("^(%d+%.*%d*)([Ee][Dd](.+))$")
-- local size, suffix, equave = unparsed:match("^(%d+%.*%d*)([Cc]?[Ee][Dd]?[Tt]?(.*))$")
if equave == nil then
return nil
end
suffix = suffix:lower()
size = tonumber(size)
equave = common_ratio[equave] or rat.parse(equave)
if size == nil or equave == nil then
return nil
end
return p.new(size, equave, suffix)
end
-- construct a string representation for a ET structure
function p.as_string(et)
return et.size .. et.suffix
end
-- convert steps to a proper ratio (except that it is a float approximation)
function p.backslash_ratio(et, steps)
if et.size == 0 then
return nil
end
return rat.as_float(et.equave) ^ (steps / et.size)
end
function p.backslash_display(et, steps)
if et.size == 0 then
return nil
end
return steps .. p.backslash_modifier(et)
end
function p.backslash_modifier(et)
if not rat.eq(et.equave, 2) then
return "\\" .. et.size .. et.suffix
end
return "\\" .. et.size
end
-- convert steps to cents
function p.cents(et, steps)
if et.size == 0 then
return nil
end
steps = steps or 1
return 1200 * steps / et.size * math.log(rat.as_float(et.equave)) / math.log(2)
end
-- convert steps to hekts
function p.hekts(et, steps)
if et.size == 0 then
return nil
end
steps = steps or 1
return 1300 * steps / et.size * math.log(rat.as_float(et.equave)) / math.log(3)
end
-- convert ratio to steps
-- ratio is a float!
-- towards is one of: -1 (floor), 0 (nearest), 1 (ceil)
function p.approximate(et, ratio, towards)
towards = towards or 0
if et.size == 0 then
return nil
end
local exact = math.log(ratio) / math.log(rat.as_float(et.equave)) * et.size
if towards < 0 then
return math.floor(exact)
elseif towards > 0 then
return math.ceil(exact)
else
return math.floor(exact + 0.5)
end
end
-- whether this ET tempers out the provided rational number
function p.tempers_out(et, ratio)
local t = 0
for factor, power in pairs(ratio) do
if type(factor) == "number" then
t = t + power * p.approximate(et, factor)
end
end
return t == 0
end
-- determine whether ET is highly composite
function p.is_highly_composite(et)
et.highly_composite = et.highly_composite or rat.is_highly_composite(et.size)
return et.highly_composite
end
-- determine whether ET's size could be within one of zeta function-related sequences
function p.is_zeta(et)
return seq.contains(seq.zeta_peak, et.size)
or seq.contains(seq.zeta_peak_integer, et.size)
or seq.contains(seq.zeta_integral, et.size)
or seq.contains(seq.zeta_gap, et.size)
end
-- describe why
function p.why_zeta(et)
local zeta_peak = seq.contains(seq.zeta_peak, et.size)
local zeta_peak_integer = seq.contains(seq.zeta_peak_integer, et.size)
local zeta_integral = seq.contains(seq.zeta_integral, et.size)
local zeta_gap = seq.contains(seq.zeta_gap, et.size)
local z = "The Riemann zeta function and tuning #Zeta EDO lists"
local markers = {}
if zeta_peak then
table.insert(markers, string.format("[[%s|Zeta peak]]", z))
elseif zeta_peak == nil then
table.insert(markers, string.format("[[%s|Zeta peak?]]", z))
end
if zeta_peak_integer then
table.insert(markers, string.format("[[%s|Zeta peak integer]]", z))
elseif zeta_peak_integer == nil then
table.insert(markers, string.format("[[%s|Zeta peak integer?]]", z))
end
if zeta_integral then
table.insert(markers, string.format("[[%s|Zeta integral]]", z))
elseif zeta_integral == nil then
table.insert(markers, string.format("[[%s|Zeta integral?]]", z))
end
if zeta_gap then
table.insert(markers, string.format("[[%s|Zeta gap]]", z))
elseif zeta_gap == nil then
table.insert(markers, string.format("[[%s|Zeta gap?]]", z))
end
return table.concat(markers, "<br />")
end
return p