Last active
October 17, 2020 07:40
-
-
Save katai5plate/66aff23320ca27b216c8e6d654221934 to your computer and use it in GitHub Desktop.
MOS Calc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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