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
|
import Tone from 'tone'
import StartAudioContext from './startAudioContext'
const isIphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))
const isIpad = (navigator.userAgent.match(/iPad/i))
const isAndroid = (navigator.userAgent.match(/Android/i))
const isMobile = isIphone || isIpad || isAndroid
const isDesktop = ! isMobile
document.body.classList.add(isMobile ? 'mobile' : 'desktop')
const browser = { isIphone, isIpad, isAndroid, isMobile, isDesktop }
function clamp(n,a,b){ return n<a?a:n<b?n:b }
function choice (a){ return a[ Math.floor(Math.random() * a.length) ] }
function mod(n,m){ return n-(m * Math.floor(n/m)) }
function randint(n){ return (Math.random()*n)|0 }
function randrange(a,b){ return a + Math.random() * (b-a) }
function randsign(){ return Math.random() >= 0.5 ? -1 : 1 }
function lerp(n,a,b){ return (b-a)*n+a }
function angle(x0,y0,x1,y1){ return Math.atan2(y1-y0,x1-x0) }
function dist(x0,y0,x1,y1){ return Math.sqrt(Math.pow(x1-x0,2)+Math.pow(y1-y0,2)) }
function xor(a,b){ a=!!a; b=!!b; return (a||b) && !(a&&b) }
function quantize(a,b){ return Math.floor(a/b)*b }
function shuffle(a){
for (var i = a.length; i > 0; i--){
var r = randint(i)
var swap = a[i-1]
a[i-1] = a[r]
a[r] = swap
}
return a
}
// returns a gaussian random function with the given mean and stdev.
function gaussian(mean, stdev) {
let y2;
let use_last = false;
return () => {
let y1;
if (use_last) {
y1 = y2;
use_last = false;
}
else {
let x1, x2, w;
do {
x1 = 2.0 * Math.random() - 1.0;
x2 = 2.0 * Math.random() - 1.0;
w = x1 * x1 + x2 * x2;
} while( w >= 1.0);
w = Math.sqrt((-2.0 * Math.log(w))/w);
y1 = x1 * w;
y2 = x2 * w;
use_last = true;
}
let retval = mean + stdev * y1;
if (retval > 0)
return retval;
return -retval;
}
}
function requestAudioContext (fn) {
if (isMobile) {
const container = document.createElement('div')
const button = document.createElement('div')
button.innerHTML = 'Tap to start - please unmute your phone'
Object.assign(container.style, {
display: 'block',
position: 'absolute',
width: '100%',
height: '100%',
zIndex: '10000',
top: '0px',
left: '0px',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
})
Object.assign(button.style, {
display: 'block',
position: 'absolute',
left: '50%',
top: '50%',
padding: '20px',
backgroundColor: '#7F33ED',
color: 'white',
fontFamily: 'monospace',
borderRadius: '3px',
transform: 'translate3D(-50%,-50%,0)',
textAlign: 'center',
lineHeight: '1.5',
width: '150px',
})
container.appendChild(button)
document.body.appendChild(container)
StartAudioContext.setContext(Tone.context)
StartAudioContext.on(button)
StartAudioContext.onStarted(_ => {
container.remove()
fn()
})
} else {
fn()
}
}
export {
clamp, choice, mod, lerp, angle, dist, xor, quantize,
randint, randrange, randsign, shuffle, gaussian,
browser, requestAudioContext,
}
|