|
|
| Line 16: |
Line 16: |
| -- - 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. |
|
| |
| -- Parse ed function
| |
| function p.parse_ed(unparsed)
| |
| local unparsed = unparsed or "12edo"
| |
|
| |
| -- If the unparsed ed is only a numeric value, default to edo
| |
| if tonumber(unparsed) ~= nil then
| |
| unparsed = unparsed .. "edo"
| |
| end
| |
|
| |
| -- Parse
| |
| local steps, suffix, equave = unparsed:match('^(%d+)([Ee][Dd](.+))$')
| |
| steps = tonumber(steps)
| |
|
| |
| -- If the equave is text, then the equave is:
| |
| -- o: octave, 2/1 (2nd harmonic)
| |
| -- t: tritave or twelfth, 3/1 (3rd harmonic)
| |
| -- f: fifth, 3/2
| |
| -- Make sure these have the correct equave and suffix
| |
| local ratio = "n/a"
| |
| local cents = 0
| |
| local ed_type = ""
| |
| if equave == "o" or equave == "O" or equave == "2" or equave == "2/1" then
| |
| equave = "2"
| |
| ratio = "2/1"
| |
| cents = 1200
| |
| suffix = "edo"
| |
| ed_type = "edo"
| |
| elseif equave == "t" or equave == "T" or equave == "3" or equave == "3/1" then
| |
| equave = "3"
| |
| ratio = "3/1"
| |
| cents = math.log(3) * 1200 / math.log(2)
| |
| suffix = "edt"
| |
| ed_type = "edt"
| |
| elseif equave == "f" or equave == "F" or equave == "3/2" then
| |
| equave = "3/2"
| |
| ratio = "3/2"
| |
| cents = math.log(3/2) * 1200 / math.log(2)
| |
| suffix = "edf"
| |
| ed_type = "edf"
| |
| end
| |
|
| |
| -- For equaves not 2/1, 3/1, or 3/2
| |
| if suffix ~= "edo" and suffix ~= "edt" and suffix ~= "edf" then
| |
| -- If the equave is a number or ratio, convert it to cents
| |
| -- If the equave is already a cent value, extract it
| |
| local is_cents = string.match(equave, '^.+c$') ~= nil
| |
| local is_harmonic = string.match(equave, '^%d+$') ~= nil
| |
| local is_ratio = string.match(equave, '^%d+/%d+$') ~= nil
| |
|
| |
| if is_cents then
| |
| ed_type = "edc"
| |
| cents = tonumber(equave:match('^(.+)c$'))
| |
| elseif is_harmonic then
| |
| ed_type = "edh"
| |
| local harmonic = tonumber(string.match(equave, '^%d+$'))
| |
| cents = math.log(harmonic) * 1200 / math.log(2)
| |
| ratio = string.format("%d/1", harmonic)
| |
| elseif is_ratio then
| |
| ed_type = "edr"
| |
| local num, den = equave:match('^(%d+)/(%d+)$')
| |
| local gcd = utils._gcd(num, den)
| |
| num = num / gcd
| |
| den = den / gcd
| |
| cents = math.log(num / den) * 1200 / math.log(2)
| |
| equave = string.format("%d/%d", num, den)
| |
| ratio = equave
| |
| end
| |
| end
| |
|
| |
| return { ['cents'] = cents, ['equave'] = equave, ['ratio'] = ratio, ['steps'] = steps, ['suffix'] = suffix, ['type'] = ed_type }
| |
| end
| |
|
| |
|
| -- Separate function for edo intro | | -- Separate function for edo intro |
| Line 102: |
Line 30: |
| local intro_text = "" | | local intro_text = "" |
| if ed == 1 then | | if ed == 1 then |
| 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]] where adjacent pitches are one interval of 2/1 (one [[octave]]) apart, or 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]] where adjacent pitches are one interval of 2/1 (one [[octave]]) apart, or exactly/about ''s'' [[¢]]." |
| 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'' [[¢]] each. Each step represents a [[frequency ratio]] of 2<sup>1/''k''</sup>, or the ''kth'' root of 2." | | 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'' [[¢]] each. Each step represents a [[frequency ratio]] of 2<sup>1/''k''</sup>, or the ''kth'' root of 2." |
| end | | end |
|
| |
|
| Line 231: |
Line 159: |
| function p.edc_intro(ed, cents, constant_symbol) | | function p.edc_intro(ed, cents, constant_symbol) |
| return "Equal divisions of an arbitrary cent value currently not supported." | | return "Equal divisions of an arbitrary cent value currently not supported." |
| | end |
| | |
| | -- Parse function |
| | function p.parse(unparsed) |
| | local unparsed = unparsed or "12" |
| | |
| | -- If the unparsed ed is only a numeric value, default to edo |
| | if tonumber(unparsed) ~= nil then |
| | unparsed = unparsed .. "edo" |
| | end |
| | |
| | -- Parse the step count, the suffix, and the equave |
| | local steps, equave = unparsed:match('^(%d+)[Ee][Dd](.+)$') |
| | |
| | local parsed_equave |
| | if equave == "o" or equave == "O" or equave == "2" or equave == "2/1" then |
| | -- Equave is octave |
| | parsed_equave = 2 |
| | elseif equave == "t" or equave == "T" or equave == "3" or equave == "3/1" then |
| | -- Equave is tritave/twelfth |
| | parsed_equave = 3 |
| | elseif equave == "f" or equave == "F" or equave == "3/2" then |
| | -- Equave is fifth |
| | parsed_equave = rat.new(3,2) |
| | elseif string.match(equave, '^%d+$') ~= nil then |
| | -- Equave is arbitrary harmonic (not 2/1 or 3/1) |
| | parsed_equave = tonumber(equave) |
| | elseif string.match(equave, '^%d+/%d+$') ~= nil then |
| | -- Equave is arbitrary ratio (not 3/2) |
| | local num, den = equave:match('^(%d+)/(%d+)$') |
| | parsed_equave = rat.new(tonumber(num), tonumber(den)) |
| | end |
| | |
| | return steps, parsed_equave |
| end | | end |
|
| |
|
| -- Primary function | | -- Primary function |
| function p._ed_intro(ed) | | function p._ed_intro(ed) |
| local ed = ed or "12edo" | | local ed = ed or "12ed4/3" |
| | | |
| local parsed_ed = p.parse_ed(ed) | | local parsed_ed, parsed_equave = p.parse(ed) |
| local ed_type = parsed_ed['type']
| |
| | | |
| -- Intro formats for each possible case | | if rat.eq(2, parsed_equave) then |
| -- - Common abbrevs: edo, edt, edf; these have specially written intros
| | return p.edo_intro(parsed_ed) |
| -- - General harmonic: edh (h-th harmonic)
| | elseif rat.eq(3, parsed_equave) then |
| -- - Arbitrary JI ratio: edr (ratio of p/q) | | return p.edt_intro(parsed_ed) |
| -- - Arbitrary constant: edc
| | elseif rat.eq(rat.new(3,2), parsed_equave) then |
| -- - [[equal]]-step tunings: 1edo, 1edt, 1edf, 1edh, 1edp/q, 1edc
| | return p.edf_intro(parsed_ed) |
| local intro_text = ""
| | elseif rat.is_harmonic(parsed_equave) then |
| if parsed_ed['steps'] == 1 then
| | return p.edh_intro(parsed_ed, parsed_equave) |
| if ed_type == "edo" then | | elseif not rat.is_harmonic(parsed_equave) 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]] where adjacent pitches are one [[octave]], or exactly/about ''s'' [[¢]], from each other."
| | return p.edr_intro(parsed_ed, parsed_equave) |
| elseif ed_type == "edt" then
| |
| intro_text = "'''1 equal division of the tritave''' (abbreviated '''1edt''' or '''1ed3''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one tritave ([[3/1]]), or exactly/about ''s'' [[¢]], apart from each other."
| |
| elseif ed_type == "edf" then | |
| intro_text = "'''1 equal division of the fifth''' (abbreviated '''1edf''' or '''1ed3/2''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one perfect fifth ([[3/2]]), or exactly/about ''s'' [[¢]], apart from each other."
| |
| elseif ed_type == "edh" then
| |
| intro_text = "'''1 equal division of the ''hth'' harmonic''' (abbreviated '''1ed''h''''') is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''h''/1]], or exactly/about ''s'' [[¢]], apart from each other."
| |
| elseif ed_type == "edr" then | |
| intro_text = "'''1 equal division of ''p''/''q''''' (abbreviated '''1ed''p''/''q'''''), also called '''ambitonal sequence of ''p''/''q''''' ('''AS''p''/''q''''') or '''''p''/''q'' [[equal]]-step tuning''', is the [[non-octave]] [[tuning system]] where adjacent pitches are one interval of [[''p''/''q'']], or exactly/about ''s'' [[¢]], apart from each other."
| |
| elseif ed_type == "edc" then
| |
| intro_text = "'''1 equal division of ''c''¢''' (abbreviated '''1ed''c''c'''), also called '''arithmetic pitch sequence of ''c''¢''' ('''APS''c''¢'''), is the [[non-octave]] [[tuning system]] where adjacent pitches are exactly/about ''s'' [[¢]] apart from each other."
| |
| end
| |
| else | | else |
| if ed_type == "edo" then | | return "Input is equal divisions of a cent value or constant (not supported) or an invalid ed." |
| 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'' [[¢]] each. Each step of ''k''edo represents a [[frequency ratio]] of 2<sup>1/''k''</sup>, or the ''kth'' root of 2."
| |
| elseif ed_type == "edt" then
| |
| intro_text = "'''''k'' equal divisions of the tritave''' (abbreviated '''''k''edt''' or '''''k''ed3''') is the [[non-octave]] [[tuning system]] that divides the interval [[3/1]] – also called the [[tritave]] or perfect twelfth – into ''k'' [[equal]] parts of exactly/about ''s'' [[¢]] each. Each step of ''k''edt represents a [[frequency ratio]] of 3<sup>1/''k''</sup>, or the ''kth'' root of 3."
| |
| elseif ed_type == "edf" then
| |
| intro_text = "'''''k'' equal divisions of the fifth''' (abbreviated '''''k''edf''' or '''''k''ed3/2''') is the [[non-octave]] [[tuning system]] that divides the interval [[3/2]], or perfect fifth, into ''k'' [[equal]] parts of exactly/about ''s'' [[¢]] each. Each step of ''k''edf represents a [[frequency ratio]] of (3/2)<sup>1/''k''</sup>, or the ''kth'' root of 3/2."
| |
| elseif ed_type == "edh" then
| |
| intro_text = "'''''k'' equal divisions of the ''hth'' harmonic''' (abbreviated '''''k''ed''h''''') is the [[non-octave]] [[tuning system]] that divides the interval [[''h''/1]], or the ''hth'' harmonic, into ''k'' [[equal]] parts of exactly/about ''s'' [[¢]] each. Each step of ''k''ed''h'' represents a [[frequency ratio]] of ''h''<sup>1/''k''</sup>, or the ''kth'' root of ''h''."
| |
| elseif ed_type == "edr" then
| |
| intro_text = "'''''k'' equal divisions of ''p''/''q''''' (abbreviated '''''k''ed''p''/''q''''') is the [[non-octave]] [[tuning system]] that divides the interval [[''p''/''q'']] into ''k'' [[equal]] pieces of exactly/about ''s'' [[¢]] each. Each step of ''k''ed''p''/''q'' represents the [[frequency ratio]] of (''p''/''q'')<sup>1/''k''</sup>, or the ''kth'' root of ''p''/''q''."
| |
| elseif ed_type == "edc" then
| |
| intro_text = "'''''k'' equal divisions of ''c''¢''' (abbreviated '''''k''ed''c''c''') is the [[non-octave]] [[tuning system]] that divides the interval of ''c'' [[¢]] into ''k'' [[equal]] pieces of exactly/about ''s'' [[¢]] each."
| |
| end
| |
| end | | end |
|
| |
| -- Produce a table of key-value pairs of text to replace
| |
| -- - ''k'': number of steps in ed
| |
| -- - ''s'': size of a step
| |
| -- - ''p''/''q'': equave as a ratio
| |
| -- - ''h'': equave as a harmonic
| |
| -- - ''c'': equave as a cent value
| |
| -- - ''hth'': harmonic as an ordinal
| |
| -- - ''kth'': step count as an ordinal
| |
| local step_size = parsed_ed['cents'] / parsed_ed['steps']
| |
| local text_replace_map = {
| |
| ["''k''"] = parsed_ed['steps'],
| |
| ["''s''"] = utils._round_dec(step_size, 3),
| |
| ["''c''"] = utils._round_dec(parsed_ed['cents'], 3),
| |
| ["''p''/''q''"] = parsed_ed['ratio'],
| |
| ["''h''"] = parsed_ed['equave'],
| |
| ["''hth''"] = ord._ordinal(parsed_ed['equave']),
| |
| ["''kth''"] = ord._ordinal(parsed_ed['steps']),
| |
| ["exactly/about"] = (utils._round(step_size, 3) == step_size and "exactly" or "about")
| |
| }
| |
|
| |
| for key, value in pairs(text_replace_map) do
| |
| intro_text = string.gsub(intro_text, key, value)
| |
| end
| |
|
| |
| return intro_text
| |
| end | | end |
|
| |
|