Module:MOS in EDO

From Xenharmonic Wiki
Revision as of 04:50, 4 December 2023 by Ganaram inukshuk (talk | contribs) (Created template; work-in-progress, as some functions are still missing)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead: Template:MOS in EDO.

This module displays all MOS scales in a given EDO with a particular generator and number of periods per octave.

Introspection summary for Module:MOS in EDO 
Functions provided (4)
Line Function Params
8 calculate_step_sizes (step_array)
32 mos_step_pattern_to_scale_sig (step_array)
60 calculate_next_mos_step_pattern (step_array)
146 edo_mos_step_patterns (edo, gen_in_edosteps, number_of_periods, temperaments)
Lua modules required (3)
Variable Module Functions used
mos Module:MOS dependency not used
rat Module:Rational dependency not used
utils Module:Utils dependency not used

No function descriptions were provided. The Lua code may have further information.


local mos = require('Module:MOS')
local rat = require('Module:Rational')
local utils = require('Module:Utils')
local p = {}

-- Helper function
-- Given a mos represented as a step pattern in an array, find the sizes of its large and small steps
function p.calculate_step_sizes(step_array)
	local step_array = step_array or { 3, 3, 3, 2, 3, 3, 2 }
	
	-- Initialize large/small step sizes to be some really big numbers
	local large_step_size = -1000000000
	local small_step_size =  1000000000
	
	-- Then iterate through array and update the largest and smallest sizes
	for i = 1, #step_array do
		if step_array[i] > large_step_size then
			large_step_size = step_array[i]
		end
		if step_array[i] < small_step_size then
			small_step_size = step_array[i]
		end
	end
	
	return { ["L"] = large_step_size, ["s"] = small_step_size }
	
end

-- Helper function
-- Given a mos represented as a step pattern in an array, produce the mos's scale sig
-- Scale sigs in this module are implied to be octave-equivalent, as this is meant for edo pages
function p.mos_step_pattern_to_scale_sig(step_array)
	local step_array = step_array or { 5, 5, 5, 3, 5, 5, 3 }
	
	-- Calculate step sizes
	local step_sizes = p.calculate_step_sizes(step_array)
	local large_step_size = step_sizes["L"]
	local small_step_size = step_sizes["s"]
	
	-- Initialize step counts
	local large_step_count = 0
	local small_step_count = 0
	
	-- Then start counting by iterating through array
	for i = 1, #step_array do
		if step_array[i] == large_step_size then
			large_step_count = large_step_count + 1
		elseif step_array[i] == small_step_size then
			small_step_count = small_step_count + 1
		end
	end
	
	return string.format("%iL %is", large_step_count, small_step_count)

end

-- Helper function
-- Given a mos represented as a step pattern in an array, find the next mos
-- Transpiled from python code with aid of ChatGPT
function p.calculate_next_mos_step_pattern(step_array)
	local step_array = step_array or { 5, 5, 5, 3, 5, 5, 3 }
	
	-- Get the step sizes
	local step_sizes = p.calculate_step_sizes(step_array)
    local small_step_size = step_sizes["s"]
    local large_step_size = step_sizes["L"]
    
    local chroma = large_step_size - small_step_size

    local first_step = step_array[1]
    local last_step = step_array[#step_array]

    local next_step_array = {}

    if small_step_size == large_step_size then
        return next_step_array
    end

	-- If the small step is smaller than the chroma, then
	-- - If the first step is the large step and the last step is the small step,
	--   then the replacement rules are L -> Ls and s -> s
	-- - If the first step is the small step and the last step is the large step,
	--   then the replacement rules are L -> sL and s -> s
	-- If the small step is larger than the chroma, then
	-- - If the first step is the large step and the last step is the small step,
	--   then the replacement rules are L -> sL and s -> L
	-- - If the first step is the small step and the last step is the large step,
	--   then the replacement rules are L -> Ls and s -> L
    if small_step_size < chroma then
        local next_large_step_size = chroma
        local next_small_step_size = small_step_size

        if first_step == large_step_size and last_step == small_step_size then
            for i = 1, #step_array do
            	local step = step_array[i]
                if step == large_step_size then
                    table.insert(next_step_array, next_large_step_size)
                    table.insert(next_step_array, next_small_step_size)
                elseif step == small_step_size then
                    table.insert(next_step_array, next_small_step_size)
                end
            end
        else
            for i = 1, #step_array do
            	local step = step_array[i]
                if step == large_step_size then
                    table.insert(next_step_array, next_small_step_size)
                    table.insert(next_step_array, next_large_step_size)
                elseif step == small_step_size then
                    table.insert(next_step_array, next_small_step_size)
                end
            end
        end
    else
        local next_large_step_size = small_step_size
        local next_small_step_size = chroma

        if first_step == large_step_size and last_step == small_step_size then
            for i = 1, #step_array do
            	local step = step_array[i]
                if step == large_step_size then
                    table.insert(next_step_array, next_small_step_size)
                    table.insert(next_step_array, next_large_step_size)
                elseif step == small_step_size then
                    table.insert(next_step_array, next_large_step_size)
                end
            end
        else
            for i = 1, #step_array do
            	local step = step_array[i]
                if step == large_step_size then
                    table.insert(next_step_array, next_large_step_size)
                    table.insert(next_step_array, next_small_step_size)
                elseif step == small_step_size then
                    table.insert(next_step_array, next_large_step_size)
                end
            end
        end
    end

    return next_step_array
end

-- Primary function
-- Create a rectangular horogram depicting a mos for a given pair of generators
function p.edo_mos_step_patterns(edo, gen_in_edosteps, number_of_periods, temperaments)
	
	
	
end


return p