Module:Harmonics infobox: Difference between revisions
Jump to navigation
Jump to search
Created page with "-- Module:Harmonics infobox -- Infobox for "Harmonics n–2n" and "Subharmonics n–2n" pages. -- Called through Template:Infobox Harmonics and Template:Infobox Subharmonics. local p = {} local getArgs = require("Module:Arguments").getArgs local infobox = require("Module:Infobox") local u = require("Module:Utils") local yesno = require("Module:Yesno") local EN_DASH = "–" -- category names, in one place local CATEGORY = { harmonics = "Overtone scale", subharmonics = "..." |
m Unify the case and plural |
||
| (One intermediate revision by one other user not shown) | |||
| Line 1: | Line 1: | ||
-- Module:Harmonics infobox | -- Module: Harmonics infobox | ||
-- Infobox for "Harmonics n–2n" and "Subharmonics n–2n" pages. | -- Infobox for "Harmonics n–2n" and "Subharmonics n–2n" pages. | ||
-- Called through Template:Infobox | -- Called through Template: Infobox harmonics and Template: Infobox subharmonics. | ||
local p = {} | local p = {} | ||
local getArgs = require("Module:Arguments").getArgs | local getArgs = require("Module:Arguments").getArgs | ||
| Line 11: | Line 11: | ||
-- category names, in one place | -- category names, in one place | ||
local CATEGORY = { harmonics = "Overtone | local CATEGORY = { harmonics = "Overtone scales", subharmonics = "Undertone scales" } | ||
local CATEGORY_PRIME = { harmonics = "Prime overtone | local CATEGORY_PRIME = { harmonics = "Prime overtone scales", subharmonics = "Prime undertone scales" } | ||
local function cents(num, den) | local function cents(num, den) | ||
| Line 26: | Line 26: | ||
local n = tonumber(args[1] or args.n or args.steps) | local n = tonumber(args[1] or args.n or args.steps) | ||
if not n or n < 1 or n ~= math.floor(n) then | if not n or n < 1 or n ~= math.floor(n) then | ||
return '<strong class="error">Template:Infobox | return '<strong class="error">Template:Infobox harmonics requires a positive integer, e.g. <code>{{Infobox harmonics|12}}</code>.</strong>' | ||
end | end | ||
local sub = kind == "subharmonics" | local sub = kind == "subharmonics" | ||
| Line 47: | Line 47: | ||
local sharp, flat, exact | local sharp, flat, exact | ||
if sub then | if sub then | ||
-- degree k has ratio 2n/(2n-k); a fifth needs 2n-k = 4n/3 | -- degree k has ratio 2n/(2n - k); a fifth needs 2n - k = 4n/3 | ||
local m = math.floor(4 * n / 3) | local m = math.floor(4 * n / 3) | ||
if (4 * n) % 3 == 0 then | if (4 * n) % 3 == 0 then | ||
| Line 55: | Line 55: | ||
end | end | ||
else | else | ||
-- degree k has ratio (n+k)/n; a fifth needs n+k = 3n/2 | -- degree k has ratio (n + k)/n; a fifth needs n + k = 3n/2 | ||
local k = n + math.ceil(n / 2) | local k = n + math.ceil(n / 2) | ||
if n % 2 == 0 then | if n % 2 == 0 then | ||
| Line 70: | Line 70: | ||
end | end | ||
local title = string.format("%s %d%s%d | -- no-wrap: otherwise the caption can break after the en dash | ||
local result = infobox. | local title = string.format( | ||
'<span style="white-space: nowrap;">%s %d%s%d</span>', | |||
sub and "Subharmonics" or "Harmonics", | |||
n, | |||
EN_DASH, | |||
2 * n | |||
) | |||
local result = infobox._infobox({ ["Title"] = title, ["Rows"] = data }) | |||
if not debug_mode then | if not debug_mode then | ||
result = result .. categories | result = result .. categories | ||
Latest revision as of 08:10, 11 October 2026
Documentation for this module may be created at Module:Harmonics infobox/doc
-- Module: Harmonics infobox
-- Infobox for "Harmonics n–2n" and "Subharmonics n–2n" pages.
-- Called through Template: Infobox harmonics and Template: Infobox subharmonics.
local p = {}
local getArgs = require("Module:Arguments").getArgs
local infobox = require("Module:Infobox")
local u = require("Module:Utils")
local yesno = require("Module:Yesno")
local EN_DASH = "–"
-- category names, in one place
local CATEGORY = { harmonics = "Overtone scales", subharmonics = "Undertone scales" }
local CATEGORY_PRIME = { harmonics = "Prime overtone scales", subharmonics = "Prime undertone scales" }
local function cents(num, den)
return math.floor(math.log(num / den) / math.log(2) * 1200 * 1000 + 0.5) / 1000
end
local function fifth_row(label, num, den)
return { label, string.format("%d/%d (%sc)", num, den, cents(num, den)) }
end
local function build(frame, kind)
local args = getArgs(frame)
local n = tonumber(args[1] or args.n or args.steps)
if not n or n < 1 or n ~= math.floor(n) then
return '<strong class="error">Template:Infobox harmonics requires a positive integer, e.g. <code>{{Infobox harmonics|12}}</code>.</strong>'
end
local sub = kind == "subharmonics"
local debug_mode = yesno(args.debug, false)
local wtext = yesno(args.wtext)
local sortkey = string.rep("#", string.len(tostring(n)))
local categories = string.format("[[Category:%s|%s]]", CATEGORY[kind], sortkey)
local prime = ""
if u.is_prime(n) then
prime = " (prime)"
categories = categories .. string.format("[[Category:%s|%s]]", CATEGORY_PRIME[kind], sortkey)
end
local data = {}
data[#data + 1] = { "Prime factorization", u._prime_factorization(n) .. prime }
-- the two steps nearest 3/2
local sharp, flat, exact
if sub then
-- degree k has ratio 2n/(2n - k); a fifth needs 2n - k = 4n/3
local m = math.floor(4 * n / 3)
if (4 * n) % 3 == 0 then
exact = { 2 * n, m }
else
sharp, flat = { 2 * n, m }, { 2 * n, m + 1 }
end
else
-- degree k has ratio (n + k)/n; a fifth needs n + k = 3n/2
local k = n + math.ceil(n / 2)
if n % 2 == 0 then
exact = { k, n }
else
sharp, flat = { k, n }, { k - 1, n }
end
end
if exact then
data[#data + 1] = fifth_row("Fifth", exact[1], exact[2])
else
data[#data + 1] = fifth_row("Dual sharp fifth", sharp[1], sharp[2])
data[#data + 1] = fifth_row("Dual flat fifth", flat[1], flat[2])
end
-- no-wrap: otherwise the caption can break after the en dash
local title = string.format(
'<span style="white-space: nowrap;">%s %d%s%d</span>',
sub and "Subharmonics" or "Harmonics",
n,
EN_DASH,
2 * n
)
local result = infobox._infobox({ ["Title"] = title, ["Rows"] = data })
if not debug_mode then
result = result .. categories
end
if wtext then
result = '<syntaxhighlight lang="wikitext">' .. result .. "</syntaxhighlight>"
end
return frame:preprocess(result)
end
function p.harmonics(frame)
return build(frame, "harmonics")
end
function p.subharmonics(frame)
return build(frame, "subharmonics")
end
return p