-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
240 lines (221 loc) · 5.25 KB
/
index.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html> <head>
<title>WTab</title>
</head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js">
</script>
<script type="text/javascript">
// csound is the Csound engine object (null as we start)
let csound = null;
// table length
const tlen = 512;
// canvas height
const height = 256;
// breakpoint list for drawing/display
let bkpts = [];
// csound synthesis code
const code = `
ifn ftgen 1,0,` + tlen + `,2,0
instr 1
out linenr(oscili(0dbfs*p4,cpsmidinn(p5),2),0.01,0.5,0.01)
endin
instr 2
ifn ftgen 2,0,16384,30,1,0,sr/(2*cpsmidinn(60))
chnset ifn, "newTable"
endin
`;
// this is the JS function to start Csound
async function start() {
// if the Csound object is not initialised
if(csound == null) {
// import the Csound method from csound.js
const { Csound } = await import('https://www.unpkg.com/@csound/browser@6.18.7/dist/csound.js');
// create a Csound engine object
csound = await Csound();
// set realtime audio (dac) output
await csound.setOption("-odac");
// no displays
await csound.setOption("-d");
// compile csound code
await csound.compileOrc(code);
// start the engine
await csound.start();
}
}
// respond to update button press
async function updateTable() {
// start Csound engine
await start();
// set button text
this.html("update");
// create the wavetable
await createTable();
}
// table array
const table = new Float32Array(tlen);
// created/updated flag
let created = false;
// create/update table
async function createTable(){
// if the table needs to be created/updated
if(!created) {
// read the list of breakpoints, write to array
for(let k = 0; k < bkpts.length - 3; k+=2) {
let y1 = bkpts[k+1];
let y2 = bkpts[k+3];
let x1 = bkpts[k];
let x2 = bkpts[k+2];
let inc = (y2-y1)/(x2-x1);
let a = y1;
// linear interpolation
for(let i=x1; i < x2; i++) {
table[int(i)] = a/height - 0.5;
a += inc;
}
}
// copy the array into table 1
await csound.tableCopyIn(1,table);
// run instr 2 to generate table 2
await csound.inputMessage('i2 0 0');
// wait for table number
let tn = 0;
while(tn != 2)
tn = await csound.getControlChannel('newTable');
// copy table 2 into array for display
let tab2 = await csound.tableCopyOut(tn);
// pos increment
let knc = tab2.length/tlen;
// clear the breakpoint list
bkpts = [];
// write array to breakpoint list
for(let i=0,k=0; i < tlen; i++){
bkpts.push(i);
bkpts.push((tab2[k] + 1)*height/2);
k += knc;
}
// set the created/update flag
created = true;
// clear control channel
await csound.setControlChannel('newTable',0);
}
}
// line draw flag
let lnd = false;
function setup() {
// update button
let but = createButton("start");
but.parent("butts");
but.mousePressed(updateTable)
// canvas clear button
but = createButton("clear");
but.parent("butts");
but.mousePressed(clearCanvas)
// canvas for drawing/display
let cnv = createCanvas(tlen,height);
// disable context menu
cnv.elt.addEventListener("contextmenu",
(e) => e.preventDefault());
cnv.parent("canvas");
// function for mouse down
cnv.mousePressed(startDraw);
// function for mouse up
cnv.mouseReleased(stopDraw);
// function for mouse movement
cnv.mouseMoved(lineDraw);
// create keys buttons
notes = [48,50,51,55,58,60];
notes.forEach(addButton);
}
// function to create a key button
function addButton(b,n) {
// b is the note number
let but = createButton(b.toString(),b.toString());
but.parent("keys");
// mouse down
but.mousePressed(noteon);
// mouse up
but.mouseReleased(noteoff);
}
// this draws background and wavetable
function draw() {
background(220);
let ix = 0;
let iy = height/2;
stroke(0);
// draw a line connecting each breakpoint
for(let i = 0; i < bkpts.length; i+=2) {
line(ix,iy,bkpts[i],bkpts[i+1]);
ix = bkpts[i];
iy = bkpts[i+1];
}
// draw a line at the Y centre
stroke(255, 0, 0);
line(0,height/2,tlen,height/2);
}
// this starts drawing with mouse
function startDraw(){
lnd = true;
}
// this stops drawing with mouse
function stopDraw() {
lnd = false;
}
// holds max x pos
let ixmax = 0;
// this function draws a wavetable
function lineDraw() {
// if we are in drawing mode
if(lnd && !created) {
// take X and Y positions
let x = mouseX;
let y = mouseY;
// if X is beyond the current X pos
// and less than the table length
if(x > ixmax && x < tlen) {
// add (x,y) to the breakpoints list
bkpts.push(x);
bkpts.push(y);
// update the max value of x
ixmax = x;
}
}
}
// clear canvas
function clearCanvas() {
// empty breakpoint list
bkpts = [];
// unset flags
lnd = false;
created = false;
// reset max x pos
ixmax = 0;
}
// mouse down function
async function noteon() {
// get the button value
let note = this.elt.value;
// create the event command: negative p3 to hold
let s = "i1." + note + " 0 -1 0.2 " + note;
// send it to the Csound engine
if(csound) await csound.inputMessage(s)
}
// mouse up function
async function noteoff() {
// get the button value
let note = this.elt.value;
// create the event command: negative p1 to release
let s = "i-1." + note + " 0 1 0.2 " + note;
// send it to the Csound engine
if(csound) await csound.inputMessage(s);
}
</script>
<body>
<h1>WTab</h1>
<p><div id="butts"> </div></p>
<p><div id="canvas"> </div></p>
<p><div id="keys"> </div></p>
<hr>
<p><a href="./readme.html">README</a></p>
<!-- hhmts start -->Last modified: Sat Sep 28 22:06:03 IST 2024 <!-- hhmts end -->
</body> </html>