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