Skip to content

Instantly share code, notes, and snippets.

@katai5plate
Last active October 17, 2020 07:40
Show Gist options
  • Save katai5plate/66aff23320ca27b216c8e6d654221934 to your computer and use it in GitHub Desktop.
Save katai5plate/66aff23320ca27b216c8e6d654221934 to your computer and use it in GitHub Desktop.
MOS Calc
const getMOS = (
edo, // 平均律(オクターブ分割数)
tonics = 7, // 音数(nLms の n+m)
noLimit = false
) => {
const UNKNOWN = "Unknown";
const FAIR_ = "Fair ";
const UNFAIR_ = "UnFair ";
const _HAPPY_ = "Happy (-> Porcupine)";
const _MISH_ = "Mish (-> Amity)";
const MAVILA = "Mavila";
const DIATONIC = "Diatonic";
const _MAVILA_ = MAVILA + " / Anti-" + DIATONIC;
const BIGGIE = "Biggie";
const GRUMPY = "Grumpy";
const PERFECT = "Perfect";
const RICE = "Rice";
const FATHER = "Father";
const BUG = "Bug";
const AUG = "Aug";
const BICYCLE = "Bicycle";
const MOSH = "Mosh";
const isMOS = ({ a, b, x, y }) =>
[
a === tonics - b && a === (edo - b * y) / x, // a が成り立つ
b === tonics - a && b === (edo - a * x) / y, // b が成り立つ
x === (edo - b * y) / a, // x が成り立つ
y === (edo - a * x) / b, // y が成り立つ
noLimit ? true : !(Math.abs(x - y) > 8), // 実用的か
].every((x) => x === true);
const getLs = ({ lCount, sCount, lPer, sPer }) =>
`${lCount}L${sCount}s ${lPer}/${sPer}`;
const getET = ({ lCount, sCount, lPer, sPer }) =>
lCount * lPer + sCount * sPer;
const getName = (ls) => {
const { lCount, sCount } = ls;
if (lCount === sCount) return PERFECT;
if (lCount === 0) return UNKNOWN;
switch (tonics) {
case 5:
return [, _HAPPY_, "Classic", FATHER, BUG, PERFECT][lCount];
case 6:
return [, _HAPPY_, RICE, AUG, BICYCLE, GRUMPY, PERFECT][lCount];
case 7:
return [, _HAPPY_, _MAVILA_, MOSH, _MISH_, DIATONIC, GRUMPY, PERFECT][
lCount
];
case 8:
return [
,
_HAPPY_,
RICE,
FAIR_ + FATHER,
"Dim",
UNFAIR_ + FATHER,
BIGGIE,
GRUMPY,
PERFECT,
][lCount];
case 9:
return [
,
_HAPPY_,
FAIR_ + MAVILA,
FAIR_ + AUG,
FAIR_ + BUG,
UNFAIR_ + BUG,
UNFAIR_ + AUG,
UNFAIR_ + MAVILA,
GRUMPY,
PERFECT,
][lCount];
case 10:
return [
,
_HAPPY_,
RICE,
FAIR_ + MOSH,
FAIR_ + BICYCLE,
"Bi-equal",
UNFAIR_ + BICYCLE,
UNFAIR_ + MOSH,
BIGGIE,
GRUMPY,
PERFECT,
][lCount];
}
return UNKNOWN;
};
let res = [];
for (let a of [...Array(tonics).keys()])
for (let b of [...Array(tonics).keys()])
for (let x of [...Array(edo).keys()])
for (let y of [...Array(edo).keys()]) {
const [lCount, sCount, lPer, sPer] = [
x > y ? a : x < y ? b : 0, // L 数
x > y ? b : x < y ? a : 0, // s 数
x > y ? x : x < y ? y : 0, // L 比
x > y ? y : x < y ? x : 0, // s 比
];
const abxyls = { a, b, x, y, lCount, sCount, lPer, sPer };
if (isMOS(abxyls)) {
res.push({
...abxyls,
ls: getLs(abxyls),
name: getName(abxyls),
et: getET(abxyls),
per: lPer / sPer,
});
}
}
return res.filter(
(v, i, s) =>
s.findIndex((e) => e.a * e.b === v.a * v.b && e.x * e.y === v.x * v.y) ===
i
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment