forked from bkarln/STEREOtype
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.js
117 lines (108 loc) · 3 KB
/
util.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
116
117
// Gera um número aleatório.
Math.randFloat = function (min, max) {
return Math.random() * (max - min) + min;
};
// Gera um número inteiro.
Math.randInt = function (min, max) {
return Math.floor(Math.random() * (max - min)) + min;
};
// Gera um array de inteiros únicos.
Math.randInts = function (min, max, n) {
let s = new Set();
while (s.size < n) {
s.add(Math.randInt(min, max));
}
let a = Array.from(s);
a.sort((a, b) => a - b);
return a;
};
// Limita um valor a um intervalo específico.
Math.clamp = function (min, val, max) {
return Math.min(Math.max(val, min), max);
};
// Função de interpolação com suavização, easing.
Math.easeInOutQuad = function (t, b, c, d) {
t /= d / 2;
if (t < 1) return c / 2 * t * t + b;
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
};
// Embaralha aleatoriamente os elementos de um array.
Array.prototype.shuffle = function () {
var j, x, i;
for (i = this.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = this[i];
this[i] = this[j];
this[j] = x;
}
};
// Converte uma cor hexadecimal em um objeto RGB.
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
// Gerar um array de batidas (beats) aleatórias em uma medida musical.
function randomBeatArray(notes, measureLength) {
let allPositions = [];
for (let i = 0; i < measureLength; i++) {
allPositions.push(i);
allPositions.push(i + .5);
}
allPositions.shuffle();
allPositions.splice(notes, allPositions.length - notes);
allPositions.sort((a, b) => a - b);
return allPositions;
}
// Encontrar a batida mais próxima em um array de batidas.
function getClosestBeat(beats, val) {
let valTokens = val.split(':');
val = Number(valTokens[0]) * 4 + Number(valTokens[1]) + Number(valTokens[2]) / 4;
val -= .32;
let bestDelta = Number.MAX_SAFE_INTEGER;
let bestI = -1;
for (let i = 0; i < beats.length; i++) {
let delta = val - beats[i];
if (Math.abs(delta) < Math.abs(bestDelta)) {
bestDelta = delta;
bestI = i;
}
}
return { beat: bestI, offset: bestDelta };
}
// Gera uma escala musical aleatória.
function randomScale() {
let notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
notes = notes.concat(notes);
let scaleStart = Math.randInt(0, 12);
notes = notes.slice(scaleStart, scaleStart + 12);
let offsets;
while (true) {
offsets = new Set(Math.randInts(0, 12, 7));
let success = true;
for (let i = 0; i < 12; i++) {
let a = offsets.has(i), b = offsets.has((i + 1) % 12), c = offsets.has((i + 2) % 12);
if (a && b && c) {
success = false;
break;
}
if (!a && !b && !c) {
success = false;
break;
}
}
if (success) {
break;
}
}
for (let i = 11; i >= 0; i--) {
if (!offsets.has(i)) {
notes.splice(i, 1);
}
}
return notes;
}