Module:Interval table: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
fixes, cleanup |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | local utils = require("Module:Utils") | ||
local rat = require("Module:Rational") | |||
local rat = require( | local ud = require("Module:Ups and downs notation") | ||
local ud = require( | local ET = require("Module:ET") | ||
local ET = require( | |||
-- Note: some of these helper functions may be moved to utils module | -- Note: some of these helper functions may be moved to utils module | ||
-- Get prime limit of n/d | -- Get prime limit of n/d | ||
local function get_limit(n,d) | local function get_limit(n, d) | ||
local result = 2 | local result = 2 | ||
local monzo = | local monzo = utils.get_monzo(n, d) | ||
for k,_ in pairs(monzo) do | for k, _ in pairs(monzo) do | ||
if k > result then | if k > result then | ||
result = k | result = k | ||
| Line 23: | Line 22: | ||
local function mapping(monzo, val) | local function mapping(monzo, val) | ||
local result = 0 | local result = 0 | ||
for k, | for k, _ in pairs(val) do | ||
result = result + val[k] * (monzo[k] or 0) | result = result + val[k] * (monzo[k] or 0) | ||
end | end | ||
| Line 35: | Line 34: | ||
for i = 1, max_nd do | for i = 1, max_nd do | ||
for j = 1, max_nd do | for j = 1, max_nd do | ||
t = i/ | local t = i / utils._gcd(i, j) .. "/" .. j / utils._gcd(i, j) | ||
if (i/j) >= 1 and (i/j) <= max_size and get_limit(i, j) <= prime_limit and not | if | ||
ratios[#ratios + 1] = {i/ | (i / j) >= 1 | ||
and (i / j) <= max_size | |||
and get_limit(i, j) <= prime_limit | |||
and not utils.table_contains(ratio_strings, t) | |||
then | |||
ratios[#ratios + 1] = { i / utils._gcd(i, j), j / utils._gcd(i, j) } | |||
ratio_strings[#ratio_strings + 1] = t | ratio_strings[#ratio_strings + 1] = t | ||
end | end | ||
end | end | ||
end | end | ||
return ratios | return ratios | ||
end | end | ||
| Line 49: | Line 53: | ||
-- (this is essentially what "Template:Ups and downs note name" does) | -- (this is essentially what "Template:Ups and downs note name" does) | ||
local function ud_note(et, fifth, step) | local function ud_note(et, fifth, step) | ||
return table.concat(ud.get_note_names_table(et, fifth)[step], ", "):sub(0, -1) | return table.concat(ud.get_note_names_table(et, fifth)[step], ", "):sub(0, -1) | ||
end | end | ||
local function mysplit (inputstr, sep) | local function mysplit(inputstr, sep) | ||
if sep == nil then | |||
sep = "%s" | |||
end | |||
local t = {} | |||
for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do | |||
table.insert(t, str) | |||
end | |||
return t | |||
end | end | ||
function p.interval_table(frame) | function p.interval_table(frame) | ||
local additional = frame.args[ | local additional = frame.args["additional"] or "" | ||
local additional_split = mysplit(additional, | local additional_split = mysplit(additional, "\n") | ||
for i=1,#additional_split do | for i = 1, #additional_split do | ||
additional_split[i] = mysplit(additional_split[i], | additional_split[i] = mysplit(additional_split[i], ";") | ||
end | end | ||
local tuning = frame.args[ | local tuning = frame.args["tuning"] | ||
local et = ET.parse(tuning) or ET.parse( | local et = ET.parse(tuning) or ET.parse("12edo") | ||
local patent_val = { | local patent_val = { | ||
[2] = ET.approximate(et, 2), | [2] = ET.approximate(et, 2), | ||
[3] = ET.approximate(et, 3), | [3] = ET.approximate(et, 3), | ||
[5] = ET.approximate(et, 5), | [5] = ET.approximate(et, 5), | ||
[7] = ET.approximate(et, 7), | [7] = ET.approximate(et, 7), | ||
[11] = ET.approximate(et, 11), | [11] = ET.approximate(et, 11), | ||
[13] = ET.approximate(et, 13), | [13] = ET.approximate(et, 13), | ||
[17] = ET.approximate(et, 17), | [17] = ET.approximate(et, 17), | ||
[19] = ET.approximate(et, 19), | [19] = ET.approximate(et, 19), | ||
[23] = ET.approximate(et, 23), | [23] = ET.approximate(et, 23), | ||
[29] = ET.approximate(et, 29), | [29] = ET.approximate(et, 29), | ||
| Line 86: | Line 90: | ||
[41] = ET.approximate(et, 41), | [41] = ET.approximate(et, 41), | ||
[43] = ET.approximate(et, 43), | [43] = ET.approximate(et, 43), | ||
[47] = ET.approximate(et, 47) | [47] = ET.approximate(et, 47), | ||
} | } | ||
local wikitext = '{|class="wikitable"\n' | local wikitext = '{|class="wikitable"\n' | ||
local fifth = patent_val[3] - patent_val[2] | local fifth = patent_val[3] - patent_val[2] | ||
local fifth_error = ET.cents(et, fifth) - | local fifth_error = ET.cents(et, fifth) - rat.cents(rat.new(3, 2)) | ||
local dual_fifth = math.abs(fifth_error) > (400 / et.size) | local dual_fifth = math.abs(fifth_error) > (400 / et.size) | ||
local dual_flat_fifth = ET.approximate(et, 3/2, -1) | local dual_flat_fifth = ET.approximate(et, 3 / 2, -1) | ||
local dual_sharp_fifth = ET.approximate(et, 3/2, 1) | local dual_sharp_fifth = ET.approximate(et, 3 / 2, 1) | ||
-- List of all 13-limit ratios with numerator and denominator <= 81 and in the range 1/1 - 5/1 | -- List of all 13-limit ratios with numerator and denominator <= 81 and in the range 1/1 - 5/1 | ||
local ratios_list = get_ratios_list(81, 5, 13) | local ratios_list = get_ratios_list(81, 5, 13) | ||
wikitext = wikitext .. | wikitext = wikitext .. "!Steps\n" | ||
wikitext = wikitext .. | wikitext = wikitext .. "!Cents\n" | ||
if rat.eq(et.equave, 2) then | if rat.eq(et.equave, 2) then | ||
if dual_fifth then | if dual_fifth then | ||
wikitext = wikitext .. | wikitext = wikitext | ||
wikitext = wikitext .. | .. "![[Ups and downs notation]]<br>(dual flat fifth " | ||
.. dual_flat_fifth | |||
.. "\\" | |||
.. et.size | |||
.. ")\n" | |||
wikitext = wikitext | |||
.. "![[Ups and downs notation]]<br>(dual sharp fifth " | |||
.. dual_sharp_fifth | |||
.. "\\" | |||
.. et.size | |||
.. ")\n" | |||
else | else | ||
wikitext = wikitext .. | wikitext = wikitext .. "![[Ups and downs notation]]\n" | ||
end | end | ||
end | end | ||
wikitext = wikitext .. | wikitext = wikitext .. "!Approximate ratios\n" | ||
if #additional_split > 0 then | if #additional_split > 0 then | ||
for i=1,#additional_split[1] do | for i = 1, #additional_split[1] do | ||
wikitext = wikitext .. | wikitext = wikitext .. "!" .. additional_split[1][i] .. "\n" | ||
end | end | ||
end | end | ||
for i=0,et.size do | for i = 0, et.size do | ||
wikitext = wikitext .. | wikitext = wikitext .. "|-\n" | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. i .. "\n" | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. utils._round(ET.cents(et, i), 6) .. "\n" | ||
if rat.eq(et.equave, 2) then | if rat.eq(et.equave, 2) then | ||
if dual_fifth then | if dual_fifth then | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. ud_note(et, dual_flat_fifth, i) .. "\n" | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. ud_note(et, dual_sharp_fifth, i) .. "\n" | ||
else | else | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. ud_note(et, fifth, i) .. "\n" | ||
end | end | ||
end | end | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" | ||
for j=1,#ratios_list do | for j = 1, #ratios_list do | ||
-- Go through all ratios | -- Go through all ratios. | ||
t = mapping( | -- If they are mapped to the current step in the ET's patent val and <2/5 edo step error, | ||
if t == i and math.abs(ET.cents(et, i) - | -- add to approximate ratios column. | ||
wikitext = wikitext .. | local t = mapping(utils.get_monzo(ratios_list[j][1], ratios_list[j][2]), patent_val) | ||
if | |||
t == i | |||
and math.abs(ET.cents(et, i) - utils._log(ratios_list[j][1] / ratios_list[j][2], 2) * 1200) | |||
< (1200 / (2.5 * et.size)) | |||
then | |||
wikitext = wikitext .. "[[" .. ratios_list[j][1] .. "/" .. ratios_list[j][2] .. "]], " | |||
end | end | ||
end | end | ||
if wikitext:sub(-1, -1) == | if wikitext:sub(-1, -1) == "|" then | ||
wikitext = wikitext .. | wikitext = wikitext .. "\n" | ||
else | else | ||
wikitext = wikitext:sub(0, -3) .. | wikitext = wikitext:sub(0, -3) .. "\n" | ||
end | end | ||
if (i + 2) <= #additional_split then | if (i + 2) <= #additional_split then | ||
for j=1,#additional_split[i+2] do | for j = 1, #additional_split[i + 2] do | ||
wikitext = wikitext .. | wikitext = wikitext .. "|" .. additional_split[i + 2][j] .. "\n" | ||
end | end | ||
end | end | ||
end | end | ||
wikitext = wikitext .. | wikitext = wikitext .. "|}" | ||
if wikitext:len() > 5000 then | if wikitext:len() > 5000 then | ||
wikitext = '{| class="wikitable mw-collapsible mw-collapsed"\n' .. wikitext:sub(20) | wikitext = '{| class="wikitable mw-collapsible mw-collapsed"\n' .. wikitext:sub(20) | ||
Revision as of 20:56, 1 April 2024
- This module should not be invoked directly; use its corresponding template instead: Template:Interval table.
This module automatically generates a table of intervals for an equal-step tuning, showing which just intervals are approximated relatively accurately.
| Introspection summary for Module:Interval table | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||||||||||||||
No function descriptions were provided. The Lua code may have further information.
local p = {}
local utils = require("Module:Utils")
local rat = require("Module:Rational")
local ud = require("Module:Ups and downs notation")
local ET = require("Module:ET")
-- Note: some of these helper functions may be moved to utils module
-- Get prime limit of n/d
local function get_limit(n, d)
local result = 2
local monzo = utils.get_monzo(n, d)
for k, _ in pairs(monzo) do
if k > result then
result = k
end
end
return result
end
-- Gets mapping of a monzo in a val
local function mapping(monzo, val)
local result = 0
for k, _ in pairs(val) do
result = result + val[k] * (monzo[k] or 0)
end
return result
end
-- Generates list of ratios up to a max numerator & denominator, max ratio size, and prime limit
local function get_ratios_list(max_nd, max_size, prime_limit)
local ratios = {}
local ratio_strings = {}
for i = 1, max_nd do
for j = 1, max_nd do
local t = i / utils._gcd(i, j) .. "/" .. j / utils._gcd(i, j)
if
(i / j) >= 1
and (i / j) <= max_size
and get_limit(i, j) <= prime_limit
and not utils.table_contains(ratio_strings, t)
then
ratios[#ratios + 1] = { i / utils._gcd(i, j), j / utils._gcd(i, j) }
ratio_strings[#ratio_strings + 1] = t
end
end
end
return ratios
end
-- Utility fuunction to get specific note name with ud.get_note_names_table
-- (this is essentially what "Template:Ups and downs note name" does)
local function ud_note(et, fifth, step)
return table.concat(ud.get_note_names_table(et, fifth)[step], ", "):sub(0, -1)
end
local function mysplit(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t = {}
for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do
table.insert(t, str)
end
return t
end
function p.interval_table(frame)
local additional = frame.args["additional"] or ""
local additional_split = mysplit(additional, "\n")
for i = 1, #additional_split do
additional_split[i] = mysplit(additional_split[i], ";")
end
local tuning = frame.args["tuning"]
local et = ET.parse(tuning) or ET.parse("12edo")
local patent_val = {
[2] = ET.approximate(et, 2),
[3] = ET.approximate(et, 3),
[5] = ET.approximate(et, 5),
[7] = ET.approximate(et, 7),
[11] = ET.approximate(et, 11),
[13] = ET.approximate(et, 13),
[17] = ET.approximate(et, 17),
[19] = ET.approximate(et, 19),
[23] = ET.approximate(et, 23),
[29] = ET.approximate(et, 29),
[31] = ET.approximate(et, 31),
[37] = ET.approximate(et, 37),
[41] = ET.approximate(et, 41),
[43] = ET.approximate(et, 43),
[47] = ET.approximate(et, 47),
}
local wikitext = '{|class="wikitable"\n'
local fifth = patent_val[3] - patent_val[2]
local fifth_error = ET.cents(et, fifth) - rat.cents(rat.new(3, 2))
local dual_fifth = math.abs(fifth_error) > (400 / et.size)
local dual_flat_fifth = ET.approximate(et, 3 / 2, -1)
local dual_sharp_fifth = ET.approximate(et, 3 / 2, 1)
-- List of all 13-limit ratios with numerator and denominator <= 81 and in the range 1/1 - 5/1
local ratios_list = get_ratios_list(81, 5, 13)
wikitext = wikitext .. "!Steps\n"
wikitext = wikitext .. "!Cents\n"
if rat.eq(et.equave, 2) then
if dual_fifth then
wikitext = wikitext
.. "![[Ups and downs notation]]<br>(dual flat fifth "
.. dual_flat_fifth
.. "\\"
.. et.size
.. ")\n"
wikitext = wikitext
.. "![[Ups and downs notation]]<br>(dual sharp fifth "
.. dual_sharp_fifth
.. "\\"
.. et.size
.. ")\n"
else
wikitext = wikitext .. "![[Ups and downs notation]]\n"
end
end
wikitext = wikitext .. "!Approximate ratios\n"
if #additional_split > 0 then
for i = 1, #additional_split[1] do
wikitext = wikitext .. "!" .. additional_split[1][i] .. "\n"
end
end
for i = 0, et.size do
wikitext = wikitext .. "|-\n"
wikitext = wikitext .. "|" .. i .. "\n"
wikitext = wikitext .. "|" .. utils._round(ET.cents(et, i), 6) .. "\n"
if rat.eq(et.equave, 2) then
if dual_fifth then
wikitext = wikitext .. "|" .. ud_note(et, dual_flat_fifth, i) .. "\n"
wikitext = wikitext .. "|" .. ud_note(et, dual_sharp_fifth, i) .. "\n"
else
wikitext = wikitext .. "|" .. ud_note(et, fifth, i) .. "\n"
end
end
wikitext = wikitext .. "|"
for j = 1, #ratios_list do
-- Go through all ratios.
-- If they are mapped to the current step in the ET's patent val and <2/5 edo step error,
-- add to approximate ratios column.
local t = mapping(utils.get_monzo(ratios_list[j][1], ratios_list[j][2]), patent_val)
if
t == i
and math.abs(ET.cents(et, i) - utils._log(ratios_list[j][1] / ratios_list[j][2], 2) * 1200)
< (1200 / (2.5 * et.size))
then
wikitext = wikitext .. "[[" .. ratios_list[j][1] .. "/" .. ratios_list[j][2] .. "]], "
end
end
if wikitext:sub(-1, -1) == "|" then
wikitext = wikitext .. "\n"
else
wikitext = wikitext:sub(0, -3) .. "\n"
end
if (i + 2) <= #additional_split then
for j = 1, #additional_split[i + 2] do
wikitext = wikitext .. "|" .. additional_split[i + 2][j] .. "\n"
end
end
end
wikitext = wikitext .. "|}"
if wikitext:len() > 5000 then
wikitext = '{| class="wikitable mw-collapsible mw-collapsed"\n' .. wikitext:sub(20)
end
return wikitext
end
return p