ratios.mjs - lists whole number ratios for pitch intervals
- Port of pitfalls/lib/ratios.lua - see https://github.com/robmckinnon/pitfalls/blob/main/lib/ratios.lua Copyright (C) 2025 Rob McKinnon and Strudel contributors - see https://codeberg.org/uzu/strudel/src/branch/main/packages/edo/ratios.mjs This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.
7const ratiointervals = {};
FJS Calculators - https://misotanni.github.io/fjs/en/calc.html List of pitch intervals - https://en.wikipedia.org/wiki/List_of_pitch_intervals Gallery of just intervals - https://en.xen.wiki/w/Gallery_of_just_intervals Two letter codes changed to make different interval labels more unique.
13ratiointervals.list = new Map([ 14 [1, ['P1', 'P1', 'P1', 1, 1]], // unison P1 15 [16 / 15, ['m2', 'm2', 'm2_5', 16, 15]], // minor second m2 16 [15 / 14, ['A1', 'A1', 'A1^5_7', 15, 14]], // augmented unison 17 [13 / 12, ['t2', 'm2', 'm2^13', 13, 12]], // tridecimal neutral second 18 [12 / 11, ['N2', 'M2', 'M2_11', 12, 11]], // undecimal neutral second 19 [11 / 10, ['n2', 'm2', 'm2^11_5', 11, 10]], // undecimal submajor second 20 [10 / 9, ['T2', 'M2', 'M2^5', 10, 9]], // classic (whole) tone 21 [9 / 8, ['M2', 'M2', 'M2', 9, 8]], // major second M2 22 [8 / 7, ['S2', 'M2', 'M2_7', 8, 7]], // septimal major second 23 [7 / 6, ['s3', 'm3', 'm3^7', 7, 6]], // septimal minor third 24 [19 / 16, ['o3', 'm3', 'm3^19', 19, 16]], // otonal minor third 25 [6 / 5, ['m3', 'm3', 'm3_5', 6, 5]], // minor third m3 26 [17 / 14, ['t3', 'm3', 'm3^17_7', 17, 14]], // septendecimal supraminor third 27 [11 / 9, ['n3', 'm3', 'm3^11', 11, 9]], // undecimal neutral third 28 [5 / 4, ['M3', 'M3', 'M3^5', 5, 4]], // major third M3 29 [9 / 7, ['S3', 'M3', 'M3_7', 9, 7]], // septimal major third SM3 30 [13 / 10, ['d4', 'd4', 'd4^13_5', 13, 10]], // Barbados third 31 [4 / 3, ['P4', 'P4', 'P4', 4, 3]], // perfect fourth P4 32 [19 / 14, ['N4', 'P4', 'P4^19_7', 19, 14]], // undevicesimal wide fourth 33 [11 / 8, ['n4', 'P4', 'P4^11', 11, 8]], // super-fourth 34 [25 / 18, ['a4', 'A4', 'A4^5,5', 25, 18]], // classic augmented fourth 35 [7 / 5, ['sT', 'd5', 'd5^7_5', 7, 5]], // lesser septimal tritone 36 [45 / 32, ['A4', 'A4', 'A4^5', 45, 32]], // just augmented fourth 37 [17 / 12, ['d5', 'd5', 'd5^17', 17, 12]], // larger septendecimal tritone 38 [10 / 7, ['ST', 'A4', 'A4^5_7', 10, 7]], // greater septimal tritone 39 [13 / 9, ['t5', 'd5', 'd5^13', 13, 9]], // tridecimal diminished fifth 40 [3 / 2, ['P5', 'P5', 'P5', 3, 2]], // perfect fifth P5 41 [14 / 9, ['s6', 'M6', 'm6^7', 14, 9]], // subminor sixth or septimal sixth 42 [25 / 16, ['a5', 'A5', 'A5^5,5', 25, 16]], // classic augmented fifth 43 [11 / 7, ['A5', 'P5', 'P5^11_7', 11, 7]], // undecimal minor sixth 44 [8 / 5, ['m6', 'm6', 'm6_5', 8, 5]], // minor sixth m6 45 [13 / 8, ['N6', 'm6', 'm6^13', 13, 8]], // tridecimal neutral sixth 46 [18 / 11, ['n6', 'M6', 'M6_11', 18, 11]], // undecimal neutral sixth 47 [5 / 3, ['M6', 'M6', 'M6^5', 5, 3]], // just major sixth M6 48 [128 / 75, ['d7', 'd7', 'd7_5,5', 128, 75]], // diminished seventh 49 [17 / 10, ['T6', 'd7', 'd7^17_5', 17, 10]], // septendecimal diminished seventh 50 [12 / 7, ['S6', 'M6', 'M6_7', 12, 7]], // septimal major sixth 51 [7 / 4, ['s7', 'm7', 'm7^7', 7, 4]], // septimal minor seventh 52 [16 / 9, ['m7', 'm7', 'm7', 16, 9]], // lesser minor seventh 53 [9 / 5, ['g7', 'm7', 'm7_5', 9, 5]], // greater just minor seventh 54 [11 / 6, ['n7', 'm7', 'm7^11', 11, 6]], // undecimal neutral seventh 55 [13 / 7, ['N7', 'm7', 'm7^13_7', 13, 7]], // tridecimal neutral seventh 56 [15 / 8, ['M7', 'M7', 'M7^5', 15, 8]], // major seventh 57 [17 / 9, ['T7', 'd8', 'd8^17', 17, 9]], // large septendecimal major seventh 58 [19 / 10, ['d8', 'd8', 'd8^19_5', 19, 10]], // large undevicesimal major seventh 59 [2, ['P8', 'P8', 'P8', 2, 1]], // octave P8 60]);
62ratiointervals.key = function (ratio) { 63 return ratio == null ? '' : ratiointervals.list.get(ratio)?.[0] || ''; 64}; 65 66ratiointervals.label = function (ratio) { 67 return ratio == null ? '' : ratiointervals.list.get(ratio)?.[1] || ''; 68}; 69 70ratiointervals.fjs = function (ratio) { 71 return ratio == null ? '' : ratiointervals.list.get(ratio)?.[2] || ''; 72}; 73 74ratiointervals.nom = function (ratio) { 75 return ratio == null ? null : ratiointervals.list.get(ratio)?.[3] || null; 76}; 77 78ratiointervals.denom = function (ratio) { 79 return ratio == null ? null : ratiointervals.list.get(ratio)?.[4] || null; 80}; 81 82ratiointervals.nearestInterval = function (v) { 83 let min = 1; 84 let match = null; 85 for (const [ratio, _labels] of ratiointervals.list) { 86 const diff = Math.abs((ratio - v) / ratio); 87 if (diff < min) { 88 min = diff; 89 match = ratio; 90 } 91 } 92 return min < 0.01 ? [min, match] : [null, null]; 93}; 94 95export default ratiointervals;