update to latest libraries
This commit is contained in:
parent
61f1a05ebe
commit
eb21d1f743
31 changed files with 2935 additions and 1227 deletions
154
js/Color.js
154
js/Color.js
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
|
||||
Color.Space : 0.3 : mudcu.be
|
||||
-----------------------------
|
||||
STRING <-> HEX <-> RGB <-> HSL
|
||||
-----------------------------
|
||||
var HEX = 0xFF0000;
|
||||
var HSL = Color.Space(HEX, "HEX>RGB>HSL");
|
||||
|
||||
*/
|
||||
|
||||
if (!window.Color) Color = {};
|
||||
if (!window.Color.Space) Color.Space = {};
|
||||
|
||||
(function () {
|
||||
|
||||
var DEG_RAD = Math.PI / 180;
|
||||
var RAD_DEG = 1 / DEG_RAD;
|
||||
|
||||
var shortcuts = { };
|
||||
var root = Color.Space = function(color, route) {
|
||||
if (shortcuts[route]) {
|
||||
route = shortcuts[route];
|
||||
}
|
||||
var arr = route.split(">");
|
||||
var key = "";
|
||||
for (var n = 0; n < arr.length; n ++) {
|
||||
if (n > 1) {
|
||||
key = key.split("_");
|
||||
key.shift();
|
||||
key = key.join("_");
|
||||
}
|
||||
key += (n == 0 ? "" : "_") + arr[n];
|
||||
if (n > 0) color = root[key](color);
|
||||
}
|
||||
return color;
|
||||
};
|
||||
|
||||
// STRING = 'FFFFFF' | 'FFFFFFFF'
|
||||
|
||||
root.STRING_HEX = function (o) {
|
||||
return parseInt('0x' + o);
|
||||
};
|
||||
|
||||
// HEX = 0x000000 -> 0xFFFFFF
|
||||
|
||||
root.HEX_STRING = function (o, maxLength) {
|
||||
if (!maxLength) maxLength = 6;
|
||||
if (!o) o = 0;
|
||||
var z = o.toString(16);
|
||||
// when string is lesser than maxLength
|
||||
var n = z.length;
|
||||
while (n < maxLength) {
|
||||
z = '0' + z;
|
||||
n++;
|
||||
}
|
||||
// when string is greater than maxLength
|
||||
var n = z.length;
|
||||
while (n > maxLength) {
|
||||
z = z.substr(1);
|
||||
n--;
|
||||
}
|
||||
return z;
|
||||
};
|
||||
|
||||
root.HEX_RGB = function (o) {
|
||||
return {
|
||||
R: (o >> 16),
|
||||
G: (o >> 8) & 0xFF,
|
||||
B: o & 0xFF
|
||||
};
|
||||
};
|
||||
|
||||
// RGB = R: Red / G: Green / B: Blue
|
||||
|
||||
root.RGB_HEX = function (o) {
|
||||
if (o.R < 0) o.R = 0;
|
||||
if (o.G < 0) o.G = 0;
|
||||
if (o.B < 0) o.B = 0;
|
||||
if (o.R > 255) o.R = 255;
|
||||
if (o.G > 255) o.G = 255;
|
||||
if (o.B > 255) o.B = 255;
|
||||
return o.R << 16 | o.G << 8 | o.B;
|
||||
};
|
||||
|
||||
root.RGB_HSL = function (o) { // RGB from 0 to 1
|
||||
// http://www.easyrgb.com/index.php?X=MATH&H=18#text18
|
||||
var _R = o.R / 255,
|
||||
_G = o.G / 255,
|
||||
_B = o.B / 255,
|
||||
min = Math.min(_R, _G, _B),
|
||||
max = Math.max(_R, _G, _B),
|
||||
D = max - min,
|
||||
H,
|
||||
S,
|
||||
L = (max + min) / 2;
|
||||
if (D == 0) { // No chroma
|
||||
H = 0;
|
||||
S = 0;
|
||||
} else { // Chromatic data
|
||||
if (L < 0.5) S = D / (max + min);
|
||||
else S = D / (2 - max - min);
|
||||
var DR = (((max - _R) / 6) + (D / 2)) / D;
|
||||
var DG = (((max - _G) / 6) + (D / 2)) / D;
|
||||
var DB = (((max - _B) / 6) + (D / 2)) / D;
|
||||
if (_R == max) H = DB - DG;
|
||||
else if (_G == max) H = (1 / 3) + DR - DB;
|
||||
else if (_B == max) H = (2 / 3) + DG - DR;
|
||||
if (H < 0) H += 1;
|
||||
if (H > 1) H -= 1;
|
||||
}
|
||||
return {
|
||||
H: H * 360,
|
||||
S: S * 100,
|
||||
L: L * 100
|
||||
};
|
||||
};
|
||||
|
||||
// HSL (1978) = H: Hue / S: Saturation / L: Lightess
|
||||
|
||||
root.HSL_RGB = function (o) {
|
||||
// http://www.easyrgb.com/index.php?X=MATH&H=19
|
||||
var H = o.H / 360,
|
||||
S = o.S / 100,
|
||||
L = o.L / 100,
|
||||
R, G, B, _1, _2;
|
||||
function Hue_2_RGB(v1, v2, vH) {
|
||||
if (vH < 0) vH += 1;
|
||||
if (vH > 1) vH -= 1;
|
||||
if ((6 * vH) < 1) return v1 + (v2 - v1) * 6 * vH;
|
||||
if ((2 * vH) < 1) return v2;
|
||||
if ((3 * vH) < 2) return v1 + (v2 - v1) * ((2 / 3) - vH) * 6;
|
||||
return v1;
|
||||
}
|
||||
if (S == 0) { // HSL from 0 to 1
|
||||
R = L * 255;
|
||||
G = L * 255;
|
||||
B = L * 255;
|
||||
} else {
|
||||
if (L < 0.5) _2 = L * (1 + S);
|
||||
else _2 = (L + S) - (S * L);
|
||||
_1 = 2 * L - _2;
|
||||
R = 255 * Hue_2_RGB(_1, _2, H + (1 / 3));
|
||||
G = 255 * Hue_2_RGB(_1, _2, H);
|
||||
B = 255 * Hue_2_RGB(_1, _2, H - (1 / 3));
|
||||
}
|
||||
return {
|
||||
R: R,
|
||||
G: G,
|
||||
B: B
|
||||
};
|
||||
};
|
||||
|
||||
})();
|
439
js/Color/Space.js
Normal file
439
js/Color/Space.js
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
----------------------------------------------------
|
||||
Color Space : 1.2 : 2012.09.01 : http://mudcu.be
|
||||
----------------------------------------------------
|
||||
RGBA <-> HSLA <-> W3
|
||||
RGBA <-> HSVA
|
||||
RGBA <-> CMY <-> CMYK
|
||||
RGBA <-> HEX24 <-> W3
|
||||
RGBA <-> HEX32
|
||||
RGBA <-> W3
|
||||
----------------------------------------------------
|
||||
Examples
|
||||
----------------------------------------------------
|
||||
Color.Space(0x99ff0000, "HEX32>RGBA>HSLA>W3"); // outputs "hsla(60,100%,17%,0.6)"
|
||||
Color.Space(0xFF0000, "HEX24>RGB>HSL"); // convert hex24 to HSL object.
|
||||
----------------------------------------------------
|
||||
W3 values
|
||||
----------------------------------------------------
|
||||
rgb(255,0,0)
|
||||
rgba(255,0,0,1)
|
||||
rgb(100%,0%,0%)
|
||||
rgba(100%,0%,0%,1)
|
||||
hsl(120, 100%, 50%)
|
||||
hsla(120, 100%, 50%, 1)
|
||||
#000000
|
||||
*/
|
||||
|
||||
if (typeof(Color) === "undefined") Color = {};
|
||||
if (typeof(Color.Space) === "undefined") Color.Space = {};
|
||||
|
||||
(function () {
|
||||
|
||||
var functions = {
|
||||
// holds generated cached conversion functions.
|
||||
};
|
||||
var shortcuts = {
|
||||
"HEX24>HSL": "HEX24>RGB>HSL",
|
||||
"HEX32>HSLA": "HEX32>RGBA>HSLA",
|
||||
"HEX24>CMYK": "HEX24>RGB>CMY>CMYK",
|
||||
"RGB>CMYK": "RGB>CMY>CMYK"
|
||||
};
|
||||
|
||||
var root = Color.Space = function(color, route) {
|
||||
if (shortcuts[route]) { // shortcut available
|
||||
route = shortcuts[route];
|
||||
}
|
||||
var r = route.split(">");
|
||||
// check whether color is an [], if so, convert to {}
|
||||
if (typeof(color) === "object" && color[0] >= 0) { // array
|
||||
var type = r[0];
|
||||
var tmp = {};
|
||||
for(var i = 0; i < type.length; i ++) {
|
||||
var str = type.substr(i, 1);
|
||||
tmp[str] = color[i];
|
||||
}
|
||||
color = tmp;
|
||||
}
|
||||
if (functions[route]) { // cached function available
|
||||
return functions[route](color);
|
||||
}
|
||||
var f = "color";
|
||||
for (var pos = 1, key = r[0]; pos < r.length; pos ++) {
|
||||
if (pos > 1) { // recycle previous
|
||||
key = key.substr(key.indexOf("_") + 1);
|
||||
}
|
||||
key += (pos === 0 ? "" : "_") + r[pos];
|
||||
color = root[key](color);
|
||||
f = "Color.Space."+key+"("+f+")";
|
||||
}
|
||||
|
||||
functions[route] = eval("(function(color) { return "+f+" })");
|
||||
return color;
|
||||
};
|
||||
|
||||
// W3C - RGB + RGBA
|
||||
|
||||
root.RGB_W3 = function(o) {
|
||||
return "rgb(" + (o.R >> 0) + "," + (o.G >> 0) + "," + (o.B >> 0) + ")";
|
||||
};
|
||||
|
||||
root.RGBA_W3 = function(o) {
|
||||
var alpha = typeof(o.A) === "number" ? o.A / 255 : 1;
|
||||
return "rgba(" + (o.R >> 0) + "," + (o.G >> 0) + "," + (o.B >> 0) + "," + alpha + ")";
|
||||
};
|
||||
|
||||
root.W3_RGB = function(o) {
|
||||
var o = o.substr(4, o.length - 5).split(",");
|
||||
return {
|
||||
R: parseInt(o[0]),
|
||||
G: parseInt(o[1]),
|
||||
B: parseInt(o[2])
|
||||
}
|
||||
};
|
||||
|
||||
root.W3_RGBA = function(o) {
|
||||
var o = o.substr(5, o.length - 6).split(",");
|
||||
return {
|
||||
R: parseInt(o[0]),
|
||||
G: parseInt(o[1]),
|
||||
B: parseInt(o[2]),
|
||||
A: parseFloat(o[3]) * 255
|
||||
}
|
||||
};
|
||||
|
||||
// W3C - HSL + HSLA
|
||||
|
||||
root.HSL_W3 = function(o) {
|
||||
return "hsl(" + ((o.H + 0.5) >> 0) + "," + ((o.S + 0.5) >> 0) + "%," + ((o.L + 0.5) >> 0) + "%)";
|
||||
};
|
||||
|
||||
root.HSLA_W3 = function(o) {
|
||||
var alpha = typeof(o.A) === "number" ? o.A / 255 : 1;
|
||||
return "hsla(" + ((o.H + 0.5) >> 0) + "," + ((o.S + 0.5) >> 0) + "%," + ((o.L + 0.5) >> 0) + "%," + alpha + ")";
|
||||
};
|
||||
|
||||
root.W3_HSL = function(o) {
|
||||
var o = o.substr(4, o.length - 5).split(",");
|
||||
return {
|
||||
H: parseInt(o[0]),
|
||||
S: parseInt(o[1]),
|
||||
L: parseInt(o[2])
|
||||
}
|
||||
};
|
||||
|
||||
root.W3_HSLA = function(o) {
|
||||
var o = o.substr(5, o.length - 6).split(",");
|
||||
return {
|
||||
H: parseInt(o[0]),
|
||||
S: parseInt(o[1]),
|
||||
L: parseInt(o[2]),
|
||||
A: parseFloat(o[3]) * 255
|
||||
}
|
||||
};
|
||||
|
||||
// W3 HEX = "FFFFFF" | "FFFFFFFF"
|
||||
|
||||
root.W3_HEX =
|
||||
root.W3_HEX24 = function (o) {
|
||||
if (o.substr(0, 1) === "#") o = o.substr(1);
|
||||
if (o.length === 3) o = o[0] + o[0] + o[1] + o[1] + o[2] + o[2];
|
||||
return parseInt("0x" + o);
|
||||
};
|
||||
|
||||
root.W3_HEX32 = function (o) {
|
||||
if (o.substr(0, 1) === "#") o = o.substr(1);
|
||||
if (o.length === 6) {
|
||||
return parseInt("0xFF" + o);
|
||||
} else {
|
||||
return parseInt("0x" + o);
|
||||
}
|
||||
};
|
||||
|
||||
// HEX = 0x000000 -> 0xFFFFFF
|
||||
|
||||
root.HEX_W3 =
|
||||
root.HEX24_W3 = function (o, maxLength) {
|
||||
if (!maxLength) maxLength = 6;
|
||||
if (!o) o = 0;
|
||||
var z = o.toString(16);
|
||||
// when string is lesser than maxLength
|
||||
var n = z.length;
|
||||
while (n < maxLength) {
|
||||
z = "0" + z;
|
||||
n++;
|
||||
}
|
||||
// when string is greater than maxLength
|
||||
var n = z.length;
|
||||
while (n > maxLength) {
|
||||
z = z.substr(1);
|
||||
n--;
|
||||
}
|
||||
return "#" + z;
|
||||
};
|
||||
|
||||
root.HEX32_W3 = function(o) {
|
||||
return root.HEX_W3(o, 8);
|
||||
};
|
||||
|
||||
root.HEX_RGB =
|
||||
root.HEX24_RGB = function (o) {
|
||||
return {
|
||||
R: (o >> 16),
|
||||
G: (o >> 8) & 0xFF,
|
||||
B: o & 0xFF
|
||||
};
|
||||
};
|
||||
|
||||
// HEX32 = 0x00000000 -> 0xFFFFFFFF
|
||||
|
||||
root.HEX32_RGBA = function (o) {
|
||||
return {
|
||||
R: o >>> 16 & 0xFF,
|
||||
G: o >>> 8 & 0xFF,
|
||||
B: o & 0xFF,
|
||||
A: o >>> 24
|
||||
};
|
||||
};
|
||||
|
||||
// RGBA = R: Red / G: Green / B: Blue / A: Alpha
|
||||
|
||||
root.RGBA_HEX32 = function (o) {
|
||||
return (o.A << 24 | o.R << 16 | o.G << 8 | o.B) >>> 0;
|
||||
};
|
||||
|
||||
// RGB = R: Red / G: Green / B: Blue
|
||||
|
||||
root.RGB_HEX24 =
|
||||
root.RGB_HEX = function (o) {
|
||||
if (o.R < 0) o.R = 0;
|
||||
if (o.G < 0) o.G = 0;
|
||||
if (o.B < 0) o.B = 0;
|
||||
if (o.R > 255) o.R = 255;
|
||||
if (o.G > 255) o.G = 255;
|
||||
if (o.B > 255) o.B = 255;
|
||||
return o.R << 16 | o.G << 8 | o.B;
|
||||
};
|
||||
|
||||
root.RGB_CMY = function (o) {
|
||||
return {
|
||||
C: 1 - (o.R / 255),
|
||||
M: 1 - (o.G / 255),
|
||||
Y: 1 - (o.B / 255)
|
||||
};
|
||||
};
|
||||
|
||||
root.RGBA_HSLA =
|
||||
root.RGB_HSL = function (o) { // RGB from 0 to 1
|
||||
var _R = o.R / 255,
|
||||
_G = o.G / 255,
|
||||
_B = o.B / 255,
|
||||
min = Math.min(_R, _G, _B),
|
||||
max = Math.max(_R, _G, _B),
|
||||
D = max - min,
|
||||
H,
|
||||
S,
|
||||
L = (max + min) / 2;
|
||||
if (D === 0) { // No chroma
|
||||
H = 0;
|
||||
S = 0;
|
||||
} else { // Chromatic data
|
||||
if (L < 0.5) S = D / (max + min);
|
||||
else S = D / (2 - max - min);
|
||||
var DR = (((max - _R) / 6) + (D / 2)) / D;
|
||||
var DG = (((max - _G) / 6) + (D / 2)) / D;
|
||||
var DB = (((max - _B) / 6) + (D / 2)) / D;
|
||||
if (_R === max) H = DB - DG;
|
||||
else if (_G === max) H = (1 / 3) + DR - DB;
|
||||
else if (_B === max) H = (2 / 3) + DG - DR;
|
||||
if (H < 0) H += 1;
|
||||
if (H > 1) H -= 1;
|
||||
}
|
||||
return {
|
||||
H: H * 360,
|
||||
S: S * 100,
|
||||
L: L * 100,
|
||||
A: o.A
|
||||
};
|
||||
};
|
||||
|
||||
root.RGBA_HSVA =
|
||||
root.RGB_HSV = function (o) { //- RGB from 0 to 255
|
||||
var _R = o.R / 255,
|
||||
_G = o.G / 255,
|
||||
_B = o.B / 255,
|
||||
min = Math.min(_R, _G, _B),
|
||||
max = Math.max(_R, _G, _B),
|
||||
D = max - min,
|
||||
H,
|
||||
S,
|
||||
V = max;
|
||||
if (D === 0) { // No chroma
|
||||
H = 0;
|
||||
S = 0;
|
||||
} else { // Chromatic data
|
||||
S = D / max;
|
||||
var DR = (((max - _R) / 6) + (D / 2)) / D;
|
||||
var DG = (((max - _G) / 6) + (D / 2)) / D;
|
||||
var DB = (((max - _B) / 6) + (D / 2)) / D;
|
||||
if (_R === max) H = DB - DG;
|
||||
else if (_G === max) H = (1 / 3) + DR - DB;
|
||||
else if (_B === max) H = (2 / 3) + DG - DR;
|
||||
if (H < 0) H += 1;
|
||||
if (H > 1) H -= 1;
|
||||
}
|
||||
return {
|
||||
H: H * 360,
|
||||
S: S * 100,
|
||||
V: V * 100,
|
||||
A: o.A
|
||||
};
|
||||
};
|
||||
|
||||
// CMY = C: Cyan / M: Magenta / Y: Yellow
|
||||
|
||||
root.CMY_RGB = function (o) {
|
||||
return {
|
||||
R: Math.max(0, (1 - o.C) * 255),
|
||||
G: Math.max(0, (1 - o.M) * 255),
|
||||
B: Math.max(0, (1 - o.Y) * 255)
|
||||
};
|
||||
};
|
||||
|
||||
root.CMY_CMYK = function (o) {
|
||||
var C = o.C;
|
||||
var M = o.M;
|
||||
var Y = o.Y;
|
||||
var K = Math.min(Y, Math.min(M, Math.min(C, 1)));
|
||||
C = Math.round((C - K) / (1 - K) * 100);
|
||||
M = Math.round((M - K) / (1 - K) * 100);
|
||||
Y = Math.round((Y - K) / (1 - K) * 100);
|
||||
K = Math.round(K * 100);
|
||||
return {
|
||||
C: C,
|
||||
M: M,
|
||||
Y: Y,
|
||||
K: K
|
||||
};
|
||||
};
|
||||
|
||||
// CMYK = C: Cyan / M: Magenta / Y: Yellow / K: Key (black)
|
||||
|
||||
root.CMYK_CMY = function (o) {
|
||||
return {
|
||||
C: (o.C * (1 - o.K) + o.K),
|
||||
M: (o.M * (1 - o.K) + o.K),
|
||||
Y: (o.Y * (1 - o.K) + o.K)
|
||||
};
|
||||
};
|
||||
|
||||
// HSL (1978) = H: Hue / S: Saturation / L: Lightess
|
||||
// en.wikipedia.org/wiki/HSL_and_HSV
|
||||
|
||||
root.HSLA_RGBA =
|
||||
root.HSL_RGB = function (o) {
|
||||
var H = o.H / 360;
|
||||
var S = o.S / 100;
|
||||
var L = o.L / 100;
|
||||
var R, G, B;
|
||||
var temp1, temp2, temp3;
|
||||
if (S === 0) {
|
||||
R = G = B = L;
|
||||
} else {
|
||||
if (L < 0.5) temp2 = L * (1 + S);
|
||||
else temp2 = (L + S) - (S * L);
|
||||
temp1 = 2 * L - temp2;
|
||||
// calculate red
|
||||
temp3 = H + (1 / 3);
|
||||
if (temp3 < 0) temp3 += 1;
|
||||
if (temp3 > 1) temp3 -= 1;
|
||||
if ((6 * temp3) < 1) R = temp1 + (temp2 - temp1) * 6 * temp3;
|
||||
else if ((2 * temp3) < 1) R = temp2;
|
||||
else if ((3 * temp3) < 2) R = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
||||
else R = temp1;
|
||||
// calculate green
|
||||
temp3 = H;
|
||||
if (temp3 < 0) temp3 += 1;
|
||||
if (temp3 > 1) temp3 -= 1;
|
||||
if ((6 * temp3) < 1) G = temp1 + (temp2 - temp1) * 6 * temp3;
|
||||
else if ((2 * temp3) < 1) G = temp2;
|
||||
else if ((3 * temp3) < 2) G = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
||||
else G = temp1;
|
||||
// calculate blue
|
||||
temp3 = H - (1 / 3);
|
||||
if (temp3 < 0) temp3 += 1;
|
||||
if (temp3 > 1) temp3 -= 1;
|
||||
if ((6 * temp3) < 1) B = temp1 + (temp2 - temp1) * 6 * temp3;
|
||||
else if ((2 * temp3) < 1) B = temp2;
|
||||
else if ((3 * temp3) < 2) B = temp1 + (temp2 - temp1) * ((2 / 3) - temp3) * 6;
|
||||
else B = temp1;
|
||||
}
|
||||
return {
|
||||
R: R * 255,
|
||||
G: G * 255,
|
||||
B: B * 255,
|
||||
A: o.A
|
||||
};
|
||||
};
|
||||
|
||||
// HSV (1978) = H: Hue / S: Saturation / V: Value
|
||||
// en.wikipedia.org/wiki/HSL_and_HSV
|
||||
|
||||
root.HSVA_RGBA =
|
||||
root.HSV_RGB = function (o) {
|
||||
var H = o.H / 360;
|
||||
var S = o.S / 100;
|
||||
var V = o.V / 100;
|
||||
var R, G, B;
|
||||
if (S === 0) {
|
||||
R = G = B = Math.round(V * 255);
|
||||
} else {
|
||||
if (H >= 1) H = 0;
|
||||
H = 6 * H;
|
||||
D = H - Math.floor(H);
|
||||
A = Math.round(255 * V * (1 - S));
|
||||
B = Math.round(255 * V * (1 - (S * D)));
|
||||
C = Math.round(255 * V * (1 - (S * (1 - D))));
|
||||
V = Math.round(255 * V);
|
||||
switch (Math.floor(H)) {
|
||||
case 0:
|
||||
R = V;
|
||||
G = C;
|
||||
B = A;
|
||||
break;
|
||||
case 1:
|
||||
R = B;
|
||||
G = V;
|
||||
B = A;
|
||||
break;
|
||||
case 2:
|
||||
R = A;
|
||||
G = V;
|
||||
B = C;
|
||||
break;
|
||||
case 3:
|
||||
R = A;
|
||||
G = B;
|
||||
B = V;
|
||||
break;
|
||||
case 4:
|
||||
R = C;
|
||||
G = A;
|
||||
B = V;
|
||||
break;
|
||||
case 5:
|
||||
R = V;
|
||||
G = A;
|
||||
B = B;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
R: R,
|
||||
G: G,
|
||||
B: B,
|
||||
A: o.A
|
||||
};
|
||||
};
|
||||
|
||||
})();
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
|
||||
Event.Mouse : 0.3.1 : mudcu.be
|
||||
-------------------------------------
|
||||
Event.add(document, "mousedown", function(event) {
|
||||
Event.drag({
|
||||
type: "absolute",
|
||||
event: event,
|
||||
element: document,
|
||||
callback: function (event, coords, state, self) {
|
||||
Event.stopPropagation(event);
|
||||
Event.preventDefault(event);
|
||||
console.log(coords);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// this does the same thing
|
||||
Event.drag({
|
||||
type: "absolute",
|
||||
element: document,
|
||||
callback: function (event, coords, state, self) {
|
||||
console.log(coords);
|
||||
}
|
||||
});
|
||||
|
||||
/// easier mousewheel events
|
||||
Event.mousewheel(window, function(event, state, wheelData, self) {
|
||||
self.stop.prevent.remove();
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Event) === "undefined") var Event = {};
|
||||
|
||||
Event.drag =
|
||||
Event.dragElement = function(props) {
|
||||
var el = props.element || document.body;
|
||||
var doc = el.ownerDocument; // could be within an iframe
|
||||
if (typeof(props.event) === "undefined") { // create event
|
||||
Event.add(el, "mousedown", function(event) {
|
||||
props.event = event;
|
||||
Event.dragElement(props);
|
||||
Event.preventDefault(event);
|
||||
Event.stopPropagation(event);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// functions accessible externally
|
||||
var self = {
|
||||
cancel: function() {
|
||||
Event.remove(doc, "mousemove", mouseMove);
|
||||
Event.remove(doc, "mouseup", mouseUp);
|
||||
}
|
||||
};
|
||||
// event move
|
||||
var mouseMove = function (event, state) {
|
||||
if (typeof(state) === "undefined") state = "move";
|
||||
var coord = Event.coords(event);
|
||||
switch (props.type) {
|
||||
case "move": // move
|
||||
props.callback(event, {
|
||||
x: coord.x + oX - eX,
|
||||
y: coord.y + oY - eY
|
||||
}, state, self);
|
||||
break;
|
||||
case "difference": // relative, from position within element
|
||||
props.callback(event, {
|
||||
x: coord.x - oX,
|
||||
y: coord.y - oY
|
||||
}, state, self);
|
||||
break;
|
||||
case "relative": // eveything is relative from origin
|
||||
props.callback(event, {
|
||||
x: coord.x - eX,
|
||||
y: coord.y - eY
|
||||
}, state, self);
|
||||
break;
|
||||
default: // "absolute", origin is 0x0
|
||||
props.callback(event, {
|
||||
x: coord.x,
|
||||
y: coord.y
|
||||
}, state, self);
|
||||
break;
|
||||
}
|
||||
};
|
||||
// event up
|
||||
var mouseUp = function(event) {
|
||||
self.cancel();
|
||||
mouseMove(event, "up");
|
||||
};
|
||||
// current element position
|
||||
var origin = abPos(el);
|
||||
var oX = origin.x;
|
||||
var oY = origin.y;
|
||||
// current mouse position
|
||||
var event = props.event;
|
||||
var coord = Event.coords(event);
|
||||
var eX = coord.x;
|
||||
var eY = coord.y;
|
||||
// events
|
||||
Event.add(doc, "mousemove", mouseMove);
|
||||
Event.add(doc, "mouseup", mouseUp);
|
||||
mouseMove(event, "down"); // run mouse-down
|
||||
//
|
||||
return self;
|
||||
};
|
||||
|
||||
Event.coords = (function() {
|
||||
if (window.ActiveXObject) {
|
||||
return function(event) {
|
||||
return {
|
||||
x: event.clientX + document.documentElement.scrollLeft,
|
||||
y: event.clientY + document.documentElement.scrollTop
|
||||
};
|
||||
};
|
||||
} else {
|
||||
return function(event) {
|
||||
return {
|
||||
x: event.pageX,
|
||||
y: event.pageY
|
||||
};
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
//////////////// MouseWheel ////////////////
|
||||
|
||||
Event.mousewheel = function(target, listener, timeout) {
|
||||
var interval = 0;
|
||||
var self = Event(target, "mousewheel", function(event) {
|
||||
event = event || window.event;
|
||||
var wheelData = event.detail ? event.detail * -1 : event.wheelDelta / 40;
|
||||
listener(event, "wheel", wheelData);
|
||||
window.clearInterval(interval);
|
||||
interval = window.setInterval(function() {
|
||||
window.clearInterval(interval);
|
||||
listener(event, "wheelup", wheelData, self);
|
||||
}, timeout || 150);
|
||||
});
|
||||
return self;
|
||||
};
|
||||
|
||||
///// DOM.absPos
|
||||
|
||||
var abPos = function(o) {
|
||||
o = typeof(o) === 'object' ? o : document.getElementById(o);
|
||||
var offset = { x: 0, y: 0 };
|
||||
while(o != null) {
|
||||
offset.x += o.offsetLeft;
|
||||
offset.y += o.offsetTop;
|
||||
o = o.offsetParent;
|
||||
};
|
||||
return offset;
|
||||
};
|
1877
js/Event.js
1877
js/Event.js
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
|||
|
||||
MIDI.Player : 0.3
|
||||
-------------------------------------
|
||||
https://github.com/mudx/MIDI.js
|
||||
https://github.com/mudcube/MIDI.js
|
||||
-------------------------------------
|
||||
requires jasmid
|
||||
|
||||
|
@ -56,23 +56,23 @@ root.clearAnimation = function() {
|
|||
|
||||
root.setAnimation = function(config) {
|
||||
var callback = (typeof(config) === "function") ? config : config.callback;
|
||||
var delay = config.delay || 24;
|
||||
var interval = config.interval || 30;
|
||||
var currentTime = 0;
|
||||
var tOurTime = 0;
|
||||
var tTheirTime = 0;
|
||||
//
|
||||
root.clearAnimation();
|
||||
root.interval = window.setInterval(function (){
|
||||
root.interval = window.setInterval(function () {
|
||||
if (root.endTime === 0) return;
|
||||
if (root.playing) {
|
||||
currentTime = (tTheirTime == root.currentTime) ? tOurTime-(new Date()).getTime() : 0;
|
||||
currentTime = (tTheirTime === root.currentTime) ? tOurTime - (new Date).getTime() : 0;
|
||||
if (root.currentTime === 0) {
|
||||
currentTime = 0;
|
||||
} else {
|
||||
currentTime = root.currentTime - currentTime;
|
||||
}
|
||||
if (tTheirTime != root.currentTime) {
|
||||
tOurTime = (new Date()).getTime();
|
||||
if (tTheirTime !== root.currentTime) {
|
||||
tOurTime = (new Date).getTime();
|
||||
tTheirTime = root.currentTime;
|
||||
}
|
||||
} else { // paused
|
||||
|
@ -91,7 +91,7 @@ root.setAnimation = function(config) {
|
|||
end: t2,
|
||||
events: noteRegistrar
|
||||
});
|
||||
}, delay);
|
||||
}, interval);
|
||||
};
|
||||
|
||||
// helpers
|
||||
|
@ -111,6 +111,10 @@ root.loadFile = function (file, callback) {
|
|||
if (callback) callback(data);
|
||||
return;
|
||||
}
|
||||
///
|
||||
var title = file.split(" - ")[1] || file;
|
||||
document.getElementById("playback-title").innerHTML = title.replace(".mid","");
|
||||
///
|
||||
var fetch = new XMLHttpRequest();
|
||||
fetch.open('GET', file);
|
||||
fetch.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
|
@ -123,7 +127,7 @@ root.loadFile = function (file, callback) {
|
|||
for (var z = 0; z < mx; z++) {
|
||||
ff[z] = scc(t.charCodeAt(z) & 255);
|
||||
}
|
||||
var data = ff.join("");
|
||||
var data = ff.join("");
|
||||
root.currentData = data;
|
||||
root.loadMidiFile();
|
||||
if (callback) callback(data);
|
||||
|
@ -140,8 +144,7 @@ var startTime = 0; // to measure time elapse
|
|||
var noteRegistrar = {}; // get event for requested note
|
||||
var onMidiEvent = undefined; // listener callback
|
||||
var scheduleTracking = function (channel, note, currentTime, offset, message, velocity) {
|
||||
var interval = window.setInterval(function () {
|
||||
window.clearInterval(interval);
|
||||
var interval = window.setTimeout(function () {
|
||||
var data = {
|
||||
channel: channel,
|
||||
note: note,
|
|
@ -225,7 +225,11 @@ if (typeof(MusicTheory.Synesthesia) === "undefined") MusicTheory.Synesthesia = {
|
|||
9: [ 29, 94, 52 ],
|
||||
10: [ 62, 78, 74 ],
|
||||
11: [ 60, 90, 60 ]
|
||||
}
|
||||
},
|
||||
'Circle of Fifths (2012)': {
|
||||
ref: "Stuart Wheatman", // http://www.valleysfamilychurch.org/
|
||||
english: [],
|
||||
data: ['#122400', '#2E002E', '#002914', '#470000', '#002142', '#2E2E00', '#290052', '#003D00', '#520029', '#003D3D', '#522900', '#000080', '#244700', '#570057', '#004D26', '#7A0000', '#003B75', '#4C4D00', '#47008F', '#006100', '#850042', '#005C5C', '#804000', '#0000C7', '#366B00', '#80007F', '#00753B', '#B80000', '#0057AD', '#6B6B00', '#6600CC', '#008A00', '#B8005C', '#007F80', '#B35900', '#2424FF', '#478F00', '#AD00AD', '#00994D', '#F00000', '#0073E6', '#8F8F00', '#8A14FF', '#00AD00', '#EB0075', '#00A3A3', '#E07000', '#6B6BFF', '#5CB800', '#DB00DB', '#00C261', '#FF5757', '#3399FF', '#ADAD00', '#B56BFF', '#00D600', '#FF57AB', '#00C7C7', '#FF9124', '#9999FF', '#6EDB00', '#FF29FF', '#00E070', '#FF9999', '#7ABDFF', '#D1D100', '#D1A3FF', '#00FA00', '#FFA3D1', '#00E5E6', '#FFC285', '#C2C2FF', '#80FF00', '#FFA8FF', '#00E070', '#FFCCCC', '#C2E0FF', '#F0F000', '#EBD6FF', '#ADFFAD', '#FFD6EB', '#8AFFFF', '#FFEBD6', '#EBEBFF', '#E0FFC2', '#FFEBFF', '#E5FFF2', '#FFF5F5'] }
|
||||
};
|
||||
|
||||
root.map = function(type) {
|
||||
|
@ -240,18 +244,28 @@ if (typeof(MusicTheory.Synesthesia) === "undefined") MusicTheory.Synesthesia = {
|
|||
var syn = root.data;
|
||||
var colors = syn[type] || syn["D. D. Jameson (1844)"];
|
||||
for (var note = 0; note <= 88; note ++) { // creates mapping for 88 notes
|
||||
var clr = colors[(note + 9) % 12];
|
||||
if (clr[0] == clr[1] && clr[1] == clr[2]) {
|
||||
clr = blend(parray, colors[(note + 10) % 12]);
|
||||
}
|
||||
var amount = clr[2] / 10;
|
||||
var octave = note / 12 >> 0;
|
||||
var octaveLum = clr[2] + amount * octave - 3 * amount; // map luminance to octave
|
||||
data[note] = {
|
||||
hsl: 'hsla(' + clr[0] + ',' + clr[1] + '%,' + octaveLum + '%, 1)',
|
||||
hex: Color.Space({H:clr[0], S:clr[1], L:octaveLum}, "HSL>RGB>HEX>STRING")
|
||||
};
|
||||
var parray = clr;
|
||||
if (colors.data) {
|
||||
data[note] = {
|
||||
hsl: colors.data[note],
|
||||
hex: colors.data[note]
|
||||
}
|
||||
} else {
|
||||
var clr = colors[(note + 9) % 12];
|
||||
var H = clr.H || clr[0];
|
||||
var S = clr.S || clr[1];
|
||||
var L = clr.L || clr[2];
|
||||
if (H == S && S == L) {
|
||||
clr = blend(parray, colors[(note + 10) % 12]);
|
||||
}
|
||||
var amount = L / 10;
|
||||
var octave = note / 12 >> 0;
|
||||
var octaveLum = L + amount * octave - 3 * amount; // map luminance to octave
|
||||
data[note] = {
|
||||
hsl: 'hsla(' + H + ',' + S + '%,' + octaveLum + '%, 1)',
|
||||
hex: Color.Space({H:H, S:S, L:octaveLum}, "HSL>RGB>HEX>W3")
|
||||
};
|
||||
var parray = clr;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
|
@ -1,205 +0,0 @@
|
|||
/*
|
||||
var loader = new widgets.Loader({ message: "loading: New loading message..." });
|
||||
-----
|
||||
var loader = new widgets.Loader({
|
||||
id: "loader",
|
||||
bars: 12,
|
||||
radius: 20,
|
||||
lineWidth: 3,
|
||||
lineHeight: 10
|
||||
});
|
||||
loader.stop();
|
||||
|
||||
loader.message("loading: New loading message...");
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(widgets) === "undefined") widgets = {};
|
||||
|
||||
(function(root) {
|
||||
|
||||
var PI = Math.PI;
|
||||
var defaultConfig = {
|
||||
id: "loader",
|
||||
bars: 12,
|
||||
radius: 0,
|
||||
lineWidth: 20,
|
||||
lineHeight: 70
|
||||
};
|
||||
|
||||
var getWindowSize = function() {
|
||||
if (window.innerWidth && window.innerHeight) {
|
||||
var width = window.innerWidth;
|
||||
var height = window.innerHeight;
|
||||
} else if (document.body && document.body.offsetWidth) {
|
||||
var width = window.innerWidth = document.body.offsetWidth;
|
||||
var height = window.innerHeight = document.body.offsetHeight;
|
||||
} else if (document.compatMode === 'CSS1Compat' && document.documentElement && document.documentElement.offsetWidth) {
|
||||
var width = window.innerWidth = document.documentElement.offsetWidth;
|
||||
var height = window.innerHeight = document.documentElement.offsetHeight;
|
||||
}
|
||||
return {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
};
|
||||
|
||||
root.Loader = function (config) {
|
||||
var that = this;
|
||||
if (!document.body) return;
|
||||
if (!config) config = {};
|
||||
for (var key in defaultConfig) {
|
||||
if (typeof(config[key]) === "undefined") {
|
||||
config[key] = defaultConfig[key];
|
||||
}
|
||||
}
|
||||
//
|
||||
var canvas = document.getElementById(config.id);
|
||||
if (!canvas) {
|
||||
var div = document.createElement("div");
|
||||
div.style.cssText = "color: #fff; pointer-events: none; -webkit-transition-property: opacity; -webkit-transition-duration: .5s; position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 10000; background: rgba(0,0,0,0.5); opacity: 1";
|
||||
if (config.message) {
|
||||
var span = document.createElement("span");
|
||||
span.style.cssText = "font-family: courier; opacity: 1; display: inline-block;background: rgba(0,0,0,0.65); border-radius: 10px; padding: 10px; width: 200px; text-align: center; position: absolute; z-index: 1000;";
|
||||
div.appendChild(span);
|
||||
that.span = span;
|
||||
}
|
||||
var canvas = document.createElement("canvas");
|
||||
document.body.appendChild(canvas);
|
||||
canvas.id = config.id;
|
||||
canvas.style.cssText = "opacity: 1; position: absolute; z-index: 1000;";
|
||||
div.appendChild(canvas);
|
||||
document.body.appendChild(div);
|
||||
} else {
|
||||
that.span = canvas.parentNode.getElementsByTagName("span")[0];
|
||||
}
|
||||
//
|
||||
var max = config.lineHeight + 20;
|
||||
var size = max * 2 + config.radius;
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
if (config.message) {
|
||||
that.span.style.left = ((width + size) / 2 - that.span.offsetWidth/2) + "px";
|
||||
that.span.style.top = (height / 2 + size - 10) + "px";
|
||||
}
|
||||
var that = this;
|
||||
var interval = 0;
|
||||
var offset = 0;
|
||||
var delay = config.delay;
|
||||
var bars = config.bars;
|
||||
var radius = config.radius;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.globalCompositeOperation = "lighter";
|
||||
ctx.shadowOffsetX = 1;
|
||||
ctx.shadowOffsetY = 1;
|
||||
ctx.shadowBlur = 1;
|
||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
|
||||
//
|
||||
function animate() {
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
//
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
if (config.message) {
|
||||
that.span.style.left = ((width + size) / 2 - that.span.offsetWidth/2) + "px";
|
||||
that.span.style.top = (height / 2 + size - 10) + "px";
|
||||
}
|
||||
//
|
||||
ctx.save();
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
ctx.translate(size / 2, size / 2);
|
||||
var hues = 360 - 360 / bars;
|
||||
for (var i = 0; i < bars; i++) {
|
||||
var angle = (i / bars * 2 * PI) + offset;
|
||||
ctx.save();
|
||||
ctx.translate(radius * Math.sin(-angle), radius * Math.cos(-angle));
|
||||
ctx.rotate(angle);
|
||||
// round-rect properties
|
||||
var x = -config.lineWidth / 2;
|
||||
var y = 0;
|
||||
var width = config.lineWidth;
|
||||
var height = config.lineHeight;
|
||||
var curve = width / 2;
|
||||
// round-rect path
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + curve, y);
|
||||
ctx.lineTo(x + width - curve, y);
|
||||
ctx.quadraticCurveTo(x + width, y, x + width, y + curve);
|
||||
ctx.lineTo(x + width, y + height - curve);
|
||||
ctx.quadraticCurveTo(x + width, y + height, x + width - curve, y + height);
|
||||
ctx.lineTo(x + curve, y + height);
|
||||
ctx.quadraticCurveTo(x, y + height, x, y + height - curve);
|
||||
ctx.lineTo(x, y + curve);
|
||||
ctx.quadraticCurveTo(x, y, x + curve, y);
|
||||
// round-rect fill
|
||||
var hue = ((i / (bars - 1)) * hues);
|
||||
ctx.fillStyle = "hsla(" + hue + ", 100%, 50%, 0.85)";
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
offset += 0.07;
|
||||
//
|
||||
if (config.messageAnimate) {
|
||||
var iteration = offset / 0.07 >> 0;
|
||||
if (iteration % 10 === 0) {
|
||||
var length = config.messageAnimate.length;
|
||||
var n = iteration / 10 % length;
|
||||
that.span.innerHTML = config.message + config.messageAnimate[n];
|
||||
}
|
||||
}
|
||||
};
|
||||
//
|
||||
this.message = function(message) {
|
||||
if (!interval) this.start();
|
||||
config.message = message;
|
||||
if (message.substr(-3) === "...") {
|
||||
config.message = message.substr(0, message.length - 3);
|
||||
config.messageAnimate = [ ". ",".. ","..." ].reverse();
|
||||
} else {
|
||||
config.messageAnimate = false;
|
||||
}
|
||||
that.span.innerHTML = config.message + (config.messageAnimate[0] || "");
|
||||
};
|
||||
//
|
||||
this.stop = function () {
|
||||
if (interval) {
|
||||
window.clearInterval(interval);
|
||||
interval = 0;
|
||||
}
|
||||
if (canvas && canvas.style) {
|
||||
canvas.parentNode.style.opacity = 0;
|
||||
window.setTimeout(function () {
|
||||
canvas.parentNode.style.display = "none";
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
//
|
||||
this.start = function (max) {
|
||||
if (interval) return;
|
||||
canvas.parentNode.style.top = document.body.scrollTop + "px";
|
||||
canvas.parentNode.style.opacity = 1;
|
||||
canvas.parentNode.style.display = "block";
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
if (!config.delay) animate();
|
||||
interval = window.setInterval(animate, 30);
|
||||
if (config.message) {
|
||||
this.message(config.message);
|
||||
}
|
||||
};
|
||||
//
|
||||
this.start(30 * 1000);
|
||||
//
|
||||
return this;
|
||||
};
|
||||
|
||||
})(widgets);
|
250
js/Widgets/Loader.js
Normal file
250
js/Widgets/Loader.js
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
----------------------------------------------------
|
||||
Loader.js : 0.3 : 2012/04/12
|
||||
----------------------------------------------------
|
||||
https://github.com/mudcube/Loader.js
|
||||
----------------------------------------------------
|
||||
var loader = new widgets.Loader({ message: "loading: New loading message..." });
|
||||
----------------------------------------------------
|
||||
var loader = new widgets.Loader({
|
||||
id: "loader",
|
||||
bars: 12,
|
||||
radius: 0,
|
||||
lineWidth: 20,
|
||||
lineHeight: 70,
|
||||
background: "rgba(0,0,0,0.5)",
|
||||
message: "loading...",
|
||||
callback: function() {
|
||||
// call function once loader has started
|
||||
}
|
||||
});
|
||||
loader.stop();
|
||||
----------------------------------------------------
|
||||
loader.message("loading: New loading message...", function() {
|
||||
// call function once loader has started
|
||||
});
|
||||
*/
|
||||
|
||||
if (typeof(widgets) === "undefined") var widgets = {};
|
||||
|
||||
widgets.Loader = (function(root) {
|
||||
|
||||
var PI = Math.PI;
|
||||
var defaultConfig = {
|
||||
id: "loader",
|
||||
bars: 12,
|
||||
radius: 0,
|
||||
lineWidth: 20,
|
||||
lineHeight: 70,
|
||||
display: true
|
||||
};
|
||||
|
||||
var getWindowSize = function() {
|
||||
if (window.innerWidth && window.innerHeight) {
|
||||
var width = window.innerWidth;
|
||||
var height = window.innerHeight;
|
||||
} else if (document.compatMode === 'CSS1Compat' && document.documentElement && document.documentElement.offsetWidth) {
|
||||
var width = document.documentElement.offsetWidth;
|
||||
var height = document.documentElement.offsetHeight;
|
||||
} else if (document.body && document.body.offsetWidth) {
|
||||
var width = document.body.offsetWidth;
|
||||
var height = document.body.offsetHeight;
|
||||
}
|
||||
return {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
};
|
||||
|
||||
return function (conf) {
|
||||
var that = this;
|
||||
if (!document.createElement("canvas").getContext) return;
|
||||
var that = this;
|
||||
if (!document.body) return;
|
||||
if (typeof(conf) === "string") conf = { message: conf };
|
||||
if (typeof(conf) === "undefined") conf = {};
|
||||
if (typeof(conf) === "boolean") conf = { display: false };
|
||||
for (var key in defaultConfig) {
|
||||
if (typeof(conf[key]) === "undefined") {
|
||||
conf[key] = defaultConfig[key];
|
||||
}
|
||||
}
|
||||
//
|
||||
function centerSpan() {
|
||||
if (conf.message) {
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
that.span.style.left = ((width + size) / 2 - that.span.offsetWidth/2) + "px";
|
||||
that.span.style.top = (height / 2 + size - 10) + "px";
|
||||
}
|
||||
};
|
||||
///
|
||||
var canvas = document.getElementById(conf.id);
|
||||
var timeout = 1;
|
||||
if (!canvas) {
|
||||
var div = document.createElement("div");
|
||||
var span = document.createElement("span");
|
||||
div.appendChild(span);
|
||||
that.span = span;
|
||||
that.div = div;
|
||||
var canvas = document.createElement("canvas");
|
||||
document.body.appendChild(canvas);
|
||||
canvas.id = conf.id;
|
||||
canvas.style.cssText = "opacity: 1; position: absolute; z-index: 10000;";
|
||||
div.appendChild(canvas);
|
||||
document.body.appendChild(div);
|
||||
} else {
|
||||
that.span = canvas.parentNode.getElementsByTagName("span")[0];
|
||||
}
|
||||
//
|
||||
var delay = conf.delay;
|
||||
var bars = conf.bars;
|
||||
var radius = conf.radius;
|
||||
var max = conf.lineHeight + 20;
|
||||
var size = max * 2 + conf.radius * 2;
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
///
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
///
|
||||
centerSpan();
|
||||
///
|
||||
var offset = 0;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.globalCompositeOperation = "lighter";
|
||||
ctx.shadowOffsetX = 1;
|
||||
ctx.shadowOffsetY = 1;
|
||||
ctx.shadowBlur = 1;
|
||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
|
||||
//
|
||||
function animate() {
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
//
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
centerSpan();
|
||||
//
|
||||
ctx.save();
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
ctx.translate(size / 2, size / 2);
|
||||
var hues = 360 - 360 / bars;
|
||||
for (var i = 0; i < bars; i++) {
|
||||
var angle = (i / bars * 2 * PI) + offset;
|
||||
ctx.save();
|
||||
ctx.translate(radius * Math.sin(-angle), radius * Math.cos(-angle));
|
||||
ctx.rotate(angle);
|
||||
// round-rect properties
|
||||
var x = -conf.lineWidth / 2;
|
||||
var y = 0;
|
||||
var width = conf.lineWidth;
|
||||
var height = conf.lineHeight;
|
||||
var curve = width / 2;
|
||||
// round-rect path
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + curve, y);
|
||||
ctx.lineTo(x + width - curve, y);
|
||||
ctx.quadraticCurveTo(x + width, y, x + width, y + curve);
|
||||
ctx.lineTo(x + width, y + height - curve);
|
||||
ctx.quadraticCurveTo(x + width, y + height, x + width - curve, y + height);
|
||||
ctx.lineTo(x + curve, y + height);
|
||||
ctx.quadraticCurveTo(x, y + height, x, y + height - curve);
|
||||
ctx.lineTo(x, y + curve);
|
||||
ctx.quadraticCurveTo(x, y, x + curve, y);
|
||||
// round-rect fill
|
||||
var hue = ((i / (bars - 1)) * hues);
|
||||
ctx.fillStyle = "hsla(" + hue + ", 100%, 50%, 0.85)";
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
offset += 0.07;
|
||||
//
|
||||
if (conf.messageAnimate) {
|
||||
var iteration = offset / 0.07 >> 0;
|
||||
if (iteration % 10 === 0) {
|
||||
var length = conf.messageAnimate.length;
|
||||
var n = iteration / 10 % length;
|
||||
that.span.innerHTML = conf.message + conf.messageAnimate[n];
|
||||
}
|
||||
}
|
||||
};
|
||||
this.css = function() {
|
||||
var background = conf.background ? conf.background : "rgba(0,0,0,0.65)";
|
||||
span.style.cssText = "font-family: monospace; font-size: 14px; opacity: 1; display: none; background: "+background+"; border-radius: 10px; padding: 10px; width: 200px; text-align: center; position: absolute; z-index: 10000;";
|
||||
div.style.cssText = "color: #fff; -webkit-transition-property: opacity; -webkit-transition-duration: " + timeout + "s; position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 100000; opacity: 0; display: none";
|
||||
if (this.stopPropagation) {
|
||||
div.style.cssText += "background: rgba(0,0,0,0.25);";
|
||||
} else {
|
||||
div.style.cssText += "pointer-events: none;";
|
||||
}
|
||||
};
|
||||
this.stop = function () {
|
||||
setTimeout(function() {
|
||||
window.clearInterval(that.interval);
|
||||
delete that.interval;
|
||||
}, 50);
|
||||
if (canvas && canvas.style) {
|
||||
div.style.cssText += "pointer-events: none;";
|
||||
canvas.parentNode.style.opacity = 0;
|
||||
window.setTimeout(function () {
|
||||
that.stopPropagation = false;
|
||||
canvas.parentNode.style.display = "none";
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
}, timeout * 1000);
|
||||
}
|
||||
};
|
||||
this.start = function (callback) {
|
||||
this.css();
|
||||
var windowSize = getWindowSize();
|
||||
var width = windowSize.width - size;
|
||||
var height = windowSize.height - size;
|
||||
canvas.parentNode.style.opacity = 1;
|
||||
canvas.parentNode.style.display = "block";
|
||||
that.span.style.display = conf.message ? "block" : "none";
|
||||
if (conf.background) that.div.style.background = conf.backgrond;
|
||||
canvas.style.left = (width / 2) + "px";
|
||||
canvas.style.top = (height / 2) + "px";
|
||||
if (!conf.delay) animate();
|
||||
window.clearInterval(this.interval);
|
||||
this.interval = window.setInterval(animate, 30);
|
||||
if (conf.message) {
|
||||
compileMessage(conf.message, callback);
|
||||
}
|
||||
};
|
||||
this.message = function(message, callback) {
|
||||
conf.message = message;
|
||||
if (!this.interval) return this.start(callback);
|
||||
if (conf.background) that.span.style.background = conf.backgrond;
|
||||
compileMessage(conf.message, callback);
|
||||
that.span.style.display = conf.message ? "block" : "none";
|
||||
};
|
||||
var compileMessage = function(message, callback) {
|
||||
if (message.substr(-3) === "...") {
|
||||
conf.message = message.substr(0, message.length - 3);
|
||||
conf.messageAnimate = [ ". ",".. ","..." ].reverse();
|
||||
that.span.innerHTML = conf.message + conf.messageAnimate[0];
|
||||
} else {
|
||||
conf.messageAnimate = false;
|
||||
that.span.innerHTML = conf.message;
|
||||
}
|
||||
if (callback) {
|
||||
setTimeout(callback, 50);
|
||||
}
|
||||
};
|
||||
//
|
||||
if (conf.display === false) return this;
|
||||
//
|
||||
this.css();
|
||||
this.start();
|
||||
//
|
||||
return this;
|
||||
};
|
||||
|
||||
})(widgets);
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2011, Daniel Guerrero
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Daniel Guerrero nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL DANIEL GUERRERO BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
var Base64Binary = {
|
||||
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
|
||||
/* will return a Uint8Array type */
|
||||
decodeArrayBuffer: function(input) {
|
||||
var bytes = Math.ceil( (3*input.length) / 4.0);
|
||||
var ab = new ArrayBuffer(bytes);
|
||||
this.decode(input, ab);
|
||||
|
||||
return ab;
|
||||
},
|
||||
|
||||
decode: function(input, arrayBuffer) {
|
||||
//get last chars to see if are valid
|
||||
var lkey1 = this._keyStr.indexOf(input.charAt(input.length-1));
|
||||
var lkey2 = this._keyStr.indexOf(input.charAt(input.length-1));
|
||||
|
||||
var bytes = Math.ceil( (3*input.length) / 4.0);
|
||||
if (lkey1 == 64) bytes--; //padding chars, so skip
|
||||
if (lkey2 == 64) bytes--; //padding chars, so skip
|
||||
|
||||
var uarray;
|
||||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
|
||||
if (arrayBuffer)
|
||||
uarray = new Uint8Array(arrayBuffer);
|
||||
else
|
||||
uarray = new Uint8Array(bytes);
|
||||
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
|
||||
for (i=0; i<bytes; i+=3) {
|
||||
//get the 3 octects in 4 ascii chars
|
||||
enc1 = this._keyStr.indexOf(input.charAt(j++));
|
||||
enc2 = this._keyStr.indexOf(input.charAt(j++));
|
||||
enc3 = this._keyStr.indexOf(input.charAt(j++));
|
||||
enc4 = this._keyStr.indexOf(input.charAt(j++));
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
uarray[i] = chr1;
|
||||
if (enc3 != 64) uarray[i+1] = chr2;
|
||||
if (enc4 != 64) uarray[i+2] = chr3;
|
||||
}
|
||||
|
||||
return uarray;
|
||||
}
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2010, Matt Westcott & Ben Firshman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The names of its contributors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2010, Matt Westcott & Ben Firshman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The names of its contributors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
class to parse the .mid file format
|
||||
(depends on stream.js)
|
||||
*/
|
||||
function MidiFile(data) {
|
||||
function readChunk(stream) {
|
||||
var id = stream.read(4);
|
||||
var length = stream.readInt32();
|
||||
return {
|
||||
'id': id,
|
||||
'length': length,
|
||||
'data': stream.read(length)
|
||||
};
|
||||
}
|
||||
|
||||
var lastEventTypeByte;
|
||||
|
||||
function readEvent(stream) {
|
||||
var event = {};
|
||||
event.deltaTime = stream.readVarInt();
|
||||
var eventTypeByte = stream.readInt8();
|
||||
if ((eventTypeByte & 0xf0) == 0xf0) {
|
||||
/* system / meta event */
|
||||
if (eventTypeByte == 0xff) {
|
||||
/* meta event */
|
||||
event.type = 'meta';
|
||||
var subtypeByte = stream.readInt8();
|
||||
var length = stream.readVarInt();
|
||||
switch(subtypeByte) {
|
||||
case 0x00:
|
||||
event.subtype = 'sequenceNumber';
|
||||
if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length;
|
||||
event.number = stream.readInt16();
|
||||
return event;
|
||||
case 0x01:
|
||||
event.subtype = 'text';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x02:
|
||||
event.subtype = 'copyrightNotice';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x03:
|
||||
event.subtype = 'trackName';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x04:
|
||||
event.subtype = 'instrumentName';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x05:
|
||||
event.subtype = 'lyrics';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x06:
|
||||
event.subtype = 'marker';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x07:
|
||||
event.subtype = 'cuePoint';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x20:
|
||||
event.subtype = 'midiChannelPrefix';
|
||||
if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length;
|
||||
event.channel = stream.readInt8();
|
||||
return event;
|
||||
case 0x2f:
|
||||
event.subtype = 'endOfTrack';
|
||||
if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length;
|
||||
return event;
|
||||
case 0x51:
|
||||
event.subtype = 'setTempo';
|
||||
if (length != 3) throw "Expected length for setTempo event is 3, got " + length;
|
||||
event.microsecondsPerBeat = (
|
||||
(stream.readInt8() << 16)
|
||||
+ (stream.readInt8() << 8)
|
||||
+ stream.readInt8()
|
||||
)
|
||||
return event;
|
||||
case 0x54:
|
||||
event.subtype = 'smpteOffset';
|
||||
if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length;
|
||||
var hourByte = stream.readInt8();
|
||||
event.frameRate = {
|
||||
0x00: 24, 0x20: 25, 0x40: 29, 0x60: 30
|
||||
}[hourByte & 0x60];
|
||||
event.hour = hourByte & 0x1f;
|
||||
event.min = stream.readInt8();
|
||||
event.sec = stream.readInt8();
|
||||
event.frame = stream.readInt8();
|
||||
event.subframe = stream.readInt8();
|
||||
return event;
|
||||
case 0x58:
|
||||
event.subtype = 'timeSignature';
|
||||
if (length != 4) throw "Expected length for timeSignature event is 4, got " + length;
|
||||
event.numerator = stream.readInt8();
|
||||
event.denominator = Math.pow(2, stream.readInt8());
|
||||
event.metronome = stream.readInt8();
|
||||
event.thirtyseconds = stream.readInt8();
|
||||
return event;
|
||||
case 0x59:
|
||||
event.subtype = 'keySignature';
|
||||
if (length != 2) throw "Expected length for keySignature event is 2, got " + length;
|
||||
event.key = stream.readInt8();
|
||||
event.scale = stream.readInt8();
|
||||
return event;
|
||||
case 0x7f:
|
||||
event.subtype = 'sequencerSpecific';
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
default:
|
||||
// console.log("Unrecognised meta event subtype: " + subtypeByte);
|
||||
event.subtype = 'unknown'
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
}
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else if (eventTypeByte == 0xf0) {
|
||||
event.type = 'sysEx';
|
||||
var length = stream.readVarInt();
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else if (eventTypeByte == 0xf7) {
|
||||
event.type = 'dividedSysEx';
|
||||
var length = stream.readVarInt();
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else {
|
||||
throw "Unrecognised MIDI event type byte: " + eventTypeByte;
|
||||
}
|
||||
} else {
|
||||
/* channel event */
|
||||
var param1;
|
||||
if ((eventTypeByte & 0x80) == 0) {
|
||||
/* running status - reuse lastEventTypeByte as the event type.
|
||||
eventTypeByte is actually the first parameter
|
||||
*/
|
||||
param1 = eventTypeByte;
|
||||
eventTypeByte = lastEventTypeByte;
|
||||
} else {
|
||||
param1 = stream.readInt8();
|
||||
lastEventTypeByte = eventTypeByte;
|
||||
}
|
||||
var eventType = eventTypeByte >> 4;
|
||||
event.channel = eventTypeByte & 0x0f;
|
||||
event.type = 'channel';
|
||||
switch (eventType) {
|
||||
case 0x08:
|
||||
event.subtype = 'noteOff';
|
||||
event.noteNumber = param1;
|
||||
event.velocity = stream.readInt8();
|
||||
return event;
|
||||
case 0x09:
|
||||
event.noteNumber = param1;
|
||||
event.velocity = stream.readInt8();
|
||||
if (event.velocity == 0) {
|
||||
event.subtype = 'noteOff';
|
||||
} else {
|
||||
event.subtype = 'noteOn';
|
||||
}
|
||||
return event;
|
||||
case 0x0a:
|
||||
event.subtype = 'noteAftertouch';
|
||||
event.noteNumber = param1;
|
||||
event.amount = stream.readInt8();
|
||||
return event;
|
||||
case 0x0b:
|
||||
event.subtype = 'controller';
|
||||
event.controllerType = param1;
|
||||
event.value = stream.readInt8();
|
||||
return event;
|
||||
case 0x0c:
|
||||
event.subtype = 'programChange';
|
||||
event.programNumber = param1;
|
||||
return event;
|
||||
case 0x0d:
|
||||
event.subtype = 'channelAftertouch';
|
||||
event.amount = param1;
|
||||
return event;
|
||||
case 0x0e:
|
||||
event.subtype = 'pitchBend';
|
||||
event.value = param1 + (stream.readInt8() << 7);
|
||||
return event;
|
||||
default:
|
||||
throw "Unrecognised MIDI event type: " + eventType
|
||||
/*
|
||||
console.log("Unrecognised MIDI event type: " + eventType);
|
||||
stream.readInt8();
|
||||
event.subtype = 'unknown';
|
||||
return event;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream = Stream(data);
|
||||
var headerChunk = readChunk(stream);
|
||||
if (headerChunk.id != 'MThd' || headerChunk.length != 6) {
|
||||
throw "Bad .mid file - header not found";
|
||||
}
|
||||
var headerStream = Stream(headerChunk.data);
|
||||
var formatType = headerStream.readInt16();
|
||||
var trackCount = headerStream.readInt16();
|
||||
var timeDivision = headerStream.readInt16();
|
||||
|
||||
if (timeDivision & 0x8000) {
|
||||
throw "Expressing time division in SMTPE frames is not supported yet"
|
||||
} else {
|
||||
ticksPerBeat = timeDivision;
|
||||
}
|
||||
|
||||
var header = {
|
||||
'formatType': formatType,
|
||||
'trackCount': trackCount,
|
||||
'ticksPerBeat': ticksPerBeat
|
||||
}
|
||||
var tracks = [];
|
||||
for (var i = 0; i < header.trackCount; i++) {
|
||||
tracks[i] = [];
|
||||
var trackChunk = readChunk(stream);
|
||||
if (trackChunk.id != 'MTrk') {
|
||||
throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id;
|
||||
}
|
||||
var trackStream = Stream(trackChunk.data);
|
||||
while (!trackStream.eof()) {
|
||||
var event = readEvent(trackStream);
|
||||
tracks[i].push(event);
|
||||
//console.log(event);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'header': header,
|
||||
'tracks': tracks
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
var clone = function (o) {
|
||||
if (typeof o != 'object') return (o);
|
||||
if (o == null) return (o);
|
||||
var ret = (typeof o.length == 'number') ? [] : {};
|
||||
for (var key in o) ret[key] = clone(o[key]);
|
||||
return ret;
|
||||
};
|
||||
|
||||
function Replayer(midiFile, timeWarp, eventProcessor) {
|
||||
var trackStates = [];
|
||||
var beatsPerMinute = 120;
|
||||
var ticksPerBeat = midiFile.header.ticksPerBeat;
|
||||
for (var i = 0; i < midiFile.tracks.length; i++) {
|
||||
trackStates[i] = {
|
||||
"nextEventIndex": 0,
|
||||
"ticksToNextEvent": (
|
||||
midiFile.tracks[i].length ? midiFile.tracks[i][0].deltaTime : null
|
||||
)
|
||||
};
|
||||
}
|
||||
function getNextEvent() {
|
||||
var ticksToNextEvent = null;
|
||||
var nextEventTrack = null;
|
||||
var nextEventIndex = null;
|
||||
for (var i = 0; i < trackStates.length; i++) {
|
||||
if (trackStates[i].ticksToNextEvent != null && (ticksToNextEvent == null || trackStates[i].ticksToNextEvent < ticksToNextEvent)) {
|
||||
ticksToNextEvent = trackStates[i].ticksToNextEvent;
|
||||
nextEventTrack = i;
|
||||
nextEventIndex = trackStates[i].nextEventIndex;
|
||||
}
|
||||
}
|
||||
if (nextEventTrack != null) {
|
||||
/// consume event from that track
|
||||
var nextEvent = midiFile.tracks[nextEventTrack][nextEventIndex];
|
||||
if (midiFile.tracks[nextEventTrack][nextEventIndex + 1]) {
|
||||
trackStates[nextEventTrack].ticksToNextEvent += midiFile.tracks[nextEventTrack][nextEventIndex + 1].deltaTime;
|
||||
} else {
|
||||
trackStates[nextEventTrack].ticksToNextEvent = null;
|
||||
}
|
||||
trackStates[nextEventTrack].nextEventIndex += 1;
|
||||
/// advance timings on all tracks by ticksToNextEvent
|
||||
for (var i = 0; i < trackStates.length; i++) {
|
||||
if (trackStates[i].ticksToNextEvent != null) {
|
||||
trackStates[i].ticksToNextEvent -= ticksToNextEvent
|
||||
}
|
||||
}
|
||||
return {
|
||||
"ticksToEvent": ticksToNextEvent,
|
||||
"event": nextEvent,
|
||||
"track": nextEventTrack
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
//
|
||||
var midiEvent;
|
||||
var temporal = [];
|
||||
//
|
||||
function processEvents() {
|
||||
function processNext() {
|
||||
if (midiEvent.ticksToEvent > 0) {
|
||||
var beatsToGenerate = midiEvent.ticksToEvent / ticksPerBeat;
|
||||
var secondsToGenerate = beatsToGenerate / (beatsPerMinute / 60);
|
||||
}
|
||||
var time = (secondsToGenerate * 1000 * timeWarp) || 0;
|
||||
temporal.push([ midiEvent, time]);
|
||||
midiEvent = getNextEvent();
|
||||
};
|
||||
//
|
||||
if (midiEvent = getNextEvent()) {
|
||||
while(midiEvent) processNext(true);
|
||||
}
|
||||
};
|
||||
processEvents();
|
||||
return {
|
||||
"getData": function() {
|
||||
return clone(temporal);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
/* Wrapper for accessing strings through sequential reads */
|
||||
function Stream(str) {
|
||||
var position = 0;
|
||||
|
||||
function read(length) {
|
||||
var result = str.substr(position, length);
|
||||
position += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read a big-endian 32-bit integer */
|
||||
function readInt32() {
|
||||
var result = (
|
||||
(str.charCodeAt(position) << 24)
|
||||
+ (str.charCodeAt(position + 1) << 16)
|
||||
+ (str.charCodeAt(position + 2) << 8)
|
||||
+ str.charCodeAt(position + 3));
|
||||
position += 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read a big-endian 16-bit integer */
|
||||
function readInt16() {
|
||||
var result = (
|
||||
(str.charCodeAt(position) << 8)
|
||||
+ str.charCodeAt(position + 1));
|
||||
position += 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read an 8-bit integer */
|
||||
function readInt8() {
|
||||
var result = str.charCodeAt(position);
|
||||
position += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
function eof() {
|
||||
return position >= str.length;
|
||||
}
|
||||
|
||||
/* read a MIDI-style variable-length integer
|
||||
(big-endian value in groups of 7 bits,
|
||||
with top bit set to signify that another byte follows)
|
||||
*/
|
||||
function readVarInt() {
|
||||
var result = 0;
|
||||
while (true) {
|
||||
var b = readInt8();
|
||||
if (b & 0x80) {
|
||||
result += (b & 0x7f);
|
||||
result <<= 7;
|
||||
} else {
|
||||
/* b is the last byte */
|
||||
return result + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'eof': eof,
|
||||
'read': read,
|
||||
'readInt32': readInt32,
|
||||
'readInt16': readInt16,
|
||||
'readInt8': readInt8,
|
||||
'readVarInt': readVarInt
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
class to parse the .mid file format
|
||||
(depends on stream.js)
|
||||
*/
|
||||
function MidiFile(data) {
|
||||
function readChunk(stream) {
|
||||
var id = stream.read(4);
|
||||
var length = stream.readInt32();
|
||||
return {
|
||||
'id': id,
|
||||
'length': length,
|
||||
'data': stream.read(length)
|
||||
};
|
||||
}
|
||||
|
||||
var lastEventTypeByte;
|
||||
|
||||
function readEvent(stream) {
|
||||
var event = {};
|
||||
event.deltaTime = stream.readVarInt();
|
||||
var eventTypeByte = stream.readInt8();
|
||||
if ((eventTypeByte & 0xf0) == 0xf0) {
|
||||
/* system / meta event */
|
||||
if (eventTypeByte == 0xff) {
|
||||
/* meta event */
|
||||
event.type = 'meta';
|
||||
var subtypeByte = stream.readInt8();
|
||||
var length = stream.readVarInt();
|
||||
switch(subtypeByte) {
|
||||
case 0x00:
|
||||
event.subtype = 'sequenceNumber';
|
||||
if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length;
|
||||
event.number = stream.readInt16();
|
||||
return event;
|
||||
case 0x01:
|
||||
event.subtype = 'text';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x02:
|
||||
event.subtype = 'copyrightNotice';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x03:
|
||||
event.subtype = 'trackName';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x04:
|
||||
event.subtype = 'instrumentName';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x05:
|
||||
event.subtype = 'lyrics';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x06:
|
||||
event.subtype = 'marker';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x07:
|
||||
event.subtype = 'cuePoint';
|
||||
event.text = stream.read(length);
|
||||
return event;
|
||||
case 0x20:
|
||||
event.subtype = 'midiChannelPrefix';
|
||||
if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length;
|
||||
event.channel = stream.readInt8();
|
||||
return event;
|
||||
case 0x2f:
|
||||
event.subtype = 'endOfTrack';
|
||||
if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length;
|
||||
return event;
|
||||
case 0x51:
|
||||
event.subtype = 'setTempo';
|
||||
if (length != 3) throw "Expected length for setTempo event is 3, got " + length;
|
||||
event.microsecondsPerBeat = (
|
||||
(stream.readInt8() << 16)
|
||||
+ (stream.readInt8() << 8)
|
||||
+ stream.readInt8()
|
||||
)
|
||||
return event;
|
||||
case 0x54:
|
||||
event.subtype = 'smpteOffset';
|
||||
if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length;
|
||||
var hourByte = stream.readInt8();
|
||||
event.frameRate = {
|
||||
0x00: 24, 0x20: 25, 0x40: 29, 0x60: 30
|
||||
}[hourByte & 0x60];
|
||||
event.hour = hourByte & 0x1f;
|
||||
event.min = stream.readInt8();
|
||||
event.sec = stream.readInt8();
|
||||
event.frame = stream.readInt8();
|
||||
event.subframe = stream.readInt8();
|
||||
return event;
|
||||
case 0x58:
|
||||
event.subtype = 'timeSignature';
|
||||
if (length != 4) throw "Expected length for timeSignature event is 4, got " + length;
|
||||
event.numerator = stream.readInt8();
|
||||
event.denominator = Math.pow(2, stream.readInt8());
|
||||
event.metronome = stream.readInt8();
|
||||
event.thirtyseconds = stream.readInt8();
|
||||
return event;
|
||||
case 0x59:
|
||||
event.subtype = 'keySignature';
|
||||
if (length != 2) throw "Expected length for keySignature event is 2, got " + length;
|
||||
event.key = stream.readInt8();
|
||||
event.scale = stream.readInt8();
|
||||
return event;
|
||||
case 0x7f:
|
||||
event.subtype = 'sequencerSpecific';
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
default:
|
||||
// console.log("Unrecognised meta event subtype: " + subtypeByte);
|
||||
event.subtype = 'unknown'
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
}
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else if (eventTypeByte == 0xf0) {
|
||||
event.type = 'sysEx';
|
||||
var length = stream.readVarInt();
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else if (eventTypeByte == 0xf7) {
|
||||
event.type = 'dividedSysEx';
|
||||
var length = stream.readVarInt();
|
||||
event.data = stream.read(length);
|
||||
return event;
|
||||
} else {
|
||||
throw "Unrecognised MIDI event type byte: " + eventTypeByte;
|
||||
}
|
||||
} else {
|
||||
/* channel event */
|
||||
var param1;
|
||||
if ((eventTypeByte & 0x80) == 0) {
|
||||
/* running status - reuse lastEventTypeByte as the event type.
|
||||
eventTypeByte is actually the first parameter
|
||||
*/
|
||||
param1 = eventTypeByte;
|
||||
eventTypeByte = lastEventTypeByte;
|
||||
} else {
|
||||
param1 = stream.readInt8();
|
||||
lastEventTypeByte = eventTypeByte;
|
||||
}
|
||||
var eventType = eventTypeByte >> 4;
|
||||
event.channel = eventTypeByte & 0x0f;
|
||||
event.type = 'channel';
|
||||
switch (eventType) {
|
||||
case 0x08:
|
||||
event.subtype = 'noteOff';
|
||||
event.noteNumber = param1;
|
||||
event.velocity = stream.readInt8();
|
||||
return event;
|
||||
case 0x09:
|
||||
event.noteNumber = param1;
|
||||
event.velocity = stream.readInt8();
|
||||
if (event.velocity == 0) {
|
||||
event.subtype = 'noteOff';
|
||||
} else {
|
||||
event.subtype = 'noteOn';
|
||||
}
|
||||
return event;
|
||||
case 0x0a:
|
||||
event.subtype = 'noteAftertouch';
|
||||
event.noteNumber = param1;
|
||||
event.amount = stream.readInt8();
|
||||
return event;
|
||||
case 0x0b:
|
||||
event.subtype = 'controller';
|
||||
event.controllerType = param1;
|
||||
event.value = stream.readInt8();
|
||||
return event;
|
||||
case 0x0c:
|
||||
event.subtype = 'programChange';
|
||||
event.programNumber = param1;
|
||||
return event;
|
||||
case 0x0d:
|
||||
event.subtype = 'channelAftertouch';
|
||||
event.amount = param1;
|
||||
return event;
|
||||
case 0x0e:
|
||||
event.subtype = 'pitchBend';
|
||||
event.value = param1 + (stream.readInt8() << 7);
|
||||
return event;
|
||||
default:
|
||||
throw "Unrecognised MIDI event type: " + eventType
|
||||
/*
|
||||
console.log("Unrecognised MIDI event type: " + eventType);
|
||||
stream.readInt8();
|
||||
event.subtype = 'unknown';
|
||||
return event;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream = Stream(data);
|
||||
var headerChunk = readChunk(stream);
|
||||
if (headerChunk.id != 'MThd' || headerChunk.length != 6) {
|
||||
throw "Bad .mid file - header not found";
|
||||
}
|
||||
var headerStream = Stream(headerChunk.data);
|
||||
var formatType = headerStream.readInt16();
|
||||
var trackCount = headerStream.readInt16();
|
||||
var timeDivision = headerStream.readInt16();
|
||||
|
||||
if (timeDivision & 0x8000) {
|
||||
throw "Expressing time division in SMTPE frames is not supported yet"
|
||||
} else {
|
||||
ticksPerBeat = timeDivision;
|
||||
}
|
||||
|
||||
var header = {
|
||||
'formatType': formatType,
|
||||
'trackCount': trackCount,
|
||||
'ticksPerBeat': ticksPerBeat
|
||||
}
|
||||
var tracks = [];
|
||||
for (var i = 0; i < header.trackCount; i++) {
|
||||
tracks[i] = [];
|
||||
var trackChunk = readChunk(stream);
|
||||
if (trackChunk.id != 'MTrk') {
|
||||
throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id;
|
||||
}
|
||||
var trackStream = Stream(trackChunk.data);
|
||||
while (!trackStream.eof()) {
|
||||
var event = readEvent(trackStream);
|
||||
tracks[i].push(event);
|
||||
//console.log(event);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'header': header,
|
||||
'tracks': tracks
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
var clone = function (o) {
|
||||
if (typeof o != 'object') return (o);
|
||||
if (o == null) return (o);
|
||||
var ret = (typeof o.length == 'number') ? [] : {};
|
||||
for (var key in o) ret[key] = clone(o[key]);
|
||||
return ret;
|
||||
};
|
||||
|
||||
function Replayer(midiFile, timeWarp, eventProcessor) {
|
||||
var trackStates = [];
|
||||
var beatsPerMinute = 120;
|
||||
var ticksPerBeat = midiFile.header.ticksPerBeat;
|
||||
for (var i = 0; i < midiFile.tracks.length; i++) {
|
||||
trackStates[i] = {
|
||||
"nextEventIndex": 0,
|
||||
"ticksToNextEvent": (
|
||||
midiFile.tracks[i].length ? midiFile.tracks[i][0].deltaTime : null
|
||||
)
|
||||
};
|
||||
}
|
||||
function getNextEvent() {
|
||||
var ticksToNextEvent = null;
|
||||
var nextEventTrack = null;
|
||||
var nextEventIndex = null;
|
||||
for (var i = 0; i < trackStates.length; i++) {
|
||||
if (trackStates[i].ticksToNextEvent != null && (ticksToNextEvent == null || trackStates[i].ticksToNextEvent < ticksToNextEvent)) {
|
||||
ticksToNextEvent = trackStates[i].ticksToNextEvent;
|
||||
nextEventTrack = i;
|
||||
nextEventIndex = trackStates[i].nextEventIndex;
|
||||
}
|
||||
}
|
||||
if (nextEventTrack != null) {
|
||||
/// consume event from that track
|
||||
var nextEvent = midiFile.tracks[nextEventTrack][nextEventIndex];
|
||||
if (midiFile.tracks[nextEventTrack][nextEventIndex + 1]) {
|
||||
trackStates[nextEventTrack].ticksToNextEvent += midiFile.tracks[nextEventTrack][nextEventIndex + 1].deltaTime;
|
||||
} else {
|
||||
trackStates[nextEventTrack].ticksToNextEvent = null;
|
||||
}
|
||||
trackStates[nextEventTrack].nextEventIndex += 1;
|
||||
/// advance timings on all tracks by ticksToNextEvent
|
||||
for (var i = 0; i < trackStates.length; i++) {
|
||||
if (trackStates[i].ticksToNextEvent != null) {
|
||||
trackStates[i].ticksToNextEvent -= ticksToNextEvent
|
||||
}
|
||||
}
|
||||
return {
|
||||
"ticksToEvent": ticksToNextEvent,
|
||||
"event": nextEvent,
|
||||
"track": nextEventTrack
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
//
|
||||
var midiEvent;
|
||||
var temporal = [];
|
||||
//
|
||||
function processEvents() {
|
||||
function processNext() {
|
||||
if (midiEvent.ticksToEvent > 0) {
|
||||
var beatsToGenerate = midiEvent.ticksToEvent / ticksPerBeat;
|
||||
var secondsToGenerate = beatsToGenerate / (beatsPerMinute / 60);
|
||||
}
|
||||
var time = (secondsToGenerate * 1000 * timeWarp) || 0;
|
||||
temporal.push([ midiEvent, time]);
|
||||
midiEvent = getNextEvent();
|
||||
};
|
||||
//
|
||||
if (midiEvent = getNextEvent()) {
|
||||
while(midiEvent) processNext(true);
|
||||
}
|
||||
};
|
||||
processEvents();
|
||||
return {
|
||||
"getData": function() {
|
||||
return clone(temporal);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
/* Wrapper for accessing strings through sequential reads */
|
||||
function Stream(str) {
|
||||
var position = 0;
|
||||
|
||||
function read(length) {
|
||||
var result = str.substr(position, length);
|
||||
position += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read a big-endian 32-bit integer */
|
||||
function readInt32() {
|
||||
var result = (
|
||||
(str.charCodeAt(position) << 24)
|
||||
+ (str.charCodeAt(position + 1) << 16)
|
||||
+ (str.charCodeAt(position + 2) << 8)
|
||||
+ str.charCodeAt(position + 3));
|
||||
position += 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read a big-endian 16-bit integer */
|
||||
function readInt16() {
|
||||
var result = (
|
||||
(str.charCodeAt(position) << 8)
|
||||
+ str.charCodeAt(position + 1));
|
||||
position += 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read an 8-bit integer */
|
||||
function readInt8() {
|
||||
var result = str.charCodeAt(position);
|
||||
position += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
function eof() {
|
||||
return position >= str.length;
|
||||
}
|
||||
|
||||
/* read a MIDI-style variable-length integer
|
||||
(big-endian value in groups of 7 bits,
|
||||
with top bit set to signify that another byte follows)
|
||||
*/
|
||||
function readVarInt() {
|
||||
var result = 0;
|
||||
while (true) {
|
||||
var b = readInt8();
|
||||
if (b & 0x80) {
|
||||
result += (b & 0x7f);
|
||||
result <<= 7;
|
||||
} else {
|
||||
/* b is the last byte */
|
||||
return result + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'eof': eof,
|
||||
'read': read,
|
||||
'readInt32': readInt32,
|
||||
'readInt16': readInt16,
|
||||
'readInt8': readInt8,
|
||||
'readVarInt': readVarInt
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue