モジュール:MOSのソースを表示
←
モジュール:MOS
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
-- Module for working with mosses in lua code; this serves as a "library" for -- mos-related modules and thus does not have a corresponding template. -- Functionality includes: -- - Creating/parsing mosses -- - Creating scalesigs (string representations) of mosses -- - Finding certain modes of a mos -- - Finding generators for a mos -- - Producing vectors for simple mos intervals -- - Interval arithmetic, in the form of adding vectors of L's and s's, and -- period/equave-reducing intervals -- - Finding equal tunings for mosses local rat = require('Module:Rational') local utils = require('Module:Utils') local et = require('Module:ET') local p = {} -- Naming scheme for function names: -- - Functions related to mosses don't have any special names. -- - Functions related to a mos's modes generally end with "mode". -- - Functions related to a mos's generators, equave, or period contain the -- corresponding interval as part of its name. -- - Functions related to intervals generally begin with "interval". -- - Interval complement/reduce functions end with "complement" and "reduce". -- - Functions that produce strings generally have the phrase "as string". -- - Functions that "count" something generally end with "count". -- - If a function requires an interval and mos as input, the interval(s) come -- after the mos. -- - Functions that have to do with equal tunings will have "et" in its name. -------------------------------------------------------------------------------- ------------------------------- HELPER FUNCTIONS ------------------------------- -------------------------------------------------------------------------------- function p.find_item_in_table(table, item) local item_found = false for i = 1, #table do if table[i] == item then item_found = true break end end return item_found end -------------------------------------------------------------------------------- -------------------------------- BASE FUNCTIONS -------------------------------- -------------------------------------------------------------------------------- -- Create a new mos. (Contains the number of large and small steps, and equave.) function p.new(nL, ns, equave) local nL = nL or 5 local ns = ns or 2 local equave = equave or 2 return { nL = nL, ns = ns, equave = equave } end -- Pasre a mos from its scalesig. function p.parse(unparsed) local nL, ns, equave = unparsed:match('^(%d+)[Ll]%s*(%d+)[Ss]%s*(.*)$') nL = tonumber(nL) ns = tonumber(ns) equave = equave:match('^%((.*)-equivalent%)$') or equave:match('^⟨(.*)⟩$') or equave:match('^<(.*)>$') or '2/1' -- Assumes this is a rational ratio written a/b equave = rat.parse(equave) if nL == nil or ns == nil or equave == nil then return nil end return p.new(nL, ns, equave) end -------------------------------------------------------------------------------- ------------------------------- STRING FUNCTIONS ------------------------------- -------------------------------------------------------------------------------- -- Construct a string representation (scalesig) for a MOS structure. -- Scalesig is "xL ys", or "xL ys<p/q>" for nonoctave scales. function p.as_string(mos) local suffix = '' if not rat.eq(mos.equave, 2) then suffix = '⟨' .. rat.as_ratio(mos.equave):lower() .. '⟩' end return '' .. mos.nL .. 'L ' .. mos.ns .. 's' .. suffix end -- Construct a longer string representation for a MOS structure. -- Scalesig is "xL ys", or "xL ys (p/q-equivalent)" for nonoctave scales. function p.as_long_string(mos) local suffix = '' if not rat.eq(mos.equave, 2) then suffix = string.format(" (%s-equivalent)", rat.as_ratio(mos.equave):lower()) end return '' .. mos.nL .. 'L ' .. mos.ns .. 's' .. suffix end -- Given an interval as a vector of L's and s's, produce a string "iL + js", -- where i and j are the quantities for L and s. function p.interval_as_string(interval) -- Quantity of L's as a string local L_string = "" if interval['L'] == 0 then L_string = "" elseif interval['L'] == 1 then L_string = "L" else L_string = string.format("%dL", interval['L']) end -- Quantity of s's as a string local s_string = "" if math.abs(interval['s']) == 0 then s_string = "" elseif math.abs(interval['s']) == 1 then s_string = "s" else s_string = string.format("%ds", math.abs(interval['s'])) end if interval['L'] == 0 and interval['s'] == 0 then return "0" elseif interval['L'] == 0 and interval['s'] ~= 0 then return s_string elseif interval['L'] ~= 0 and interval['s'] == 0 then return L_string else return L_string .. (interval['s'] > 0 and " + " or " - ") .. s_string end end -------------------------------------------------------------------------------- ------------------------------- MODE FUNCTIONS --------------------------------- -------------------------------------------------------------------------------- -- Find the brightest (true-mos) mode of a mos, as a string of L's and s's. -- Calculation is based on the definition of a Christoffel word, as the closest -- integer approximation to line y = #s/#L*x. function p.brightest_mode(mos) local nL = mos.nL local ns = mos.ns local d = utils._gcd(nL, ns) if d > 1 then -- use single period mos, with period as new equave nL = utils._round_dec(nL/d) ns = utils._round_dec(ns/d) end local current_L, current_s = 0, 0 local result = '' while current_L < nL or current_s < ns do if (current_s + 1) * nL <= ns * (current_L) then current_s = current_s + 1 result = result .. 's' else current_L = current_L + 1 result = result .. 'L' end end return string.rep(result, d) end -- Find the darkest true-mos mode of a mos. -- It's the reverse of the brightest mode. function p.darkest_mode(mos) local nL = mos.nL local ns = mos.ns local d = utils._gcd(nL, ns) if d > 1 then -- use single period mos, with period as new equave nL = utils._round_dec(nL/d) ns = utils._round_dec(ns/d) end local current_L, current_s = 0, 0 local result = '' while current_L < nL or current_s < ns do if (current_s + 1) * nL <= ns * (current_L) then current_s = current_s + 1 result = 's' .. result -- !esreveR else current_L = current_L + 1 result = 'L' .. result -- !esreveR end end return string.rep(result, d) end -- Given a mos, return a mode based on how it's ranked by modal brightness. -- Ordering here is based on the number of bright gens going DOWN: 0 is the -- brightest mode, 1 is 2nd brightest, etc... function p.mode_from_mos(mos, bright_gens_going_down) return p.rotate_mode(p.brightest_mode(mos), bright_gens_going_down * p.bright_gen_step_count(mos)) end -------------------------------------------------------------------------------- --------------------------- MODE ROTATION FUNCTIONS ---------------------------- -------------------------------------------------------------------------------- -- Given a mos, list all modes in descending order of brightness. function p.modes_by_brightness(mos) local bright_gen_step_count = p.bright_gen_step_count(mos) local period_step_count = p.period_step_count(mos) local modes = {} local current_mode = p.brightest_mode(mos) for i = 1, period_step_count do table.insert(modes, current_mode) current_mode = p.rotate_mode(current_mode, bright_gen_step_count) end return modes end -- List all unique rotations for a mode. Order of modes is by rotation. -- Note: there will always be s/p modes, where s is the number of steps in the -- entered mode, and p is the period of repetition. At most, there will be s -- modes, but if there is a substring of length p that repeats within the mode -- (where p divides s with remainder = 0), then there will be p modes. It's also -- possible to have only one mode, but this can only happen if there is only one -- step size, meaning it's a unary scale (only one step size). function p.mode_rotations(mode_string) local rotations = {} local current_mode = mode_string for i = 1, #mode_string do if not p.find_item_in_table(rotations, current_mode) then table.insert(rotations, current_mode) end current_mode = p.rotate_mode(current_mode) end return rotations end -- Rotate a mode by shifting the step sequence to the left. Negative values -- shift it to the right. Helper function for mode_from_mos(). function p.rotate_mode(mode_string, shift_amt) local shift_amt = shift_amt == nil and 1 or shift_amt % #mode_string -- Defualt is 1 local first = string.sub(mode_string, 1, shift_amt) local second = string.sub(mode_string, shift_amt + 1, #mode_string) return second .. first end -------------------------------------------------------------------------------- ---------------------------- STEP MATRIX FUNCTIONS ----------------------------- -------------------------------------------------------------------------------- -- Convert a single mode (as a string) into a step matrix. This is a listing of -- every interval's step vector in the mode. function p.mode_to_step_matrix(mode_string) local matrix = {} for i = 1, #mode_string + 1 do local steps = i - 1 local interval = p.interval_from_step_sequence(string.sub(mode_string, 0, steps)) table.insert(matrix, interval) end return matrix end -- Given a mos, produce every step matrix for every mode. Modes are listed in -- order of brightness. function p.modes_to_step_matrices(mos) local modes = p.modes_by_brightness(mos) local matrices = {} for i = 1, #modes do table.insert(matrices, p.mode_to_step_matrix(modes[i])) end return matrices end -- Given a single mode (as a string), produce the step matrices for each -- rotation of that mode. Modes are listed in order of rotation. function p.mode_rotations_to_step_matrices(mode_string) local modes = p.mode_rotations(mode_string) local matrices = {} for i = 1, #modes do table.insert(matrices, p.mode_to_step_matrix(modes[i])) end return matrices end -------------------------------------------------------------------------------- --------------- INTERVAL FUNCTIONS FOR PERFECTABLE INTERVALS ------------------- ------------------ (IE, GENERATORS AND PERIOD INTERVALS) ----------------------- -------------------------------------------------------------------------------- -- Compute the bright gen as a vector of L's and s's. -- Bright gen has two sizes: perfect (large) and diminished (small). The size -- given by this function is the large size. function p.bright_gen(mos) local nL = mos.nL local ns = mos.ns local d = utils._gcd(nL, ns) if d > 1 then -- use single period mos, with period as new equave nL = utils._round_dec(nL/d) ns = utils._round_dec(ns/d) end local min_dist = 2; -- the distance we get will always be <= sqrt(2) local current_L, current_s = 0, 0 local result = {['L'] = 0, ['s'] = 0} while current_L < nL or current_s < ns do if (current_s + 1) * nL <= ns * (current_L) then current_s = current_s + 1 else current_L = current_L + 1 end if current_L < nL or current_s < ns then -- check to exclude (current_L, current_s) = (nL, ns) local distance_here = math.abs(nL*current_s - ns*current_L)/math.sqrt(nL^2 + ns^2) if distance_here < min_dist then min_dist = distance_here result['L'] = current_L result['s'] = current_s end end end return result end -- Compute the dark gen as a vector of L's and s's. -- Dark gen has two sizes: augmented (large) and perfect (small). The size given -- by this function is the small size. It's the period complement of the bright -- gen. function p.dark_gen(mos) local bright_gen = p.bright_gen(mos) return p.period_complement(bright_gen, mos) end -- Compute the period as a vector of L's and s's. -- Period intervals only have one size: perfect. function p.period(mos) local gcd = utils._gcd(mos.nL, mos.ns) return { ['L'] = mos.nL / gcd, ['s'] = mos.ns / gcd } end -- Compute the equave as a vector of L's and s's. -- Equave intervals only have one size: perfect. Equave and period intervals are -- the same for single-period mosses. function p.equave(mos) return { ['L'] = mos.nL, ['s'] = mos.ns } end -------------------------------------------------------------------------------- ------------------ INTERVAL FUNCTIONS FOR SIMPLE INTERVALS --------------------- -------------------------------------------------------------------------------- -- Compute the unison as a vector of L's and s's. -- The unison is denoted by moving up from the root by zero steps, and thus does -- not need a mos as input. It's basically a zero vector. -- The unison only has one size: perfect. function p.unison() return { ['L'] = 0, ['s'] = 0 } end -- Compute the vector for a single chroma. It's a large step minus a small step. -- Adding or subtracting any interval by this interval changes its "size". function p.chroma() return { ['L'] = 1, ['s'] = -1 } end -- Compute the vector for an augmented step. It's a large step plus a chroma. function p.augmented_step() return { ['L'] = 2, ['s'] = -1 } end -- Compute the vector for a single large step. function p.large_step() return { ['L'] = 1, ['s'] = 0 } end -- Compute the vector for a single small step. function p.small_step() return { ['L'] = 0, ['s'] = 1 } end -- Compute the vector for a diminished step. It's a small step minus a chroma. function p.diminished_step() return { ['L'] = -1, ['s'] = 2 } end -------------------------------------------------------------------------------- ---------------- INTERVAL FUNCTIONS FOR ARBITRARY INTERVALS -------------------- -------------------------------------------------------------------------------- -- Create a new interval using step counts (the quantities of L's and s's). function p.interval_from_step_counts(i, j) return { ['L'] = i, ['s'] = j } end -- Compute an arbitrary mos interval as a vector of L's and s's. -- The step_count param is the number of mossteps in the interval. EG, in 5L 2s, -- the large 2-mosstep is "LL", so the corresponding vector has L=2, s=0. -- Mossteps larger than the equave (eg, the minor 9th in non-xen music theory) -- are allowed. -- The size_offset denotes whether the interval is the large size (0) or the -- small size (-1). This can exceed the range of [-1, 0] to represent intervals -- raised/lowered by multiple chromas (augmented, diminished, etc). -- Note that for period intervals (eg, the root and equave), there is only one -- size (0 = perfect), so -1 is diminished and 1 is augmented. -- EG, a perfect 4-diastep (perf. 5th) is 4 steps. Since it's the large size, -- the offset is 0, but to get the diminished 5th, the offset should be -1. function p.interval_from_mos(mos, step_count, size_offset) local size_offset = size_offset or 0 -- Optional param; defaults to large size local step_sequence = p.brightest_mode(mos) step_sequence = string.rep(step_sequence, math.ceil(step_count/(mos.nL + mos.ns))) step_sequence = string.sub(step_sequence, 1, step_count) local interval_vector = p.interval_from_step_sequence(step_sequence) local chromas = p.interval_mul(p.chroma(), size_offset) interval_vector = p.interval_add(interval_vector, chromas) return interval_vector end -- Compute an arbitrary mos interval (as a string of steps) as a vector of L's -- and s's. This also serves as a helper function for p.interval_from_mos(). -- Sequences of steps can be entered, where each step is one of five sizes: -- - L: large step. -- - s: small step. -- - c: a chroma; the difference between a large and small step. -- - A: an augmented step; a large step plus a chroma. -- - d: a diminished step, or diesis; a small step minus a chroma. function p.interval_from_step_sequence(step_sequence) local mossteps = #step_sequence local interval_vector = p.unison() for i = 1, mossteps do local step = string.sub(step_sequence, i, i) if step == "L" then interval_vector = p.interval_add(interval_vector, p.large_step()) elseif step == "s" or step == "S" then interval_vector = p.interval_add(interval_vector, p.small_step()) elseif step == "c" then interval_vector = p.interval_add(interval_vector, p.chroma()) elseif step == "A" then interval_vector = p.interval_add(interval_vector, p.augmented_step()) elseif step == "d" then interval_vector = p.interval_add(interval_vector, p.diminished_step()) end end return interval_vector end -------------------------------------------------------------------------------- ------------------------------- COUNT FUNCTIONS -------------------------------- -------------------------------------------------------------------------------- -- Given a mos, compute the number of steps in its bright gen (L's plus s's). function p.bright_gen_step_count(mos) local interval = p.bright_gen(mos) return interval['L'] + interval['s'] end -- Given a mos, compute the number of steps in its dark gen (L's plus s's). function p.dark_gen_step_count(mos) return p.period_step_count(mos) - p.bright_gen_step_count(mos) end -- Given a mos, compute the number of steps in its period (L's plus s's). function p.period_step_count(mos) return (mos.nL + mos.ns) / utils._gcd(mos.nL, mos.ns) end -- Given a mos, compute the number of steps in its equave (L's plus s's). function p.equave_step_count(mos) return mos.nL + mos.ns end -- Given a mos, compute the number of periods it has. function p.period_count(mos) return utils._gcd(mos.nL, mos.ns) end -- Given a vector representing an interval, compute the number of mossteps it -- corresponds to. Knowledge of the corresponding mos is not needed. Intervals -- can be negative, resulting in a negative output. function p.interval_step_count(interval) return interval['L'] + interval['s'] end -- Given a vector representing an interval, compute the number of chromas it was -- raised or lowered by from its large size (for non-period intervals) or its -- perfect size (for period/root/equave intervals). This requires the mos as -- input. -- If the number of chromas from a small (EG minor) interval is desired, then -- using the param size_offset can be used: 0 for chromas from large size, -1 -- for chromas from small size. This can exceed the range [-1, 0] if needed. -- EG, a diminished 2-diastep (dim. 3rd) has the vector {0,2}. It's reached by -- either lowering the major 2-step by 2 chromas, or lowering the minor 2-step -- by 1 chroma. function p.interval_chroma_count(interval, mos, size_offset) local size_offset = size_offset or 0 -- Default of 0. local step_count = p.interval_step_count(interval) local base_interval = p.interval_from_mos(mos, step_count, 0) return interval['L'] - base_interval['L'] - size_offset end -------------------------------------------------------------------------------- ----------------------- INTERVAL ARITHMETIC FUNCTIONS -------------------------- -------------------------------------------------------------------------------- -- Add two intervals together by adding their respective vectors. function p.interval_add(interval_1, interval_2) return { ['L'] = interval_1['L'] + interval_2['L'], ['s'] = interval_1['s'] + interval_2['s'] } end -- Subtract two intervals by subtracting their respective vectors. function p.interval_sub(interval_1, interval_2) return { ['L'] = interval_1['L'] - interval_2['L'], ['s'] = interval_1['s'] - interval_2['s'] } end -- Repeatedly add the same interval to itself. function p.interval_mul(interval, amt) return { ['L'] = interval['L'] * amt, ['s'] = interval['s'] * amt } end -- Check whether two intervals are equal to one another. function p.interval_eq(interval_1, interval_2) return interval_1['L'] == interval_2['L'] and interval_1['s'] == interval_2['s'] end -------------------------------------------------------------------------------- ---------------------- INTERVAL MANIPULATION FUNCTIONS ------------------------- -------------------------------------------------------------------------------- -- Given an interval vector and a mos, find its period complement. This is the -- interval to add to produce the period. function p.period_complement(interval, mos) local sign = p.interval_step_count(interval) < 0 and -1 or 1 local period_vector = p.period(mos) return p.interval_sub(p.interval_mul(period_vector, sign), interval) end -- Given an interval vector and a mos, find its equave complement. This is the -- interval to add to produce the equave. function p.equave_complement(interval, mos) local sign = p.interval_step_count(interval) < 0 and -1 or 1 local equave_vector = p.equave(mos, interval) return p.interval_sub(p.interval_mul(equave_vector, sign), interval) end -- Given an interval vector and a mos, period-reduce it. This works like -- modular arithmetic, so passing a negative interval returns a positive one. function p.period_reduce(interval, mos) local step_count = p.interval_step_count(interval) local reduce_amt = math.floor(step_count / p.period_step_count(mos)) local periods = p.interval_mul(p.period(mos), reduce_amt) return p.interval_sub(interval, periods) end -- Given an interval vector and a mos, equave-reduce it. This works like -- modular arithmetic, so passing a negative interval returns a positive one. function p.equave_reduce(interval, mos) local step_count = p.interval_step_count(interval) local reduce_amt = math.floor(step_count / p.equave_step_count(mos)) local equaves = p.interval_mul(p.equave(mos), reduce_amt) return p.interval_sub(interval, equaves) end -- Invert an interval. This makes an interval negative. function p.invert_interval(interval) return p.interval_mul(interval, -1) end -- Intervals usually denote distances between two scale degrees and should be -- positive values. Normalizing makes a negative interval positive again. function p.normalize_interval(interval) return p.interval_step_count(interval) < 0 and p.interval_mul(interval, -1) or interval end -------------------------------------------------------------------------------- ---------------------------- EQUAL-TUNING FUNCTIONS ---------------------------- -------------------------------------------------------------------------------- -- Given a mos and a step ratio, return an equal tuning (or equal division). -- The step ratio is entered as a 2-element array to allow non-simplified -- ratios to be entered. (The rational module isn't suitable since it simplifies -- ratios.) function p.mos_to_et(mos, step_ratio) local et_size = mos.nL * step_ratio[1] + mos.ns * step_ratio[2] return et.new(et_size, mos.equave, rat.as_ratio(mos.equave)) end -- Given a mos and a step ratio, return the number of et-steps for its bright -- generator. function p.bright_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.bright_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its dark -- generator. function p.dark_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.dark_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its period. function p.period_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.period(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its equave. function p.equave_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.equave(mos), step_ratio) end -- Given an interval vector and step ratio, compute the number of et-steps it -- corresponds to. function p.interval_to_et_steps(interval, step_ratio) return interval['L'] * step_ratio[1] + interval['s'] * step_ratio[2] end -------------------------------------------------------------------------------- ------------------------------- CENT FUNCTIONS --------------------------------- -------------------------------------------------------------------------------- -- Given a mos and a step ratio, return the number of cents for its bright gen. function p.bright_gen_to_cents(mos, step_ratio) local interval_steps = p.interval_to_et_steps(p.bright_gen(mos), step_ratio) local equave_steps = p.equave_to_et_steps(mos, step_ratio) return interval_steps * rat.cents(mos.equave) / equave_steps end -- Given a mos and a step ratio, return the number of cents for its dark gen. function p.dark_gen_to_cents(mos, step_ratio) local interval_steps = p.interval_to_et_steps(p.dark_gen(mos), step_ratio) local equave_steps = p.equave_to_et_steps(mos, step_ratio) return interval_steps * rat.cents(mos.equave) / equave_steps end -- Given a mos and a step ratio, return the number of cents for its period. -- The period is the interval at which the step pattern repeats, so no step -- ratio is needed. function p.period_to_cents(mos) return rat.cents(mos.equave) / p.period_count(mos) end -- Given a mos and a step ratio, return the number of cents for its equave. -- The period is the interval at which the step pattern repeats, and the equave -- is a multiple of that (at least for multi-period mosses), so no step ratio is -- needed. function p.equave_to_cents(mos) return rat.cents(mos.equave) end -- Given an interval vector and step ratio, convert it to cents. This requires -- info about the mos itself. function p.interval_to_cents(interval, mos, step_ratio) local interval_steps = p.interval_to_et_steps(interval, step_ratio) local equave_steps = p.equave_to_et_steps(mos, step_ratio) return interval_steps * rat.cents(mos.equave) / equave_steps end -------------------------------------------------------------------------------- ------------ UNUSED FUNCTIONS OR FUNCTIONS TO MOVE TO OTHER MODULES ------------ -------------------------------------------------------------------------------- -- Given a mos, find the ancestor mos with a target note count (default 10) -- or less; to be moved to tamnams module function p.find_ancestor(mos, target_note_count) local mos = mos or p.new(5, 2) local target_note_count = target_note_count or 10 local z = mos.nL local w = mos.ns while (z ~= w) and (z + w > target_note_count) do local m1 = math.max(z, w) local m2 = math.min(z, w) -- For use with updating ancestor mos chunks local z_prev = z -- Update step ratios z = m2 w = m1 - m2 end return p.new(z, w, mos.equave) end -------------------------------------------------------------------------------- ---------------------------- EQUAL-TUNING FUNCTIONS ---------------------------- -------------------------------------------------------------------------------- -- Given a mos and a step ratio, return an equal tuning (or equal division). -- The step ratio is entered as a 2-element array to allow non-simplified -- ratios to be entered. (The rational module isn't suitable since it simplifies -- ratios.) function p.as_et(mos, step_ratio, suffix) local suffix = suffix or nil local et_size = mos.nL * step_ratio[1] + mos.ns * step_ratio[2] return et.new(et_size, mos.equave, suffix) end -- Given a mos and a step ratio, return the number of et-steps for its bright -- generator. function p.bright_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.bright_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its dark generator. function p.dark_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.dark_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its period. function p.period_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.period(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its equave. function p.equave_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.equave(mos), step_ratio) end -- Given an interval vector and step ratio, compute the number of et-steps it corresponds to. function p.interval_to_et_steps(interval, step_ratio) return interval["L"] * step_ratio[1] + interval["s"] * step_ratio[2] end -------------------------------------------------------------------------------- ------------------------ EQUAL-TUNING STRING FUNCTIONS ------------------------- -------------------------------------------------------------------------------- -- Given a mos and step ratio, return its equal temperament as a string "{steps}\{division}{suffix}". function p.et_string(mos, step_ratio, suffix) local suffix = suffix or nil local et_mos = p.as_et(mos, step_ratio, suffix) return et.as_string(et_mos) end -- Given a mos, return its equal temperament suffix as a string (edo, edt, edf, or ed-p/q). function p.et_suffix(mos) if rat.eq(mos.equave, rat.new(2)) then return "平均律" elseif rat.eq(mos.equave, rat.new(3)) then return "edt" elseif rat.eq(mos.equave, rat.new(3, 2)) then return "edf" else return "ed" .. rat.as_ratio(mos.equave) end end -- Given a mos and a step ratio, return the number of et-steps for its bright -- generator. function p.bright_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.bright_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its dark generator. function p.dark_gen_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.dark_gen(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its period. function p.period_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.period(mos), step_ratio) end -- Given a mos and a step ratio, return the number of et-steps for its equave. function p.equave_to_et_steps(mos, step_ratio) return p.interval_to_et_steps(p.equave(mos), step_ratio) end -- Given an interval vector and step ratio, compute the number of et-steps it corresponds to. function p.interval_to_et_steps(interval, step_ratio) return interval["L"] * step_ratio[1] + interval["s"] * step_ratio[2] end -------------------------------------------------------------------------------- ----------------------------------- TESTER ------------------------------------- -------------------------------------------------------------------------------- -- Tester function function p.tester() --local interval = p.dark_gen(p.new(5,2)) --return p.interval_chroma_count(interval, p.new(5,2), -1) --return p.equave_reduce({['L']=-3,['s']=-1},p.new(5,2)) --return p.interval_from_mos(p.new(5,2), 4, 1) --return p.interval_from_step_sequence("LLLdLLc") --return p.mode_from_mos(p.new(5,2), -90673) --return p.mode_to_step_matrix(p.brightest_mode(p.new(5,4))) --return p.mode_rotations("LssLLssL") --return p.mode_rotations_to_step_matrices("LLsLsAs") --return p.mode_from_mos(p.new(5,2),1) local string_return = "" for i = 1, 7 do string_return = string_return .. p.mode_from_mos(p.new(5,2), i-1) .. "\n" end return string_return end return p
このページで使用されているテンプレート:
モジュール:MOS/doc
(
ソースを閲覧
)
モジュール:MOS
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
アカウント申請
名前空間
モジュール
議論
English
表示
閲覧
ソースを閲覧
履歴表示
その他
検索
案内
メインページ
最近の更新
おまかせ表示
ヘルプ
高度な検索
参加申請
理論
手法
一般理論
コミュニティ
XA Facebook
XA Discord
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報