MOS substitution: Difference between revisions
Tags: Mobile edit Mobile web edit |
|||
| Line 37: | Line 37: | ||
where <math>\mathbf{z}</math> is the new step size inserted, <math>\mathbf{y}</math> is the step size in the starting MOS identified with <math>\mathbf{z}</math> by the template MOS, and <math>k</math> is the brightness of the mode of the filling MOS used (<math>k = 0</math> corresponds to the darkest mode; the conventional understanding of "brightness" makes sense as <math>\mathbf{L}</math> (resp. <math>\mathbf{m}</math>) > <math>\mathbf{s}</math>). | where <math>\mathbf{z}</math> is the new step size inserted, <math>\mathbf{y}</math> is the step size in the starting MOS identified with <math>\mathbf{z}</math> by the template MOS, and <math>k</math> is the brightness of the mode of the filling MOS used (<math>k = 0</math> corresponds to the darkest mode; the conventional understanding of "brightness" makes sense as <math>\mathbf{L}</math> (resp. <math>\mathbf{m}</math>) > <math>\mathbf{s}</math>). | ||
== Algorithm == | |||
Rust code for generating MOS substitution scales: | |||
<syntaxhighlight lang="rs> | |||
/// Return the collection of all MOS substitution scales `subst n0 x (n1 y n2 z)` | |||
/// where the template MOS is assumed to have step signature `n0*0 (n1 + n2)*X` (`X` is the slot letter) | |||
/// and the filling MOS has step signature `n1*1 n2*2`. | |||
fn mos_substitution_scales_one_perm(n0: usize, n1: usize, n2: usize) -> Vec<Vec<Letter>> { | |||
let (template, _) = darkest_mos_mode_and_gen_bresenham(n0, n1 + n2); | |||
let (filler, gener) = darkest_mos_mode_and_gen_bresenham(n1, n2); | |||
let filler = filler.into_iter().map(|x| x + 1).collect::<Vec<_>>(); | |||
let gener_size = gener.len(); | |||
(0..(n1 + n2)) | |||
.map(|i| { | |||
subst( | |||
&template, | |||
1usize, | |||
&rotate(&filler, (i * gener_size) % filler.len()), | |||
) | |||
}) | |||
.collect() | |||
} | |||
/// The set of all [MOS substitution](https://en.xen.wiki/w/User:Inthar/MOS_substitution) ternary scales. | |||
pub fn mos_substitution_scales(sig: &[usize]) -> Vec<Vec<Letter>> { | |||
let (n0, n1, n2) = (sig[0], sig[1], sig[2]); | |||
// Only need 3 permutations of (0, 1, 2) for the MOS substitution patterns n0*_ (n1*_ n2*_) | |||
let redundant_list = [ | |||
// n0L (n1m n2s) | |||
mos_substitution_scales_one_perm(n0, n1, n2), | |||
// n1m (n0L n2s) | |||
mos_substitution_scales_one_perm(n1, n2, n0) | |||
.into_iter() | |||
.map(|scale| scale.into_iter().map(|x| (x + 1) % 3).collect()) | |||
.collect(), | |||
// n2s (n0L n1m) | |||
mos_substitution_scales_one_perm(n2, n0, n1) | |||
.into_iter() | |||
.map(|scale| { | |||
scale | |||
.into_iter() | |||
.map(|x| if x == 0 { 2 } else { (x - 1) % 3 }) | |||
.collect() | |||
}) | |||
.collect(), | |||
] | |||
.concat(); | |||
// Canonicalize every scale and remove duplicates | |||
redundant_list | |||
.into_iter() | |||
.map(|scale| least_mode(&scale)) | |||
.sorted() | |||
.dedup() | |||
.collect() | |||
} | |||
</syntaxhighlight> | |||
==Examples== | ==Examples== | ||
In the following tables, the interval class of the generators stacked in the generator sequence is such that the perfect generator has fewer <math>\mathbf{X}</math> steps than the imperfect counterpart. | In the following tables, the interval class of the generators stacked in the generator sequence is such that the perfect generator has fewer <math>\mathbf{X}</math> steps than the imperfect counterpart. | ||