1879 lines
65 KiB
JavaScript
1879 lines
65 KiB
JavaScript
|
// Webmodular https://www.g200kg.com/docs/webmodular/
|
||
|
// Originally by g200kg
|
||
|
// Modified by Tomoya Matsuura so that working with touch events(2020/07/02).
|
||
|
var samplerate;
|
||
|
var stereo = 1;
|
||
|
var audioif;
|
||
|
var audiomix;
|
||
|
var outbufsize = 1024;
|
||
|
var outbufsize2 = outbufsize * 2;
|
||
|
var outquenum = 5;
|
||
|
var app;
|
||
|
var ctx;
|
||
|
var imgpanel;
|
||
|
var imgknobs = new Array();
|
||
|
var mouseX, mouseY;
|
||
|
var jinum = jonum = 0;
|
||
|
var colnum = 0;
|
||
|
//var cablecol = [0xcc0000, 0xcc4400, 0xcc8800, 0xcccc00, 0x88cc00, 0x44cc00, 0x00cc00, 0x00cc44, 0x00cc88,
|
||
|
// 0x00cccc, 0x0088cc, 0x0044cc, 0x0000cc, 0x4400cc, 0x8800cc, 0xcc00cc, 0xcc0088, 0xcc0044, ];
|
||
|
var cablecol = [0xcc0000, 0x00cccc, 0xcc4400, 0x0088cc, 0xcc8800, 0x0044cc, 0xcccc00, 0x0000cc, 0x88cc00, 0x4400cc, 0x44cc00, 0x8800cc, 0x00cc00, 0xcc00cc, 0x00cc44, 0xcc0088, 0x00cc88, 0xcc0044, ];
|
||
|
|
||
|
|
||
|
|
||
|
window.addEventListener("message", webMidiLinkRecv, false);
|
||
|
function webMidiLinkRecv(event) {
|
||
|
var msg = event.data.split(",");
|
||
|
switch (msg[0]) {
|
||
|
case "link":
|
||
|
switch (msg[1]) {
|
||
|
case "reqpatch":
|
||
|
LinkSend(event.source, "link,patch," + GetPatchString());
|
||
|
break;
|
||
|
case "setpatch":
|
||
|
SetPatchString(msg[2]);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case "midi":
|
||
|
switch (parseInt(msg[1], 16) & 0xf0) {
|
||
|
case 0x80:
|
||
|
app.keyboard.key.NoteOff(parseInt(msg[2], 16));
|
||
|
break;
|
||
|
case 0x90:
|
||
|
var velo = parseInt(msg[3], 16);
|
||
|
if (velo > 0)
|
||
|
app.keyboard.key.NoteOn(parseInt(msg[2], 16), velo);
|
||
|
else
|
||
|
app.keyboard.key.NoteOff(parseInt(msg[2], 16));
|
||
|
break;
|
||
|
case 0xb0:
|
||
|
if (parseInt(msg[2], 16) == 0x78) {
|
||
|
app.keyboard.key.AllOff();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
function LinkSend(win, s) {
|
||
|
win.postMessage(s, "*");
|
||
|
}
|
||
|
function LinkReady() {
|
||
|
LinkSend(window.parent, "link,ready");
|
||
|
}
|
||
|
function GetPatchString() {
|
||
|
return CmdSave();
|
||
|
}
|
||
|
function SetPatchString(s) {
|
||
|
CmdLoad(s);
|
||
|
}
|
||
|
function getXY(e) {
|
||
|
var rc = e.target.getBoundingClientRect();
|
||
|
mouseX = Math.floor(e.clientX - rc.left);
|
||
|
mouseY = Math.floor(e.clientY - rc.top);
|
||
|
if (mouseX < 0) mouseX = 0;
|
||
|
if (mouseY < 0) mouseY = 0;
|
||
|
}
|
||
|
function getXYTouch(e){
|
||
|
var touch =e.changedTouches[0];
|
||
|
var rc = touch.target.getBoundingClientRect()
|
||
|
mouseX = Math.floor(touch.clientX - rc.left);
|
||
|
mouseY = Math.floor(touch.clientY - rc.top);
|
||
|
if (mouseX < 0) mouseX = 0;
|
||
|
if (mouseY < 0) mouseY = 0;
|
||
|
}
|
||
|
function Rect(x, y, w, h) {
|
||
|
this.ty = 10000;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.w = w;
|
||
|
this.h = h;
|
||
|
this.Draw = function() {
|
||
|
ctx.lineWidth = 1;
|
||
|
ctx.strokeStyle = "#000000";
|
||
|
ctx.strokeRect(x, y, w, h);
|
||
|
}
|
||
|
this.MouseDown = function(x,y) {
|
||
|
}
|
||
|
this.MouseMove = function(x,y) {
|
||
|
}
|
||
|
this.MouseUp = function(x,y) {
|
||
|
}
|
||
|
}
|
||
|
function Jack(x, y, ty,col) {
|
||
|
this.ty = ty;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.w = 16;
|
||
|
this.h = 16;
|
||
|
this.connect = null;
|
||
|
this.fanout = 0;
|
||
|
if (ty == 0)
|
||
|
this.pnum = jinum++;
|
||
|
else
|
||
|
this.pnum = jonum++;
|
||
|
this.col = cablecol[colnum];
|
||
|
if (ty == 0) {
|
||
|
if (++colnum >= 18)
|
||
|
colnum = 0;
|
||
|
}
|
||
|
if (ty != 0) {
|
||
|
try {
|
||
|
this.buf = new Float32Array(128);
|
||
|
} catch (e) {
|
||
|
this.buf = new Array(128);
|
||
|
}
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.buf[i] = 0;
|
||
|
}
|
||
|
this.Draw = function() {
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
return;
|
||
|
if (this.connect != null) {
|
||
|
this.Cable(this, this.connect.x + 8, this.connect.y + 12, this.col, 0);
|
||
|
}
|
||
|
}
|
||
|
this.FillBuf = function(v) {
|
||
|
var out = this.buf;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
out[i] = v;
|
||
|
}
|
||
|
this.Connect = function(jck) {
|
||
|
var jIn = this;
|
||
|
var jOut = jck;
|
||
|
if (this.ty != 0) {
|
||
|
jIn = jck;
|
||
|
jOut = this;
|
||
|
}
|
||
|
if (jIn.connect != null) {
|
||
|
if (jIn.connect.fanout > 0)
|
||
|
--(jIn.connect.fanout);
|
||
|
}
|
||
|
jIn.connect = jOut;
|
||
|
if (jOut != null)
|
||
|
++jOut.fanout;
|
||
|
}
|
||
|
this.Cable = function(j, x, y, col, f) {
|
||
|
var mx = (j.x + 8 + x) / 2;
|
||
|
var my = Math.max(j.y+12, y)+40;
|
||
|
ctx.beginPath();
|
||
|
ctx.moveTo(j.x + 8, j.y+12);
|
||
|
ctx.bezierCurveTo(mx, my, mx, my, x, y);
|
||
|
|
||
|
var r = (col >> 16) & 0xff;
|
||
|
var g = (col >> 8) & 0xff;
|
||
|
var b = col & 0xff;
|
||
|
for (var i = 3; i; --i) {
|
||
|
ctx.strokeStyle = "#" + ("000000" + ((r << 16) + (g << 8) + b).toString(16)).slice(-6);
|
||
|
if (r < 200)
|
||
|
r += Math.floor((200 - r) / 3);
|
||
|
if (g < 200)
|
||
|
g += Math.floor((200 - g) / 3);
|
||
|
if (b < 200)
|
||
|
b += Math.floor((200 - b) / 3);
|
||
|
ctx.lineWidth = i;
|
||
|
ctx.lineCap = "round";
|
||
|
ctx.stroke();
|
||
|
}
|
||
|
switch (f) {
|
||
|
case 1:
|
||
|
ctx.lineWidth = 2;
|
||
|
ctx.strokeStyle = "#00ff00";
|
||
|
ctx.beginPath();
|
||
|
ctx.arc(x, y, 8, 0, Math.PI * 2, true);
|
||
|
ctx.stroke();
|
||
|
break;
|
||
|
case 2:
|
||
|
ctx.lineWidth = 2;
|
||
|
ctx.strokeStyle = "#ff0000";
|
||
|
ctx.beginPath();
|
||
|
ctx.moveTo(x - 8, y - 8);
|
||
|
ctx.lineTo(x + 8, y + 8);
|
||
|
ctx.moveTo(x + 8, y - 8);
|
||
|
ctx.lineTo(x - 8, y + 8);
|
||
|
ctx.stroke();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
this.MouseDown = function(x,y) {
|
||
|
}
|
||
|
this.MouseMove = function(x,y) {
|
||
|
}
|
||
|
this.MouseUp = function(x,y) {
|
||
|
}
|
||
|
}
|
||
|
function Knob(x, y, w, h, img, step, def) {
|
||
|
this.ty = 100;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.w = w;
|
||
|
this.h = h;
|
||
|
this.x0 = 0;
|
||
|
this.y0 = 0;
|
||
|
this.v0 = 0;
|
||
|
this.img = img;
|
||
|
this.step = step;
|
||
|
this.val = def;
|
||
|
this.Draw = function() {
|
||
|
if (typeof (gadget) != "undefined" || imgknobs[img] == undefined)
|
||
|
return;
|
||
|
var n = Math.floor(this.val * step);
|
||
|
if (this.val == 1)
|
||
|
--n;
|
||
|
ctx.drawImage(imgknobs[img], 0, n * h, w, h, this.x, this.y, w, h);
|
||
|
}
|
||
|
this.Set = function(v) {
|
||
|
if (v < 0)
|
||
|
v = 0;
|
||
|
if (v > 1)
|
||
|
v = 1;
|
||
|
if (this.step > 1)
|
||
|
v = Math.floor(v * (this.step - 1)) / (this.step - 1);
|
||
|
this.val = v;
|
||
|
}
|
||
|
this.MouseDown = function(x, y) {
|
||
|
this.x0 = x;
|
||
|
this.y0 = y;
|
||
|
this.v0 = this.val;
|
||
|
}
|
||
|
this.MouseMove = function(x, y) {
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
return;
|
||
|
this.Set(this.v0 + (x - this.x0 - y + this.y0) * 0.01);
|
||
|
this.Draw();
|
||
|
}
|
||
|
this.MouseUp = function(x, y) {
|
||
|
}
|
||
|
}
|
||
|
function Switch(x, y, w, h, img, step, def) {
|
||
|
this.ty = 102;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.w = w;
|
||
|
this.h = h;
|
||
|
this.img = img;
|
||
|
this.step = step;
|
||
|
this.val = def;
|
||
|
this.Draw = function() {
|
||
|
if (typeof (gadget) != "undefined" || imgknobs[img] == undefined)
|
||
|
return;
|
||
|
var n = Math.floor(this.val * this.step);
|
||
|
if (this.val == 1)
|
||
|
--n;
|
||
|
ctx.drawImage(imgknobs[img], 0, n * this.h, this.w, this.h, this.x, this.y, this.w, this.h);
|
||
|
}
|
||
|
this.Set = function(v) {
|
||
|
if (v < 0)
|
||
|
v = 0;
|
||
|
if (v > 1)
|
||
|
v = 1;
|
||
|
this.val = v;
|
||
|
}
|
||
|
this.MouseDown = function(x, y) {
|
||
|
this.MouseMove(x, y);
|
||
|
}
|
||
|
this.MouseMove = function(x, y) {
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
return;
|
||
|
this.Set(Math.floor((1 - (y - this.y) / this.h) * this.step) / (this.step - 1));
|
||
|
this.Draw();
|
||
|
}
|
||
|
this.MouseUp = function(x, y) {
|
||
|
}
|
||
|
}
|
||
|
function Slider(x, y,def) {
|
||
|
this.ty = 101;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.w = 16;
|
||
|
this.h = 65;
|
||
|
this.val = def;
|
||
|
this.vala = (Math.pow(1000, this.val) - 1) * 0.0001;
|
||
|
this.v0 = 0;
|
||
|
this.x0 = 0;
|
||
|
this.y0 = 0;
|
||
|
this.Draw = function() {
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
return;
|
||
|
ctx.drawImage(imgknobs["slider"], this.x, this.y + 50 - this.val * 50);
|
||
|
}
|
||
|
this.Set=function(v) {
|
||
|
if (v < 0)
|
||
|
v = 0;
|
||
|
if (v > 1)
|
||
|
v = 1;
|
||
|
this.val = v;
|
||
|
this.vala = (Math.pow(100, this.val) - 1) * 0.04;
|
||
|
}
|
||
|
this.MouseDown = function(x, y) {
|
||
|
this.x0 = x;
|
||
|
this.y0 = y;
|
||
|
this.v0 = this.val;
|
||
|
}
|
||
|
this.MouseMove = function(x, y) {
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
return;
|
||
|
this.Set(this.v0 + (this.y0 - y) * 0.01);
|
||
|
this.Draw();
|
||
|
}
|
||
|
this.MouseUp = function(x,y) {
|
||
|
}
|
||
|
}
|
||
|
var cnt = 0;
|
||
|
function Key(x, y) {
|
||
|
this.ty = 900;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
if (typeof(gadget) == "undefined")
|
||
|
this.w = 448;
|
||
|
else
|
||
|
this.w = 272;
|
||
|
this.h = 64;
|
||
|
this.gate = 0;
|
||
|
this.cv = 0;
|
||
|
this.retrig = 0;
|
||
|
this.lastn = -1;
|
||
|
this.table = [
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,
|
||
|
27, -1, 13, 15, -1, 18, 20, 22, -1, 25, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, 7, 4, 3, 16, -1, 6, 8, 24, 10, -1, 13, 11, 9, 26,
|
||
|
28, 12,17,1,19,23,5,14,2,21,0,-1,-1,-1,-1,-1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 14, -1,
|
||
|
];
|
||
|
this.press = new Array();
|
||
|
this.Draw = function() {
|
||
|
}
|
||
|
this.KeyPosX = function(n) {
|
||
|
return Math.floor(n / 12) * 112 + [0, 12, 16, 28, 32, 48, 60, 64, 76, 80, 92, 96][n % 12];
|
||
|
}
|
||
|
this.KeyPosY = function(n) {
|
||
|
return [40, 0, 40, 0, 40, 40, 0, 40, 0, 40, 0, 40][n % 12];
|
||
|
}
|
||
|
this.DrawKey = function(n) {
|
||
|
// if (this.lastn != n) {
|
||
|
var nmax = 48;
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
nmax = 29;
|
||
|
ctx.drawImage(imgpanel, this.x, this.y, this.w, this.h, this.x, this.y, this.w, this.h);
|
||
|
if (n >= 0 && n < nmax) {
|
||
|
var y = this.KeyPosY(n);
|
||
|
var w = (y != 0) ? 16 : 8;
|
||
|
var h = (y != 0) ? 24 : 40;
|
||
|
ctx.drawImage(imgknobs["keypress"], this.KeyPosX(n), y, w, h, this.x + this.KeyPosX(n), this.y + y, w, h);
|
||
|
}
|
||
|
this.lastn = n;
|
||
|
// }
|
||
|
}
|
||
|
this.MouseDown = function(x, y) {
|
||
|
this.gate = 1;
|
||
|
this.MouseMove(x, y);
|
||
|
}
|
||
|
this.MouseMove = function(x, y) {
|
||
|
var n;
|
||
|
x = (x - this.x);
|
||
|
if (y >= this.y + 40) {
|
||
|
x = Math.floor(x / 16);
|
||
|
if (x < 0)
|
||
|
x = 0;
|
||
|
if (x >= 28)
|
||
|
x = 27;
|
||
|
n = Math.floor(x / 7) * 12 + [0, 2, 4, 5, 7, 9, 11][x % 7];
|
||
|
}
|
||
|
else {
|
||
|
var xx = x + 5;
|
||
|
if (xx % 16 < 10) {
|
||
|
var xxx = Math.floor(xx / 16) % 7;
|
||
|
if (xxx == 1 || xxx == 2 || xxx == 4 || xxx == 5 | xxx == 6) {
|
||
|
x = Math.floor(x / 16);
|
||
|
n = Math.floor(x / 7) * 12 + [0, 1, 3, 0, 6, 8, 10][xxx];
|
||
|
this.cv = n / 12 * 0.2;
|
||
|
this.DrawKey(n);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
x = Math.floor(x / 16);
|
||
|
if (x < 0)
|
||
|
x = 0;
|
||
|
if (x >= 28)
|
||
|
x = 27;
|
||
|
}
|
||
|
n = Math.floor(x / 7) * 12 + [0, 2, 4, 5, 7, 9, 11][x % 7];
|
||
|
this.cv = n / 12 * 0.2;
|
||
|
if (this.lastn >= 0 && n >= 0 && n != this.lastn)
|
||
|
this.retrig = 1;
|
||
|
this.DrawKey(n);
|
||
|
}
|
||
|
this.MouseUp = function(x, y) {
|
||
|
this.gate = 0;
|
||
|
this.DrawKey(-1);
|
||
|
}
|
||
|
this.AllOff = function() {
|
||
|
this.press.length = 0;
|
||
|
this.gate = 0;
|
||
|
this.DrawKey(-1);
|
||
|
}
|
||
|
this.NoteOn = function(n,v) {
|
||
|
for (var i = 0; i < this.press.length; ++i) {
|
||
|
if (this.press[i] == n)
|
||
|
break;
|
||
|
}
|
||
|
if (i == this.press.length) {
|
||
|
this.gate = 1;
|
||
|
this.retrig = 1;
|
||
|
n -= 36;
|
||
|
this.cv = n / 60;
|
||
|
this.DrawKey(n);
|
||
|
}
|
||
|
}
|
||
|
this.NoteOff = function(n) {
|
||
|
for (var i = 0; i < this.press.length; ++i) {
|
||
|
if (this.press[i] == n) {
|
||
|
this.press.splice(i, 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (this.press.length == 0) {
|
||
|
this.gate = 0;
|
||
|
this.DrawKey(-1);
|
||
|
}
|
||
|
else {
|
||
|
n = this.press[0] - 36;
|
||
|
this.cv = n / 60;
|
||
|
this.DrawKey(n);
|
||
|
}
|
||
|
}
|
||
|
this.KeyPress = function(c, f) {
|
||
|
if (f) {
|
||
|
if (c >= 0x20 && c <= 0xbf) {
|
||
|
var n = this.table[c - 0x20];
|
||
|
if (n >= 0) {
|
||
|
for (var i = 0; i < this.press.length; ++i) {
|
||
|
if (this.press[i] == c)
|
||
|
break;
|
||
|
}
|
||
|
if (i == this.press.length) {
|
||
|
this.press.unshift(c);
|
||
|
this.gate = 1;
|
||
|
this.retrig = 1;
|
||
|
this.cv = n / 60;
|
||
|
this.DrawKey(n);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (var i = 0; i < this.press.length; ++i) {
|
||
|
if (this.press[i] == c) {
|
||
|
this.press.splice(i, 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (this.press.length == 0) {
|
||
|
this.gate = 0;
|
||
|
this.DrawKey(-1);
|
||
|
}
|
||
|
else {
|
||
|
var n = this.table[this.press[0] - 0x20];
|
||
|
this.cv = n / 60;
|
||
|
this.DrawKey(n);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Knobs() {
|
||
|
this.drag = null;
|
||
|
this.knobs = new Array();
|
||
|
this.AddRect = function(name, x, y, w, h) {
|
||
|
this.knobs[name] = new Rect(x, y, w, h);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.AddJack = function(name, x, y,ty,col) {
|
||
|
this.knobs[name] = new Jack(x, y,ty,col);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.AddKnob = function(name, x, y, w,h,img, step,def) {
|
||
|
this.knobs[name] = new Knob(x, y, w,h,img,step,def);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.AddSwitch = function(name, x, y,w,h,img,step,def) {
|
||
|
this.knobs[name] = new Switch(x,y,w,h,img,step,def);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.AddSlider = function(name, x, y, def) {
|
||
|
this.knobs[name] = new Slider(x, y, def);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.AddKey = function(name, x, y) {
|
||
|
this.knobs[name] = new Key(x, y);
|
||
|
return this.knobs[name];
|
||
|
}
|
||
|
this.MouseDown = function(x, y) {
|
||
|
this.drag = this.HitTest(x, y);
|
||
|
if (this.drag != null)
|
||
|
this.drag.MouseDown(x, y);
|
||
|
}
|
||
|
this.MouseMove = function(x, y) {
|
||
|
if (this.drag != null) {
|
||
|
app.Draw();
|
||
|
this.drag.MouseMove(x, y);
|
||
|
}
|
||
|
}
|
||
|
this.MouseUp = function(x, y) {
|
||
|
var wd = this.HitTest(x, y);
|
||
|
if (this.drag != null) {
|
||
|
if (wd != null) {
|
||
|
if (wd.ty == 0 && (this.drag.ty == 1 || this.drag.ty == 2)) {
|
||
|
wd.Connect(this.drag);
|
||
|
}
|
||
|
if ((wd.ty == 1 || wd.ty == 2) && this.drag.ty == 0) {
|
||
|
this.drag.Connect(wd);
|
||
|
}
|
||
|
}
|
||
|
if (this.drag.ty == 0) {
|
||
|
if(wd==null || (wd.ty!=1 && wd.ty!=2))
|
||
|
this.drag.Connect(null);
|
||
|
}
|
||
|
this.drag.MouseUp(x, y);
|
||
|
}
|
||
|
this.drag = null;
|
||
|
app.Draw();
|
||
|
}
|
||
|
this.HitTest = function(x, y) {
|
||
|
var wd, r;
|
||
|
r = null;
|
||
|
for (var i in this.knobs) {
|
||
|
var wd = this.knobs[i];
|
||
|
if (x >= wd.x && x < wd.x + wd.w && y >= wd.y && y < wd.y + wd.h) {
|
||
|
if (wd.ty < 1000)
|
||
|
r = wd;
|
||
|
}
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
this.Draw = function() {
|
||
|
for (var i in this.knobs) {
|
||
|
if (this.knobs[i].ty >= 100)
|
||
|
this.knobs[i].Draw();
|
||
|
}
|
||
|
for (var i in this.knobs) {
|
||
|
if (this.knobs[i].ty < 100)
|
||
|
this.knobs[i].Draw();
|
||
|
}
|
||
|
if (this.drag != null && this.drag.ty < 100) {
|
||
|
var wd = this.HitTest(mouseX, mouseY);
|
||
|
var f = 0;
|
||
|
if (wd != null && wd.ty < 100) {
|
||
|
if ((this.drag.ty == 0 && wd.ty != 0) || (this.drag.ty != 0 && wd.ty == 0))
|
||
|
f = 1;
|
||
|
else
|
||
|
f = 2;
|
||
|
}
|
||
|
this.drag.Cable(this.drag, mouseX, mouseY, 0x808080, f);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Keyboard(name, x, y) {
|
||
|
this.str = "";
|
||
|
this.start = 0;
|
||
|
this.tempo = 120;
|
||
|
this.deflen = 8;
|
||
|
this.oct = 3;
|
||
|
this.index = 0;
|
||
|
this.dur = 0;
|
||
|
this.gt = 0;
|
||
|
this.cvcur = 0;
|
||
|
this.cvlog = 0;
|
||
|
this.jckCv = app.knobs.AddJack(name + ".cv", x + 24, y + 8, 2,0x600000);
|
||
|
this.jckGate = app.knobs.AddJack(name + ".g", x + 60, y + 8, 2, 0x700000);
|
||
|
this.knbGlide = app.knobs.AddKnob(name + ".gl", x + 484, y + 36, 32, 32, "knob", 51, 0);
|
||
|
if (typeof (gadget) != "undefined")
|
||
|
this.key = app.knobs.AddKey(name + ".k", x, y);
|
||
|
else
|
||
|
this.key = app.knobs.AddKey(name + ".k", x + 24, y + 48);
|
||
|
this.SetStr=function(s) {
|
||
|
this.str=s;
|
||
|
}
|
||
|
this.Start = function(v) {
|
||
|
this.jckGate.buf[0] = 0;
|
||
|
this.tempo = 120;
|
||
|
this.deflen = 8;
|
||
|
this.oct = 3;
|
||
|
this.index = 0;
|
||
|
this.start = v;
|
||
|
if (v == 0)
|
||
|
this.key.DrawKey(-1);
|
||
|
}
|
||
|
this.GetNum=function() {
|
||
|
var n = 0;
|
||
|
while (this.str[this.index] >= '0' && this.str[this.index] <= '9') {
|
||
|
n = n * 10 + parseInt(this.str[this.index]);
|
||
|
++this.index;
|
||
|
}
|
||
|
return n;
|
||
|
}
|
||
|
this.Note = function(n) {
|
||
|
++this.index;
|
||
|
var n2 = n;
|
||
|
while (1) {
|
||
|
switch (this.str[this.index]) {
|
||
|
case '+':
|
||
|
case '#':
|
||
|
++n2;
|
||
|
++this.index;
|
||
|
break;
|
||
|
case '-':
|
||
|
--n2;
|
||
|
++this.index;
|
||
|
break;
|
||
|
default:
|
||
|
var len;
|
||
|
len = this.GetNum();
|
||
|
if (len <= 0)
|
||
|
len = this.deflen;
|
||
|
var st = 240 / (this.tempo * len);
|
||
|
var st2 = st;
|
||
|
while(this.str[this.index] == '.'){
|
||
|
++this.index;
|
||
|
st += (st2/=2);
|
||
|
}
|
||
|
if (this.str[this.index] == '&'|| this.str[this.index] == '^') {
|
||
|
++this.index;
|
||
|
this.gt = st;
|
||
|
}
|
||
|
else
|
||
|
this.gt = st * 0.8;
|
||
|
this.dur += st;
|
||
|
if (n >= 0) {
|
||
|
var nn = (this.oct - 2) * 12 + n2;
|
||
|
var v = n / 12 * 0.2;
|
||
|
if (v < 0)
|
||
|
v = 0;
|
||
|
if (v > 2)
|
||
|
v = 2;
|
||
|
this.cvlog=(nn / 12 * 0.2);
|
||
|
this.jckGate.FillBuf(1);
|
||
|
this.key.DrawKey(nn);
|
||
|
}
|
||
|
else {
|
||
|
this.jckGate.FillBuf(0);
|
||
|
this.gt = 0;
|
||
|
this.key.DrawKey(-1);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.OutCv = function() {
|
||
|
var diff = Math.abs(this.cvlog - this.cvcur);
|
||
|
var ratio = 1;
|
||
|
if (this.knbGlide.val != 0) {
|
||
|
ratio = Math.pow(100, this.knbGlide.val) * 0.000078125 * samplerate;
|
||
|
ratio = 1 - Math.exp(Math.log(0.01) / ratio);
|
||
|
}
|
||
|
if (diff < 1e-10)
|
||
|
this.cvcur = this.cvlog;
|
||
|
else
|
||
|
this.cvcur += (this.cvlog - this.cvcur) * ratio;
|
||
|
this.jckCv.FillBuf(this.cvcur);
|
||
|
}
|
||
|
this.Process = function() {
|
||
|
if (this.start == 0) {
|
||
|
if (this.key.gate != 0) {
|
||
|
if (this.key.retrig)
|
||
|
this.jckGate.FillBuf(0);
|
||
|
else
|
||
|
this.jckGate.FillBuf(1);
|
||
|
this.cvlog = this.key.cv;
|
||
|
}
|
||
|
else
|
||
|
this.jckGate.FillBuf(0);
|
||
|
this.OutCv();
|
||
|
this.key.retrig = 0;
|
||
|
return;
|
||
|
}
|
||
|
this.key.retrig = 0;
|
||
|
if (this.dur > 0) {
|
||
|
this.dur -= 128 / samplerate;
|
||
|
}
|
||
|
if (this.gt > 0) {
|
||
|
if ((this.gt -= 128 / samplerate) <= 0) {
|
||
|
this.gt = 0;
|
||
|
this.jckGate.FillBuf(0);
|
||
|
}
|
||
|
}
|
||
|
while (this.dur <= 0) {
|
||
|
if (this.index >= this.str.length)
|
||
|
break;
|
||
|
switch (this.str[this.index]) {
|
||
|
case 'T':
|
||
|
case 't':
|
||
|
++this.index;
|
||
|
this.tempo = this.GetNum();
|
||
|
if (this.tempo <= 0)
|
||
|
this.tempo = 120;
|
||
|
break;
|
||
|
case 'V':
|
||
|
++this.index;
|
||
|
this.GetNum();
|
||
|
break;
|
||
|
case 'L':
|
||
|
case 'l':
|
||
|
++this.index;
|
||
|
this.deflen = this.GetNum();
|
||
|
break;
|
||
|
case '>':
|
||
|
++this.index;
|
||
|
++this.oct;
|
||
|
break;
|
||
|
case '<':
|
||
|
++this.index;
|
||
|
--this.oct;
|
||
|
break;
|
||
|
case 'O':
|
||
|
case 'o':
|
||
|
++this.index;
|
||
|
this.oct = this.GetNum();
|
||
|
break;
|
||
|
case 'R':
|
||
|
case 'r':
|
||
|
this.Note(-1);
|
||
|
break;
|
||
|
case 'C':
|
||
|
case 'c':
|
||
|
this.Note(0);
|
||
|
break;
|
||
|
case 'D':
|
||
|
case 'd':
|
||
|
this.Note(2);
|
||
|
break;
|
||
|
case 'E':
|
||
|
case 'e':
|
||
|
this.Note(4);
|
||
|
break;
|
||
|
case 'F':
|
||
|
case 'f':
|
||
|
this.Note(5);
|
||
|
break;
|
||
|
case 'G':
|
||
|
case 'g':
|
||
|
this.Note(7);
|
||
|
break;
|
||
|
case 'A':
|
||
|
case 'a':
|
||
|
this.Note(9);
|
||
|
break;
|
||
|
case 'B':
|
||
|
case 'b':
|
||
|
this.Note(11);
|
||
|
break;
|
||
|
default:
|
||
|
++this.index;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
this.OutCv();
|
||
|
if (this.index >= this.str.length) {
|
||
|
this.tempo = 120;
|
||
|
this.deflen = 8;
|
||
|
this.oct = 3;
|
||
|
this.index = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Mix(name, x, y) {
|
||
|
try {
|
||
|
this.buf = new Float32Array(128);
|
||
|
} catch(e) {
|
||
|
this.buf=new Array(128);
|
||
|
}
|
||
|
this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y+52, 0,0x005000);
|
||
|
this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y+52, 0,0x006000);
|
||
|
this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y+52, 0,0x007000);
|
||
|
this.jckIn4 = app.knobs.AddJack(name + ".i4", x + 68, y+52, 0,0x008000);
|
||
|
this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y+72, 0.8);
|
||
|
this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y+72, 0.8);
|
||
|
this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y+72, 0);
|
||
|
this.sliIn4 = app.knobs.AddSlider(name + ".i4m", x + 68, y+72, 0);
|
||
|
this.Process = function() {
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
this.buf[i] = 1e-100;
|
||
|
}
|
||
|
if (this.jckIn1.connect) {
|
||
|
var vala = this.sliIn1.vala;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.buf[i] += this.jckIn1.connect.buf[i] * vala;
|
||
|
}
|
||
|
if (this.jckIn2.connect) {
|
||
|
var vala = this.sliIn2.vala;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.buf[i] += this.jckIn2.connect.buf[i] * vala;
|
||
|
}
|
||
|
if (this.jckIn3.connect) {
|
||
|
var vala = this.sliIn3.vala;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.buf[i] += this.jckIn3.connect.buf[i] * vala;
|
||
|
}
|
||
|
if (this.jckIn4.connect) {
|
||
|
var vala = this.sliIn4.vala;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.buf[i] += this.jckIn4.connect.buf[i] * vala;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Ring(name, x, y) {
|
||
|
this.jckIn1 = app.knobs.AddJack(name + ".i1", x+8, y + 0, 0,0x009000);
|
||
|
this.jckIn2 = app.knobs.AddJack(name + ".i2", x+32, y + 0, 0,0x00a000);
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x800000);
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout > 0) {
|
||
|
var out = this.jckOut.buf;
|
||
|
if (this.jckIn1.connect && this.jckIn2.connect) {
|
||
|
var in1 = this.jckIn1.connect.buf;
|
||
|
var in2 = this.jckIn2.connect.buf;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
out[i] = in1[i] * in2[i];
|
||
|
}
|
||
|
else {
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
out[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Noise(name, x, y) {
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x900000);
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout > 0) {
|
||
|
var out = this.jckOut.buf;
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
out[i] = Math.random()*2 - 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function SH(name, x, y) {
|
||
|
this.hold = 0;
|
||
|
this.trlast = 0;
|
||
|
this.jckIn = app.knobs.AddJack(name + ".i", x + 8, y + 0, 0,0x009000);
|
||
|
this.jckTr = app.knobs.AddJack(name + ".tr", x + 32, y + 0, 0,0x00a000);
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x990000);
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout > 0) {
|
||
|
var out = this.jckOut.buf;
|
||
|
var hold = this.hold;
|
||
|
if (this.jckTr.connect != null) {
|
||
|
var tr = this.jckTr.connect.buf[0];
|
||
|
if (tr > 0 && this.trlast <= 0) {
|
||
|
if (this.jckIn.connect != null)
|
||
|
this.hold = this.jckIn.connect.buf[0];
|
||
|
else
|
||
|
this.hold = 0;
|
||
|
}
|
||
|
this.trlast = tr;
|
||
|
}
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
out[i] = hold;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Env(name, x, y) {
|
||
|
this.jckOutP = app.knobs.AddJack(name + ".op", x + 68, y + 120, 2,0xb00000);
|
||
|
this.jckOutN = app.knobs.AddJack(name + ".on", x + 40, y + 120, 2,0xc00000);
|
||
|
this.jckTrig = app.knobs.AddJack(name + ".tr", x + 8, y + 120, 0,0);
|
||
|
this.sliA = app.knobs.AddSlider(name + ".a", x + 8, y + 28, 0);
|
||
|
this.sliD = app.knobs.AddSlider(name + ".d", x + 28, y + 28, 0);
|
||
|
this.sliS = app.knobs.AddSlider(name + ".s", x + 48, y + 28, 1);
|
||
|
this.sliR = app.knobs.AddSlider(name + ".r", x + 68, y + 28, 0);
|
||
|
this.phase = 0;
|
||
|
this.val = 0;
|
||
|
this.Process = function() {
|
||
|
if (this.jckTrig.connect == null) {
|
||
|
this.jckOutP.buf[0] = this.jckOutN.buf[0] = 0;
|
||
|
this.phase = this.val = 0;
|
||
|
return;
|
||
|
}
|
||
|
var n = 128 / samplerate;
|
||
|
var ratea = n / (Math.pow(1000, this.sliA.val) * 0.001);
|
||
|
var rated = Math.pow(10, -2 / ((Math.pow(1000, this.sliD.val) * 0.01) / n));
|
||
|
var rater = Math.pow(10, -2 / ((Math.pow(1000, this.sliR.val) * 0.01) / n));
|
||
|
switch (this.phase) {
|
||
|
case 0:
|
||
|
if (this.jckTrig.connect.buf[0] > 0)
|
||
|
this.phase = 1;
|
||
|
else {
|
||
|
if (this.val > this.sliS.val) {
|
||
|
this.val = this.sliS.val + (this.val - this.sliS.val) * rated;
|
||
|
}
|
||
|
this.val *= rater;
|
||
|
if (this.val < 0.00001)
|
||
|
this.val = 0;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
if (this.jckTrig.connect.buf[0] > 0) {
|
||
|
if ((this.val += ratea) >= 1) {
|
||
|
this.val = 1;
|
||
|
this.phase = 2;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
this.phase = 0;
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
if (this.jckTrig.connect.buf[0] > 0) {
|
||
|
this.val = this.sliS.val + (this.val - this.sliS.val) * rated;
|
||
|
}
|
||
|
else
|
||
|
this.phase = 0;
|
||
|
break;
|
||
|
}
|
||
|
var xxp = this.val;
|
||
|
var xxn = -this.val;
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
this.jckOutP.buf[i] = xxp;
|
||
|
this.jckOutN.buf[i] = xxn;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Lfo(name, x, y) {
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 20, 2,0x880000);
|
||
|
this.jckOut10 = app.knobs.AddJack(name + ".o10", x + 40, y + 20, 2,0x990000);
|
||
|
this.knbForm = app.knobs.AddSwitch(name + ".form", x + 8, y + 64, 16, 40, "sw3", 3, 1);
|
||
|
this.knbFreq = app.knobs.AddKnob(name + ".f", x + 48, y + 68, 32, 32, "knob", 51, 0.5);
|
||
|
this.phase = 0;
|
||
|
this.Process = function() {
|
||
|
var f = Math.pow(1000, this.knbFreq.val) * 0.1;
|
||
|
this.phase += f * 128 / samplerate;
|
||
|
if (this.phase >= 1)
|
||
|
this.phase -= 1;
|
||
|
var x, mul0, mul1, add0, add1;
|
||
|
switch (this.knbForm.val) {
|
||
|
case 1:
|
||
|
mul0 = 4;
|
||
|
mul1 = -4;
|
||
|
add0 = -1;
|
||
|
add1 = 3;
|
||
|
break;
|
||
|
case 0.5:
|
||
|
mul0 = mul1 = 2;
|
||
|
add0 = add1 = -1;
|
||
|
break;
|
||
|
case 0:
|
||
|
mul0 = mul1 = 0;
|
||
|
add0 = -1;
|
||
|
add1 = 1;
|
||
|
break;
|
||
|
}
|
||
|
if (this.phase >= 0.5)
|
||
|
x = this.phase * mul1 + add1;
|
||
|
else
|
||
|
x = this.phase * mul0 + add0;
|
||
|
var xx = x;
|
||
|
var xx10 = x * 0.1;
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
this.jckOut.buf[i] = xx;
|
||
|
this.jckOut10.buf[0] = xx10;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Vco(name, x, y, oct, pit) {
|
||
|
this.jckPwm = app.knobs.AddJack(name + ".ipw", x + 8, y + 52, 0, 0x007700);
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 52, 1, 0xf00000);
|
||
|
this.sliPwm = app.knobs.AddSlider(name + ".pwm", x + 8, y + 72, 0);
|
||
|
this.sliPw = app.knobs.AddSlider(name + ".pw", x + 28, y + 72, 0);
|
||
|
this.knbOct = app.knobs.AddSwitch(name + ".oct", x + 8, y + 168, 16, 40, "sw5", 5, oct);
|
||
|
this.knbForm = app.knobs.AddSwitch(name + ".form", x + 40, y + 168, 16, 40, "sw3", 3, 0.5);
|
||
|
this.knbCoarse = app.knobs.AddKnob(name + ".co", x + 8, y + 236, 40, 40, "knob2", 25, 0.5);
|
||
|
this.knbPitch = app.knobs.AddKnob(name + ".pi", x + 16, y + 244, 24, 24, "knob3", 51, pit);
|
||
|
this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
|
||
|
this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0.1);
|
||
|
this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
|
||
|
this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
|
||
|
this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
|
||
|
this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
|
||
|
this.phase = 0;
|
||
|
this.freq = 0;
|
||
|
this.delta = 0;
|
||
|
this.cpw = 0;
|
||
|
this.rcpw = 1;
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout <= 0)
|
||
|
return;
|
||
|
var cv;
|
||
|
cv = (this.knbOct.val - 0.5) * (this.knbOct.step - 1) * 0.2 + (this.knbCoarse.val - 0.5) * 0.4 + (this.knbPitch.val - 0.5) * 0.4 / 12;
|
||
|
if (this.jckMod1.connect)
|
||
|
cv += this.jckMod1.connect.buf[0] * this.sliMod1.val;
|
||
|
if (this.jckMod2.connect)
|
||
|
cv += this.jckMod2.connect.buf[0] * this.sliMod2.val;
|
||
|
if (this.jckMod3.connect)
|
||
|
cv += this.jckMod3.connect.buf[0] * this.sliMod3.val;
|
||
|
this.freq = 130.8127826502993 * Math.pow(2, cv * 5);
|
||
|
this.delta = this.freq / samplerate;
|
||
|
if (this.delta > 1)
|
||
|
this.delta = 1;
|
||
|
var cpw = this.sliPw.val;
|
||
|
if (this.jckPwm.connect)
|
||
|
cpw += this.jckPwm.connect.buf[0] * this.sliPwm.val;
|
||
|
if (cpw < 0)
|
||
|
cpw = -cpw;
|
||
|
if (cpw > 0.95)
|
||
|
cpw = 0.95;
|
||
|
var rcpw = 1 / (1 - cpw);
|
||
|
var mul0, mul1, add0, add1;
|
||
|
switch (this.knbForm.val) {
|
||
|
case 1:
|
||
|
mul0 = 4;
|
||
|
add0 = -1;
|
||
|
mul1 = -4;
|
||
|
add1 = 3;
|
||
|
break;
|
||
|
case 0.5:
|
||
|
mul0 = mul1 = 2;
|
||
|
add0 = add1 = -1;
|
||
|
break;
|
||
|
case 0:
|
||
|
mul0 = mul1 = 0;
|
||
|
add0 = -1;
|
||
|
add1 = 1;
|
||
|
break;
|
||
|
}
|
||
|
var x;
|
||
|
var out = this.jckOut.buf;
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
if (this.phase > cpw) {
|
||
|
var ph2 = (this.phase - cpw) * rcpw;
|
||
|
if (ph2 >= 0.5)
|
||
|
x = ph2 * mul1 + add1;
|
||
|
else
|
||
|
x = ph2 * mul0 + add0;
|
||
|
}
|
||
|
else
|
||
|
x = 0;
|
||
|
this.phase += this.delta;
|
||
|
if (this.phase >= 1)
|
||
|
this.phase -= 1;
|
||
|
out[i] = x;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Vcf(name, x, y) {
|
||
|
this.y1 = this.y2 = this.y3 = this.y4 = 0;
|
||
|
this.ox = 0;
|
||
|
this.k = this.r = this.p = 0;
|
||
|
this.gain = 0;
|
||
|
this.enable = false;
|
||
|
this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y + 52, 0);
|
||
|
this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y + 52, 0);
|
||
|
this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y + 52, 0);
|
||
|
this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y + 72, 0.8);
|
||
|
this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y + 72, 0.8);
|
||
|
this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y + 72, 0);
|
||
|
this.knbFreq = app.knobs.AddKnob(name + ".f", x + 12, y + 152, 32, 32, "knob", 50, 0.8);
|
||
|
this.knbReso = app.knobs.AddKnob(name + ".r", x + 12, y + 200, 32, 32, "knob", 50, 0.5);
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 252, 1);
|
||
|
this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
|
||
|
this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0.5);
|
||
|
this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
|
||
|
this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
|
||
|
this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
|
||
|
this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
|
||
|
this.SetFreq = function(f) {
|
||
|
f = Math.min(0.45, Math.max(0.001, f));
|
||
|
this.p = f * (1.8 - 0.8 * f);
|
||
|
this.k = this.p * 2 - 1;
|
||
|
t = (1 - this.p) * 1.35;
|
||
|
t2 = 11 + t * t;
|
||
|
this.r = this.knbReso.val * (t2 + 6 * t) / (t2 - 6 * t) * 0.8;
|
||
|
}
|
||
|
this.SetFreq(1);
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout <= 0)
|
||
|
return;
|
||
|
var cv;
|
||
|
cv = this.knbFreq.val;
|
||
|
if (this.jckMod1.connect)
|
||
|
cv += this.jckMod1.connect.buf[0] * this.sliMod1.val;
|
||
|
if (this.jckMod2.connect)
|
||
|
cv += this.jckMod2.connect.buf[0] * this.sliMod2.val;
|
||
|
if (this.jckMod3.connect)
|
||
|
cv += this.jckMod3.connect.buf[0] * this.sliMod3.val;
|
||
|
this.freq = 130.8127826502993 * Math.pow(2, cv * 5);
|
||
|
this.SetFreq(this.freq / samplerate);
|
||
|
var sliIn1 = this.sliIn1.val;
|
||
|
var sliIn2 = this.sliIn2.val;
|
||
|
var sliIn3 = this.sliIn3.val;
|
||
|
var enIn1 = (this.jckIn1.connect != null);
|
||
|
var enIn2 = (this.jckIn2.connect != null);
|
||
|
var enIn3 = (this.jckIn3.connect != null);
|
||
|
if (enIn1 || enIn2 || enIn3) {
|
||
|
var out = this.jckOut.buf;
|
||
|
var k = this.k;
|
||
|
var p = this.p;
|
||
|
this.enable = true;
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
var x = 1e-100;
|
||
|
if (enIn1)
|
||
|
x += this.jckIn1.connect.buf[i] * sliIn1;
|
||
|
if (enIn2)
|
||
|
x += this.jckIn2.connect.buf[i] * sliIn2;
|
||
|
if (enIn3)
|
||
|
x += this.jckIn3.connect.buf[i] * sliIn3;
|
||
|
|
||
|
x = x * .1 - this.r * this.y4;
|
||
|
y1 = this.y1; y2 = this.y2; y3 = this.y3;
|
||
|
this.y1 = (x + this.ox) * p - y1 * k;
|
||
|
this.y2 = (this.y1 + y1) * p - y2 * k;
|
||
|
this.y3 = (this.y2 + y2) * p - y3 * k;
|
||
|
y4 = (this.y3 + y3) * p - this.y4 * k;
|
||
|
this.y4 = y4 - y4 * y4 * y4 * 0.1666666666666667;
|
||
|
this.ox = x;
|
||
|
out[i] = this.y4 * 12;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (this.enable)
|
||
|
this.jckOut.FillBuf(0);
|
||
|
this.enable = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function Vca(name, x, y) {
|
||
|
this.gain = 0;
|
||
|
this.enable = false;
|
||
|
this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y + 52, 0);
|
||
|
this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y + 52, 0);
|
||
|
this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y + 52, 0);
|
||
|
this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y + 72, 0.8);
|
||
|
this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y + 72, 0);
|
||
|
this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y + 72, 0);
|
||
|
this.knbVol = app.knobs.AddKnob(name + ".vol", x + 12, y + 164, 32, 32, "knob", 50, 0.5);
|
||
|
this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 224, 1);
|
||
|
this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
|
||
|
this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0);
|
||
|
this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
|
||
|
this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
|
||
|
this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
|
||
|
this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
|
||
|
this.Process = function() {
|
||
|
if (this.jckOut.fanout <= 0)
|
||
|
return;
|
||
|
var v;
|
||
|
var g = this.knbVol.val;
|
||
|
if (this.jckMod1.connect != null)
|
||
|
g += this.jckMod1.connect.buf[0] * this.sliMod1.val;
|
||
|
if (this.jckMod2.connect != null)
|
||
|
g += this.jckMod2.connect.buf[0] * this.sliMod2.val;
|
||
|
if (this.jckMod3.connect != null)
|
||
|
g += this.jckMod3.connect.buf[0] * this.sliMod3.val;
|
||
|
if (g < 0)
|
||
|
g = 0;
|
||
|
if (Math.abs(this.gain - g) < 1e-10)
|
||
|
this.gain = g;
|
||
|
var sli1 = this.sliIn1.val;
|
||
|
var sli2 = this.sliIn2.val;
|
||
|
var sli3 = this.sliIn3.val;
|
||
|
var enIn1 = (this.jckIn1.connect != null);
|
||
|
var enIn2 = (this.jckIn2.connect != null);
|
||
|
var enIn3 = (this.jckIn3.connect != null);
|
||
|
if (enIn1 || enIn2 || enIn3) {
|
||
|
this.enable = true;
|
||
|
var out = this.jckOut.buf;
|
||
|
for (var i = 0; i < 128; ++i) {
|
||
|
v = 1e-100;
|
||
|
if (enIn1)
|
||
|
v += this.jckIn1.connect.buf[i] * sli1;
|
||
|
if (enIn2)
|
||
|
v += this.jckIn2.connect.buf[i] * sli2;
|
||
|
if (enIn3)
|
||
|
v += this.jckIn3.connect.buf[i] * sli3;
|
||
|
out[i] = v * this.gain;
|
||
|
this.gain += (g - this.gain) * 0.02;
|
||
|
// this.gain = g;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (this.enable)
|
||
|
this.jckOut.FillBuf(0);
|
||
|
this.enable = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function App() {
|
||
|
this.Draw = function() {
|
||
|
if (!this.canvas || !this.canvas.getContext) {
|
||
|
return false;
|
||
|
}
|
||
|
ctx = this.canvas.getContext('2d');
|
||
|
ctx.drawImage(imgpanel, 0, 0);
|
||
|
this.knobs.Draw();
|
||
|
}
|
||
|
this.MouseDown = function(e) {
|
||
|
if(!this.ready){
|
||
|
audioif.audio.resume();
|
||
|
this.ready = true;
|
||
|
}
|
||
|
console.log("Press");
|
||
|
document.getElementById("canvas").focus();
|
||
|
getXY(e);
|
||
|
app.knobs.MouseDown(mouseX, mouseY);
|
||
|
return false;
|
||
|
}
|
||
|
this.MouseMove = function(e) {
|
||
|
getXY(e);
|
||
|
app.knobs.MouseMove(mouseX, mouseY);
|
||
|
}
|
||
|
this.MouseUp = function(e) {
|
||
|
getXY(e);
|
||
|
app.knobs.MouseUp(mouseX, mouseY);
|
||
|
}
|
||
|
this.TouchDown = function(e) {
|
||
|
if(!this.ready){
|
||
|
audioif.audio.resume();
|
||
|
this.ready = true;
|
||
|
}
|
||
|
e.preventDefault();
|
||
|
document.getElementById("canvas").focus();
|
||
|
getXYTouch(e);
|
||
|
app.knobs.MouseDown(mouseX, mouseY);
|
||
|
return false;
|
||
|
}
|
||
|
this.TouchMove = function(e) {
|
||
|
e.preventDefault();
|
||
|
getXYTouch(e);
|
||
|
app.knobs.MouseMove(mouseX, mouseY);
|
||
|
}
|
||
|
this.TouchUp = function(e) {
|
||
|
e.preventDefault();
|
||
|
getXYTouch(e);
|
||
|
app.knobs.MouseUp(mouseX, mouseY);
|
||
|
}
|
||
|
this.DblClick = function(e) {
|
||
|
}
|
||
|
this.KeyDown = function(e) {
|
||
|
if (document.activeElement == document.getElementById("canvas")) {
|
||
|
app.keyboard.key.KeyPress(e.keyCode, 1);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
this.KeyUp = function(e) {
|
||
|
app.keyboard.key.KeyPress(e.keyCode, 0);
|
||
|
}
|
||
|
this.KeyPress = function(e) {
|
||
|
if (document.activeElement == document.getElementById("canvas"))
|
||
|
return false;
|
||
|
}
|
||
|
this.Init = function() {
|
||
|
samplerate = 44100;
|
||
|
this.ready = false;
|
||
|
this.canvas = document.getElementById('canvas');
|
||
|
this.canvas.onmousedown = this.MouseDown;
|
||
|
this.canvas.onmousemove = this.MouseMove;
|
||
|
this.canvas.onmouseup = this.MouseUp;
|
||
|
this.canvas.ondblclick = this.DblClick;
|
||
|
this.canvas.ontouchstart = this.TouchDown;
|
||
|
this.canvas.ontouchmove = this.TouchMove;
|
||
|
this.canvas.ontouchend = this.TouchUp;
|
||
|
document.onkeydown = this.KeyDown;
|
||
|
document.onkeyup = this.KeyUp;
|
||
|
document.onkeypress = this.KeyPress;
|
||
|
this.knobs = new Knobs();
|
||
|
this.vco1 = new Vco("vco1", 36, 78, 0.5, 0.5);
|
||
|
this.vco2 = new Vco("vco2", 108, 78, 0.25, 0.45);
|
||
|
this.vcf1 = new Vcf("vcf1", 180, 78);
|
||
|
this.vcf2 = new Vcf("vcf2", 252, 78);
|
||
|
this.vca1 = new Vca("vca1", 324, 78);
|
||
|
this.vca2 = new Vca("vca2", 396, 78);
|
||
|
this.env1 = new Env("env1", 468, 78);
|
||
|
this.env2 = new Env("env2", 468, 226);
|
||
|
this.lfo1 = new Lfo("lfo1", 468, 374);
|
||
|
this.lfo2 = new Lfo("lfo2", 564, 374);
|
||
|
this.mix = new Mix("mix", 564, 78);
|
||
|
this.ring = new Ring("ring", 564, 250);
|
||
|
this.noise = new Noise("noise", 564, 286);
|
||
|
this.sh = new SH("sh", 564, 346);
|
||
|
if (typeof(gadget) != "undefined")
|
||
|
this.keyboard = new Keyboard("kb", 24, 154);
|
||
|
else
|
||
|
this.keyboard = new Keyboard("kb", 48, 502);
|
||
|
try {
|
||
|
this.dummybuf = new Float32Array(128);
|
||
|
} catch (e) {
|
||
|
this.dummybuf = new Array(128);
|
||
|
}
|
||
|
for (var i = 0; i < 128; ++i)
|
||
|
this.dummybuf[i] = 0;
|
||
|
audioif = new AudioIf();
|
||
|
audiomix = new AudioMix();
|
||
|
imgpanel = document.getElementById("panel");
|
||
|
imgknobs["knob"] = document.getElementById("knob");
|
||
|
imgknobs["knob2"] = document.getElementById("knob2");
|
||
|
imgknobs["knob3"] = document.getElementById("knob3");
|
||
|
imgknobs["sw2"] = document.getElementById("sw2");
|
||
|
imgknobs["sw3"] = document.getElementById("sw3");
|
||
|
imgknobs["sw5"] = document.getElementById("sw5");
|
||
|
imgknobs["slider"] = document.getElementById("slider");
|
||
|
imgknobs["keypress"] = document.getElementById("keypress");
|
||
|
Setup();
|
||
|
this.Draw();
|
||
|
var param = location.search;
|
||
|
if (param.length > 1)
|
||
|
CmdLoad(location.search.substring(1));
|
||
|
}
|
||
|
}
|
||
|
function Interval() {
|
||
|
// if (typeof (document.hasFocus) != "undefined" && document.hasFocus() == false)
|
||
|
// return;
|
||
|
audiomix.Play();
|
||
|
audioif.Write();
|
||
|
}
|
||
|
function Init() {
|
||
|
app = new App();
|
||
|
app.Init();
|
||
|
if (audioif.enable == 0) {
|
||
|
return;
|
||
|
}
|
||
|
if (audioif.start == 0) {
|
||
|
audioif.Start();
|
||
|
audiomix.Reset();
|
||
|
playint = setInterval(Interval, 20);
|
||
|
}
|
||
|
LinkReady();
|
||
|
}
|
||
|
function CmdPlay(v) {
|
||
|
if (v) {
|
||
|
if(!app.ready)
|
||
|
audioif.audio.resume();
|
||
|
app.keyboard.SetStr(document.getElementById("mml").value);
|
||
|
app.keyboard.Start(1);
|
||
|
}
|
||
|
else {
|
||
|
app.keyboard.Start(0);
|
||
|
}
|
||
|
}
|
||
|
function CmdSave() {
|
||
|
var jstr = "";
|
||
|
var kstr = "";
|
||
|
var vals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||
|
for (var i in app.knobs.knobs) {
|
||
|
var w = app.knobs.knobs[i];
|
||
|
switch(w.ty) {
|
||
|
case 0:
|
||
|
if (w.connect != null) {
|
||
|
jstr += vals[w.pnum];
|
||
|
jstr += vals[w.connect.pnum];
|
||
|
}
|
||
|
break;
|
||
|
case 100:
|
||
|
case 102:
|
||
|
kstr += vals[(w.val * (w.step-1)) | 0];
|
||
|
break;
|
||
|
case 101:
|
||
|
kstr += vals[(w.val * 50) | 0];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
var mstr = encodeURIComponent(document.getElementById("mml").value);
|
||
|
var url = document.URL.split("?")[0] + "?p=" + jstr + "_" + kstr+"&m="+mstr;
|
||
|
document.getElementById("url").value = url;
|
||
|
return url;
|
||
|
}
|
||
|
function GetJack(n, t) {
|
||
|
for (var i in app.knobs.knobs) {
|
||
|
var w = app.knobs.knobs[i];
|
||
|
if (t == 0) {
|
||
|
if (w.ty == 0) {
|
||
|
if (w.pnum == n)
|
||
|
return w;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (w.ty != 0 && w.ty < 100) {
|
||
|
if (w.pnum == n)
|
||
|
return w;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function CmdLoad(str) {
|
||
|
if (str == null) {
|
||
|
str = document.getElementById("url").value;
|
||
|
}
|
||
|
n = str.indexOf("?");
|
||
|
if (n >= 0)
|
||
|
str = str.substring(n + 1);
|
||
|
var param = str.split("&");
|
||
|
var vals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||
|
for (var i = 0; i < param.length; ++i) {
|
||
|
if (param[i].search("p=") == 0) {
|
||
|
var s = param[i].substring(2);
|
||
|
for (var ii in app.knobs.knobs) {
|
||
|
var w = app.knobs.knobs[ii];
|
||
|
if (w.ty == 0)
|
||
|
w.connect = null;
|
||
|
else if (w.ty < 100)
|
||
|
w.fanout = 0;
|
||
|
}
|
||
|
for (var j = 0; j < s.length; j += 2) {
|
||
|
if (s.charAt(j) == "_")
|
||
|
break;
|
||
|
var n = vals.indexOf(s.charAt(j));
|
||
|
var v = vals.indexOf(s.charAt(j + 1));
|
||
|
GetJack(n, 0).Connect(GetJack(v, 1));
|
||
|
}
|
||
|
++j;
|
||
|
for (var ii in app.knobs.knobs) {
|
||
|
var w = app.knobs.knobs[ii];
|
||
|
switch (w.ty) {
|
||
|
case 100:
|
||
|
case 102:
|
||
|
w.Set(vals.indexOf(s.charAt(j)) / (w.step-1));
|
||
|
++j;
|
||
|
break;
|
||
|
case 101:
|
||
|
w.Set(vals.indexOf(s.charAt(j)) / 50);
|
||
|
++j;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (param[i].search("m=") == 0) {
|
||
|
var s;
|
||
|
try {
|
||
|
s=decodeURIComponent(param[i].substring(2));
|
||
|
} catch (e) {
|
||
|
s = param[i].substring(2);
|
||
|
}
|
||
|
document.getElementById("mml").value = s;
|
||
|
}
|
||
|
}
|
||
|
app.Draw();
|
||
|
}
|
||
|
function CmdTweet() {
|
||
|
CmdSave();
|
||
|
var url = "https://twitter.com/intent/tweet?hashtags=WebModular&url=" + encodeURIComponent(document.getElementById("url").value);
|
||
|
var win = window.open(url, "", "toolbar=0, status=0, width=650, height=360");
|
||
|
|
||
|
}
|
||
|
function Message(s) {
|
||
|
}
|
||
|
var datbuf = new Array(4096);
|
||
|
for (var ii = 0; ii < 4096; ++ii) {
|
||
|
datbuf[ii] = 0;
|
||
|
}
|
||
|
function FlashGetEnable() {
|
||
|
if (audioif.enable == 3)
|
||
|
return 1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
function FlashGetData() {
|
||
|
var b = audiomix.GetOutBuf();
|
||
|
if (b < 0) {
|
||
|
return datbuf;
|
||
|
}
|
||
|
else {
|
||
|
audiomix.NextBuf();
|
||
|
return audiomix.queout[b];
|
||
|
}
|
||
|
}
|
||
|
function AudioIf() {
|
||
|
this.start = 0;
|
||
|
this.written = 0;
|
||
|
this.size = Math.floor(samplerate * 15 / 120) * 16;
|
||
|
this.buf = 0;
|
||
|
samplerate = 44100;
|
||
|
this.enable = 0;
|
||
|
this.totalwritten = 0;
|
||
|
this.count = 0;
|
||
|
if (typeof (webkitAudioContext) != "undefined") {
|
||
|
this.audio = new webkitAudioContext();
|
||
|
samplerate = this.audio.sampleRate;
|
||
|
this.enable = 2;
|
||
|
outbufsize = 1024;
|
||
|
}
|
||
|
else if(typeof (AudioContext) != "undefined") {
|
||
|
this.audio = new AudioContext();
|
||
|
samplerate = this.audio.sampleRate;
|
||
|
this.enable = 2;
|
||
|
outbufsize = 1024;
|
||
|
}
|
||
|
else if (typeof (Audio) != "function") {
|
||
|
this.audio = new Audio();
|
||
|
if (typeof (this.audio.mozSetup) == "function") {
|
||
|
this.enable = 1;
|
||
|
outbufsize = 1024;
|
||
|
}
|
||
|
}
|
||
|
if (this.enable == 0) {
|
||
|
this.enable = 3;
|
||
|
outbufsize = 4096;
|
||
|
}
|
||
|
switch (this.enable) {
|
||
|
case 0:
|
||
|
Message("Audio Disabled: 'AudioDataAPI' or 'WebAudioAPI' is not supported in this browser.");
|
||
|
break;
|
||
|
case 1:
|
||
|
Message("Using Audio Data API");
|
||
|
break;
|
||
|
case 2:
|
||
|
Message("Using Web Audio API");
|
||
|
break;
|
||
|
case 3:
|
||
|
break;
|
||
|
}
|
||
|
if (this.enable > 0) {
|
||
|
try {
|
||
|
this.dummysample = new Float32Array(outbufsize);
|
||
|
} catch (e) {
|
||
|
this.dummysample = new Array(outbufsize);
|
||
|
}
|
||
|
for (var i = 0; i < outbufsize; ++i)
|
||
|
this.dummysample[i] = 0;
|
||
|
}
|
||
|
if (this.enable == 1) {
|
||
|
this.audio.mozSetup(stereo+1, samplerate);
|
||
|
}
|
||
|
if (this.enable == 2) {
|
||
|
this.dummyosc = this.audio.createOscillator();
|
||
|
this.jsnode = this.audio.createScriptProcessor(outbufsize,2,2);
|
||
|
// this.jsnode = this.audio.createJavaScriptNode(outbufsize, 2, 2);
|
||
|
this.jsnode.onaudioprocess = function(e) {
|
||
|
var outl = e.outputBuffer.getChannelData(0);
|
||
|
var outr = e.outputBuffer.getChannelData(1);
|
||
|
var b = audiomix.GetOutBuf();
|
||
|
if (b < 0) {
|
||
|
outl.set(audioif.dummysample);
|
||
|
outr.set(audioif.dummysample);
|
||
|
}
|
||
|
else {
|
||
|
outl.set(audiomix.queout[b]);
|
||
|
outr.set(audiomix.queout[b]);
|
||
|
audiomix.NextBuf();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.SetSamplerate = function(s) {
|
||
|
if (s != samplerate) {
|
||
|
samplerate = s;
|
||
|
audiomix.SetSamplerate();
|
||
|
}
|
||
|
}
|
||
|
this.Write = function() {
|
||
|
if (this.enable == 1) {
|
||
|
if (audioif.start == 0)
|
||
|
return;
|
||
|
if (this.written >= outbufsize2) {
|
||
|
if (audiomix.NextBuf() < 0)
|
||
|
return;
|
||
|
this.written = 0;
|
||
|
}
|
||
|
if (this.totalwritten > this.audio.mozCurrentSampleOffset() + 16384)
|
||
|
return;
|
||
|
var b = audiomix.GetOutBuf();
|
||
|
if (b >= 0) {
|
||
|
w = this.audio.mozWriteAudio(audiomix.queout[b].subarray(this.written));
|
||
|
this.totalwritten += w;
|
||
|
this.written += w;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.Start = function() {
|
||
|
this.start = 1;
|
||
|
switch (this.enable) {
|
||
|
case 1:
|
||
|
break;
|
||
|
case 2:
|
||
|
this.audio.resume();
|
||
|
this.dummyosc.connect(this.audio.destination);
|
||
|
this.jsnode.connect(this.audio.destination);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
this.Stop = function() {
|
||
|
this.start = 0;
|
||
|
switch (this.enable) {
|
||
|
case 1:
|
||
|
break;
|
||
|
case 2:
|
||
|
this.jsnode.disconnect(0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
this.SetSize = function(s) {
|
||
|
this.size = s;
|
||
|
}
|
||
|
}
|
||
|
function AudioMix() {
|
||
|
this.queout = new Array(outquenum);
|
||
|
this.queout2 = new Array(outquenum);
|
||
|
this.windex = 0;
|
||
|
this.rindex = 0;
|
||
|
this.pat = 0;
|
||
|
this.step = 0;
|
||
|
this.steplen = samplerate / 8;
|
||
|
this.tick = 0;
|
||
|
this.count = 0;
|
||
|
for (var i = 0; i < outquenum; ++i) {
|
||
|
if (audioif.enable == 1) {
|
||
|
this.queout[i] = new Float32Array(outbufsize2);
|
||
|
for (var ii = 0; ii < outbufsize2; ++ii)
|
||
|
this.queout[i][ii] = 0;
|
||
|
}
|
||
|
else if (audioif.enable == 2) {
|
||
|
this.queout[i] = new Float32Array(outbufsize);
|
||
|
this.queout2[i] = new Float32Array(outbufsize);
|
||
|
for (var ii = 0; ii < outbufsize; ++ii) {
|
||
|
this.queout[i][ii] = this.queout2[i][ii] = 0;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
this.queout[i] = new Array(outbufsize);
|
||
|
for (var ii = 0; ii < outbufsize2; ++ii)
|
||
|
this.queout[i][ii] = 0;
|
||
|
}
|
||
|
}
|
||
|
this.SetSamplerate = function() {
|
||
|
this.steplen = samplerate * 15 / tempo;
|
||
|
}
|
||
|
this.SetTempo = function(x) {
|
||
|
this.steplen = samplerate * 15 / x;
|
||
|
}
|
||
|
this.GetQueNum = function() {
|
||
|
if ((n = this.windex - this.rindex) < 0)
|
||
|
n += outquenum;
|
||
|
return n;
|
||
|
}
|
||
|
this.GetOutBuf = function() {
|
||
|
if (audiomix.rindex == audiomix.windex)
|
||
|
return -1;
|
||
|
return audiomix.rindex;
|
||
|
}
|
||
|
this.NextBuf = function() {
|
||
|
if (audiomix.rindex == audiomix.windex)
|
||
|
return -1;
|
||
|
if (++audiomix.rindex >= outquenum)
|
||
|
audiomix.rindex = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
this.Reset = function() {
|
||
|
audiomix.tick = audiomix.steplen;
|
||
|
audiomix.rindex = audiomix.windex = 0;
|
||
|
audioif.written = 0;
|
||
|
}
|
||
|
this.Render = function(buf) {
|
||
|
}
|
||
|
this.DrawVu = function() {
|
||
|
}
|
||
|
this.Play = function() {
|
||
|
if (((audiomix.windex + 1) % outquenum) == audiomix.rindex)
|
||
|
return;
|
||
|
for (var ilp = 0; ilp < outbufsize; ilp += 128) {
|
||
|
app.keyboard.Process();
|
||
|
app.noise.Process();
|
||
|
app.vco1.Process();
|
||
|
app.vco2.Process();
|
||
|
app.vcf1.Process();
|
||
|
app.vcf2.Process();
|
||
|
app.vca1.Process();
|
||
|
app.vca2.Process();
|
||
|
app.lfo1.Process();
|
||
|
app.lfo2.Process();
|
||
|
app.env1.Process();
|
||
|
app.env2.Process();
|
||
|
app.ring.Process();
|
||
|
app.sh.Process();
|
||
|
app.mix.Process();
|
||
|
switch (audioif.enable) {
|
||
|
case 1:
|
||
|
for (var j = 0; j < 128; ++j) {
|
||
|
audiomix.queout[audiomix.windex][(ilp + j) << 1] = app.mix.buf[j];
|
||
|
audiomix.queout[audiomix.windex][((ilp + j) << 1) + 1] = app.mix.buf[j];
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
for (var j = 0; j < 128; ++j) {
|
||
|
audiomix.queout[audiomix.windex][ilp + j] = app.mix.buf[j];
|
||
|
audiomix.queout2[audiomix.windex][ilp + j] = app.mix.buf[j];
|
||
|
}
|
||
|
break;
|
||
|
case 3:
|
||
|
for (var j = 0; j < 128; ++j) {
|
||
|
audiomix.queout[audiomix.windex][ilp + j] = app.mix.buf[j];
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
audiomix.windex = (audiomix.windex + 1) % outquenum;
|
||
|
}
|
||
|
}
|
||
|
function Setup() {
|
||
|
for (var i in app.knobs.knobs) {
|
||
|
var widget = app.knobs.knobs[i];
|
||
|
if (widget.ty == 0) {
|
||
|
widget.Connect(null);
|
||
|
}
|
||
|
else if (widget.ty < 100) {
|
||
|
widget.fanout = 0;
|
||
|
}
|
||
|
if (widget.ty >= 100 && widget.ty < 200)
|
||
|
widget.Set(0);
|
||
|
}
|
||
|
app.knobs.knobs["vco1.oct"].Set(0.5);
|
||
|
app.knobs.knobs["vco1.form"].Set(0.5);
|
||
|
app.knobs.knobs["vco1.co"].Set(0.5);
|
||
|
app.knobs.knobs["vco1.pi"].Set(0.5);
|
||
|
app.knobs.knobs["vco1.m1m"].Set(1);
|
||
|
app.knobs.knobs["vco2.oct"].Set(0.5);
|
||
|
app.knobs.knobs["vco2.form"].Set(0.5);
|
||
|
app.knobs.knobs["vco2.co"].Set(0.5);
|
||
|
app.knobs.knobs["vco2.pi"].Set(0.48);
|
||
|
app.knobs.knobs["vco2.m1m"].Set(1);
|
||
|
app.knobs.knobs["vcf1.i1m"].Set(0.7);
|
||
|
app.knobs.knobs["vcf1.f"].Set(1);
|
||
|
app.knobs.knobs["vcf1.r"].Set(0.5);
|
||
|
app.knobs.knobs["vcf1.m1m"].Set(1);
|
||
|
app.knobs.knobs["vcf2.i1m"].Set(0.7);
|
||
|
app.knobs.knobs["vcf2.f"].Set(0.8);
|
||
|
app.knobs.knobs["vcf2.r"].Set(0.5);
|
||
|
app.knobs.knobs["vcf2.m1m"].Set(1);
|
||
|
app.knobs.knobs["vca1.i1m"].Set(0.7);
|
||
|
app.knobs.knobs["vca1.m1m"].Set(1);
|
||
|
app.knobs.knobs["vca2.i1m"].Set(0.7);
|
||
|
app.knobs.knobs["vca2.m1m"].Set(1);
|
||
|
app.knobs.knobs["env1.s"].Set(1);
|
||
|
app.knobs.knobs["env2.s"].Set(1);
|
||
|
app.knobs.knobs["lfo1.f"].Set(0.5);
|
||
|
app.knobs.knobs["lfo1.form"].Set(0.5);
|
||
|
app.knobs.knobs["lfo2.f"].Set(0.5);
|
||
|
app.knobs.knobs["lfo2.form"].Set(0.5);
|
||
|
app.knobs.knobs["mix.i1m"].Set(0.5);
|
||
|
app.knobs.knobs["mix.i2m"].Set(0.5);
|
||
|
var n = document.getElementById("patch").selectedIndex;
|
||
|
switch (n) {
|
||
|
case 0:
|
||
|
break;
|
||
|
case 1:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
break;
|
||
|
case 2:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
|
||
|
app.knobs.knobs["vco2.oct"].Set(0);
|
||
|
app.knobs.knobs["vcf1.i2m"].Set(0.7);
|
||
|
break;
|
||
|
case 3:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["env2.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["vcf2.i1"].Connect(app.knobs.knobs["vco2.o"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
|
||
|
app.knobs.knobs["vca2.i1"].Connect(app.knobs.knobs["vcf2.o"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["mix.i2"].Connect(app.knobs.knobs["vca2.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
|
||
|
app.knobs.knobs["vca2.m1"].Connect(app.knobs.knobs["env2.op"]);
|
||
|
app.knobs.knobs["vcf1.f"].Set(0.6);
|
||
|
app.knobs.knobs["vcf1.r"].Set(0.6);
|
||
|
app.knobs.knobs["vcf2.f"].Set(0.7);
|
||
|
app.knobs.knobs["vcf2.r"].Set(1);
|
||
|
app.knobs.knobs["vco2.oct"].Set(0);
|
||
|
app.knobs.knobs["env1.d"].Set(0.8);
|
||
|
app.knobs.knobs["env1.s"].Set(0.1);
|
||
|
break;
|
||
|
case 4:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
|
||
|
app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["lfo1.o10"]);
|
||
|
app.knobs.knobs["vcf1.m2"].Connect(app.knobs.knobs["lfo1.o"]);
|
||
|
app.knobs.knobs["vcf1.i2m"].Set(0.8);
|
||
|
app.knobs.knobs["vco1.m2m"].Set(0.1);
|
||
|
app.knobs.knobs["vcf1.m2m"].Set(0.5);
|
||
|
app.knobs.knobs["lfo1.f"].Set(0.4);
|
||
|
app.knobs.knobs["lfo1.form"].Set(1);
|
||
|
break;
|
||
|
case 5:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
|
||
|
app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["lfo1.o10"]);
|
||
|
app.knobs.knobs["vcf1.m2"].Connect(app.knobs.knobs["lfo1.o"]);
|
||
|
app.knobs.knobs["vcf1.i3"].Connect(app.knobs.knobs["noise.o"]);
|
||
|
app.knobs.knobs["sh.i"].Connect(app.knobs.knobs["noise.o"]);
|
||
|
app.knobs.knobs["sh.tr"].Connect(app.knobs.knobs["lfo2.o"]);
|
||
|
app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["sh.o"]);
|
||
|
app.knobs.knobs["vcf1.i2m"].Set(0.5);
|
||
|
app.knobs.knobs["vcf1.i3m"].Set(0.4);
|
||
|
app.knobs.knobs["vcf1.r"].Set(0.8);
|
||
|
app.knobs.knobs["vco1.m2m"].Set(0.2);
|
||
|
app.knobs.knobs["vcf1.m2m"].Set(0.5);
|
||
|
app.knobs.knobs["lfo1.f"].Set(0.4);
|
||
|
app.knobs.knobs["lfo1.form"].Set(1);
|
||
|
app.knobs.knobs["lfo2.f"].Set(0.7);
|
||
|
break;
|
||
|
case 6:
|
||
|
app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["ring.o"]);
|
||
|
app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vca2.o"]);
|
||
|
app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
|
||
|
app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
|
||
|
app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
|
||
|
app.knobs.knobs["vca2.i1"].Connect(app.knobs.knobs["noise.o"]);
|
||
|
app.knobs.knobs["vca2.m1"].Connect(app.knobs.knobs["env2.op"]);
|
||
|
app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["env2.tr"].Connect(app.knobs.knobs["kb.g"]);
|
||
|
app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
|
||
|
app.knobs.knobs["ring.i1"].Connect(app.knobs.knobs["vco1.o"]);
|
||
|
app.knobs.knobs["ring.i2"].Connect(app.knobs.knobs["vco2.o"]);
|
||
|
app.knobs.knobs["vco1.form"].Set(1);
|
||
|
app.knobs.knobs["vco2.form"].Set(1);
|
||
|
app.knobs.knobs["vco2.pi"].Set(0);
|
||
|
app.knobs.knobs["vco2.m1m"].Set(0.5);
|
||
|
app.knobs.knobs["vcf1.i2m"].Set(0.5);
|
||
|
app.knobs.knobs["vcf1.r"].Set(0.8);
|
||
|
app.knobs.knobs["vcf1.f"].Set(0.5);
|
||
|
app.knobs.knobs["env1.d"].Set(0.75);
|
||
|
app.knobs.knobs["env1.s"].Set(0);
|
||
|
app.knobs.knobs["env1.r"].Set(0.75);
|
||
|
app.knobs.knobs["env2.s"].Set(0);
|
||
|
app.knobs.knobs["env2.d"].Set(0.8);
|
||
|
app.knobs.knobs["env2.r"].Set(0.8);
|
||
|
app.knobs.knobs["mix.i1m"].Set(0.75);
|
||
|
break;
|
||
|
}
|
||
|
app.Draw();
|
||
|
}
|