-
Notifications
You must be signed in to change notification settings - Fork 0
/
business.js
115 lines (95 loc) · 3.42 KB
/
business.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
const business = {
randInt: (maxInt) => Math.floor(Math.random() * maxInt),
selectRandKey: (obj) => {
const keys = Object.keys(obj);
return keys[business.randInt(keys.length)];
},
selectRandIndex: (arr) => business.randInt(arr.length),
JAZZY_BOIS: {
899: "7",
949: "7b5",
999: "9",
1000: "7#9",
},
getJazzyBoi: (manualRoll) => {
// Selects a value from `JAZZY_BOIS` based on a roll against the
// keys of that object.
const numBois = Object.keys(business.JAZZY_BOIS).map(k => parseInt(k));
const roll = manualRoll || business.randInt(Math.max(...numBois));
return business.JAZZY_BOIS[numBois.find(b => b > roll)];
},
jazzify: (jazziness, [index, chord]) => {
// Randomly augments a chord with a `JAZZY_BOI` based on a role
// against `jazziness` (int).
const roll = business.randInt(100);
if (roll < jazziness) {
const jazzyBoi = business.getJazzyBoi();
return [index + jazzyBoi, chord + jazzyBoi];
}
return [index, chord];
},
generateChord: (aScale, keyI, scale, includeDiminished, numerals) => {
// Produce a chord from the scale `aScale`. Retrying if the
// chord is diminished and `includeDiminished` is false.
let next = null;
let nextI = null;
while (next === null) {
nextI = business.randInt(aScale.length);
next = scale[nextI];
if (!includeDiminished && next === "dim") {
next = null;
}
}
const nextNoteI = (nextI + keyI) % aScale.length;
return [numerals[nextI], aScale[nextNoteI] + next];
},
generateChordsForScale: ({
rooted,
includeDiminished,
chordCount,
jazziness,
keyI,
scaleKey,
}) => {
// Generates a progression of `chordCount` chords in the key of
// `music.ROOTS[keyI]` on the `music.SCALES[scaleKey]` scale.
//
// `jazziness` (int) in range [0-100] that determines how likely
// a given chord is to be `jazzified`.
// `includeDiminished` (boolean) determines whether diminished
// chords are allowed in the progression.
const aScale = music.ASCALES[scaleKey][music.ROOTS[keyI]];
const scale = music.SCALES[scaleKey];
const numerals = music.NUMERALS[scaleKey];
let chordCountdown = chordCount;
const chords = [];
if (rooted) {
chords.push(business.jazzify(
jazziness,
[numerals[0], aScale[keyI] + scale[0]],
));
chordCountdown--;
}
for (let i = 0; i < chordCountdown; i++) {
chords.push(business.jazzify(
jazziness,
business.generateChord(aScale, keyI, scale, includeDiminished, numerals),
));
}
return chords;
},
generateRandProg: (settings) => {
// Selects a random key and scale and chord progression
const keyI = business.selectRandIndex(music.ROOTS);
const scaleKey = business.selectRandKey(music.SCALES);
return {
root: music.getRoot(scaleKey, keyI),
scale: scaleKey,
chords: business.generateChordsForScale({
keyI,
scaleKey,
...settings,
}),
}
},
};