forked from xem/miniMusic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple.html
99 lines (86 loc) · 2.67 KB
/
simple.html
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
<!doctype html>
<meta charset=utf-8>
<body id=b>
<div id=c></div>
<br style=clear:both>
<p>Grey line: <input id=z size=2 value=440> hz. Tempo: <input id=t size=2 value=100> ms<input id=v size=2 value=1 hidden>
<p>Oscillator: <input type=radio name=wave value=sine checked id=sine> sine / <input type=radio name=wave value=square id=square> square / <input type=radio name=wave value=sawtooth id=sawtooth> sawtooth / <input type=radio name=wave value=triangle id=triangle> triangle.
<p>Click on notes (max 1 per column) and press play.
<p><button id=p>PLAY</button>
<p>JS export (smaller if volume = 1 & oscillator = "sine")
<p><textarea id=exp></textarea>
<style>
* { box-sizing: border-box }
#c { width: 5000px; }
.note { width: 20px; height: 20px; float: left; border: 1px solid; }
[line="13"] { background: #ccc }
#exp, #exp2 { width: 90vh; height: 100px }
</style>
<script>
A = new AudioContext;
d = [];
h='';
for(i = 1; i < 26; i++){
d[i] = [];
for(j = 0; j < 250; j++){
h+='<div class=note line='+i+' id=c'+i+'_'+j+' onclick=toggle('+i+','+j+',this,0) onmouseover=toggle('+i+','+j+',this,1) '
+
(
j == 0 && [1,3,6,8,11,13,15,18,20,23].indexOf(i-1) > -1 ? "style=background:#000": (j==0 || i == 13) ? "" : "style=background:#eee"
)
+
'></div>';
}
}
c.innerHTML = h;
mousedown = 0;
onmousedown=e=>{mousedown = 1;}
onmouseup=e=>{mousedown = 0;}
toggle=(i,j,t,f)=>{
if(j==0)return;
if(f && mousedown){
d[i][j] = 1;
}
else if(!f){
d[i][j] ^= 1;
}
t.style.background = d[i][j] ? "#000" : (i == 13) ? "#ccc" : "#eee";
if(d[i][j]){
for(k = 1; k < 26; k++){
if(k != i){
d[k][j] = 0;
top["c"+k+"_"+j].style.background = (k == 13) ? "#ccc" : "#eee";
}
}
}
}
p.onclick=()=>{
A.close();
wave="sine";
if(square.checked) wave = "square";
if(sawtooth.checked) wave = "sawtooth";
if(triangle.checked) wave = "triangle";
df = [];
for(i = 1; i < 26; i++){
for(j = 0; j < 1000; j++){
if(d[i][j]){
df[j-1]=i;
}
}
}
exp.value =
`with(new AudioContext)
with(G=createGain())
for(i in D=[${df}])
with(createOscillator())
if(D[i])
connect(G),
G.connect(destination),
start(i*${(""+t.value/1e3).replace("0.",".")}),
frequency.setValueAtTime(${+z.value}*1.06**(13-D[i]),i*${(""+t.value/1e3).replace("0.",".")}),${(wave=="sine")?"":"type='"+wave+"',"}
gain.setValueAtTime(1,i*${(""+t.value/1e3).replace("0.",".")}),
gain.setTargetAtTime(.0001,i*${(""+t.value/1e3).replace("0.",".")}+${(""+((t.value/1e3)-.02).toFixed(2)).replace("0.",".")},.005),
stop(i*${(""+t.value/1e3).replace("0.",".")}+${(""+((t.value/1e3)-.01).toFixed(2)).replace("0.",".")})`;
eval(exp.value);
}
</script>