Module:Harmonics in edo

Revision as of 03:11, 29 July 2021 by Inthar (talk | contribs)
This page is deprecated. It is being kept for posterity and for reference, but is no longer being actively maintained.

If you have contributions to add to this page, it would be advisable to add them to a different, related page instead.

When writing other pages, avoid including links to this page.

Used in Template:Odd harmonics in edo.


local p = {}

local function edoprox(edo, odds, title, prec)
  local f = 1/edo
  local eps = .0001
  local todd = {'! colspan="2" | Odd harmonic '}
  local tapprox = {'! colspan="2" | Approximation '}
  local tabs = {'! rowspan="2" | Error \n! absolute ([[cent|¢]]) '}
  local trel = {'! [[Relative error|relative]] (%) '}
  local tdeg = {'! colspan="2" | Steps ([[octave reduction|reduced]])'}
  local tfs = {'! colspan="2" | [[Fifthspan]]'}
  local fmt_approx = string.format(' %%.%df', prec)
  local fmt_abs = string.format(' %%+.%df', prec)
  local fmt_rel = ' %+.0f'
  for _, p in pairs(odds) do
    s = math.log(p) / math.log(2)
    v = s*edo
    ev = math.floor(v + .5)
    m = math.floor(math.log(3)/math.log(2)*edo + .5)
    table.insert(todd, ' ' .. p )
    table.insert(tapprox, string.format(fmt_approx, 1200*(ev % edo)/edo) )
    table.insert(tabs, string.format(fmt_abs, 1200 * (ev - v ) / edo))
    table.insert(trel, string.format(fmt_rel, 100 * (ev - v)))
    table.insert(tdeg, ' ' .. ev .. ' ('.. ev % edo .. ')')
    diatonic_edo = m/edo > 4/7 and m/edo < 3/5 and gcd(m, edo) == 1
    if(diatonic_edo) then -- if the best fifth = m\edo is diatonic AND gcd(m, edo) == 1
    	fs = 0
    	position = 0
    	while position ~= ev do
    		fs = fs + 1
    		position = (position + m) % edo
    	end
    	if (fs > edo/2) then
    		fs = fs - edo
    	end
    	table.insert(tfs, ' ' .. fs )
    end
  end
  local titleMarkup = ''
  if title then
	titleMarkup = '|-\n|+ ' .. title .. '\n'

  end
  noFifthSpan = '{| class="wikitable center-all"\n' ..
	titleMarkup ..
	'|-\n' ..
	table.concat(todd, '\n!') .. '\n' ..
    '|-\n' ..
    table.concat(tabs, '\n|') .. '\n' ..
    '|-\n' ..
	table.concat(trel, '\n|') .. '\n' ..
    '|-\n' ..
  table.concat(tdeg, '\n|') .. '\n' ..
    '|}'
    if (diatonic_edo) then
    	return noFifthSpan .. 
  table.concat(tfs, '\n|') .. '\n' ..
    '|}'
    else
    	return noFifthspan
    end
end

local odds = { 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43 }

function gcd(a, b)
	if (b ~= 0) then
		return a
	else 
		return gcd(y, x%y)
	end
end

function p.harmonics_in_edo (frame)
  local edo = frame.args[1] or frame.args['edo'] or 12 -- edo (default=12)
  local columns = frame.args['columns'] or 15 -- number of columns (default = 15, harmonics 3 to 31)
  local start = frame.args['start'] or 1 -- start column, default: start with harmonic 3
  local title = frame.args['title'] or 'Approximation of odd harmonics in ' .. edo .. 'edo'
  local prec = frame.args['prec'] or 1 -- for now only variable precision for abs error
  return edoprox( edo, {unpack(odds, start, start+columns-1)}, title, prec)
end

return p;