Compare commits

...

8 Commits

Author SHA1 Message Date
ed
32f9c6b5bb v0.11.16 2021-06-16 01:51:18 +02:00
ed
6251584ef6 fix .13dB clipping with all-zero eq 2021-06-15 23:37:44 +00:00
ed
f3e413bc28 icons 2021-06-16 00:01:07 +02:00
ed
6f6cc8f3f8 move eq to the player settings tab 2021-06-15 22:26:39 +02:00
ed
8b081e9e69 media player: continue to next folder 2021-06-15 22:19:53 +02:00
ed
c8a510d10e fully hide columns when minimized 2021-06-15 21:43:37 +02:00
ed
6f834f6679 sticky tree header 2021-06-15 21:07:27 +02:00
ed
cf2d6650ac audio-eq: flatten frequency response 2021-06-15 21:06:00 +02:00
7 changed files with 341 additions and 104 deletions

View File

@@ -1,8 +1,8 @@
# coding: utf-8 # coding: utf-8
VERSION = (0, 11, 15) VERSION = (0, 11, 16)
CODENAME = "the grid" CODENAME = "the grid"
BUILD_DT = (2021, 6, 15) BUILD_DT = (2021, 6, 16)
S_VERSION = ".".join(map(str, VERSION)) S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT) S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -584,6 +584,7 @@ input.eq_gain {
} }
#wrap { #wrap {
margin-top: 2em; margin-top: 2em;
min-height: 90vh;
} }
#tree { #tree {
display: none; display: none;
@@ -596,6 +597,12 @@ input.eq_gain {
overscroll-behavior-y: none; overscroll-behavior-y: none;
scrollbar-color: #eb0 #333; scrollbar-color: #eb0 #333;
} }
#treeh {
background: #333;
position: sticky;
z-index: 1;
top: 0;
}
#thx_ff { #thx_ff {
padding: 5em 0; padding: 5em 0;
} }
@@ -621,6 +628,7 @@ input.eq_gain {
box-shadow: 0 .1em .2em #222 inset; box-shadow: 0 .1em .2em #222 inset;
border-radius: .3em; border-radius: .3em;
margin: .2em; margin: .2em;
white-space: pre;
position: relative; position: relative;
top: -.2em; top: -.2em;
} }
@@ -688,34 +696,20 @@ input.eq_gain {
font-size: 2em; font-size: 2em;
white-space: nowrap; white-space: nowrap;
} }
#files th:hover .cfg, #files th:hover .cfg {
#files th.min .cfg {
display: block; display: block;
width: 1em; width: 1em;
border-radius: .2em; border-radius: .2em;
margin: -1.3em auto 0 auto; margin: -1.3em auto 0 auto;
background: #444; background: #444;
} }
#files th.min .cfg { #files>thead>tr>th.min,
margin: -.6em; #files td.min {
} display: none;
#files>thead>tr>th.min span {
position: absolute;
transform: rotate(270deg);
background: linear-gradient(90deg, rgba(68,68,68,0), rgba(68,68,68,0.5) 70%, #444);
margin-left: -4.6em;
padding: .4em;
top: 5.4em;
width: 8em;
text-align: right;
letter-spacing: .04em;
} }
#files td:nth-child(2n) { #files td:nth-child(2n) {
color: #f5a; color: #f5a;
} }
#files td.min a {
display: none;
}
#files tr.play td, #files tr.play td,
#files tr.play div a { #files tr.play div a {
background: #fc4; background: #fc4;
@@ -730,18 +724,18 @@ input.eq_gain {
color: #300; color: #300;
background: #fea; background: #fea;
} }
#op_cfg { .opwide {
max-width: none; max-width: none;
margin-right: 1.5em; margin-right: 1.5em;
} }
#op_cfg>div>a { .opwide>div>a {
line-height: 2em; line-height: 2em;
} }
#op_cfg>div>span { #op_cfg>div>span {
display: inline-block; display: inline-block;
padding: .2em .4em; padding: .2em .4em;
} }
#op_cfg h3 { .opbox h3 {
margin: .8em 0 0 .6em; margin: .8em 0 0 .6em;
padding: 0; padding: 0;
border-bottom: 1px solid #555; border-bottom: 1px solid #555;
@@ -965,13 +959,9 @@ html.light tr.play td {
html.light tr.play a { html.light tr.play a {
color: #406; color: #406;
} }
html.light #files th:hover .cfg, html.light #files th:hover .cfg {
html.light #files th.min .cfg {
background: #ccc; background: #ccc;
} }
html.light #files > thead > tr > th.min span {
background: linear-gradient(90deg, rgba(204,204,204,0), rgba(204,204,204,0.5) 70%, #ccc);
}
html.light #blocked { html.light #blocked {
background: #eee; background: #eee;
} }
@@ -1042,6 +1032,9 @@ html.light #files tr.sel a:hover {
color: #000; color: #000;
background: #fff; background: #fff;
} }
html.light #treeh {
background: #eee;
}
html.light #tree { html.light #tree {
scrollbar-color: #a70 #ddd; scrollbar-color: #a70 #ddd;
} }

View File

@@ -26,6 +26,7 @@
<a href="#" data-perm="write" data-dest="mkdir" data-desc="mkdir: create a new directory">📂</a> <a href="#" data-perm="write" data-dest="mkdir" data-desc="mkdir: create a new directory">📂</a>
<a href="#" data-perm="read write" data-dest="new_md" data-desc="new-md: create a new markdown document">📝</a> <a href="#" data-perm="read write" data-dest="new_md" data-desc="new-md: create a new markdown document">📝</a>
<a href="#" data-perm="write" data-dest="msg" data-desc="msg: send a message to the server log">📟</a> <a href="#" data-perm="write" data-dest="msg" data-desc="msg: send a message to the server log">📟</a>
<a href="#" data-dest="player" data-desc="media player options">🎺</a>
<a href="#" data-dest="cfg" data-desc="configuration options">⚙️</a> <a href="#" data-dest="cfg" data-desc="configuration options">⚙️</a>
<div id="opdesc"></div> <div id="opdesc"></div>
</div> </div>
@@ -39,24 +40,23 @@
<div id="srch_q"></div> <div id="srch_q"></div>
</div> </div>
<div id="op_player" class="opview opbox opwide"></div>
{%- include 'upload.html' %} {%- include 'upload.html' %}
<div id="op_cfg" class="opview opbox"> <div id="op_cfg" class="opview opbox opwide">
<h3>switches</h3> <h3>switches</h3>
<div> <div>
<a id="tooltips" class="tgl btn" href="#">tooltips</a> <a id="tooltips" class="tgl btn" href="#"> tooltips</a>
<a id="lightmode" class="tgl btn" href="#">lightmode</a> <a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>
<a id="griden" class="tgl btn" href="#">the grid</a> <a id="griden" class="tgl btn" href="#">the grid</a>
<a id="thumbs" class="tgl btn" href="#">thumbs</a> <a id="thumbs" class="tgl btn" href="#">🖼️ thumbs</a>
</div> </div>
{%- if have_zip %} {%- if have_zip %}
<h3>folder download</h3> <h3>folder download</h3><div id="arc_fmt"></div>
<div id="arc_fmt"></div>
{%- endif %} {%- endif %}
<h3>key notation</h3> <h3>key notation</h3><div id="key_notation"></div>
<div id="key_notation"></div> <h3>hidden columns</h3><div id="hcols"></div>
<h3>audio equalizer</h3>
<div id="audio_eq"></div>
</div> </div>
<h1 id="path"> <h1 id="path">
@@ -67,10 +67,12 @@
</h1> </h1>
<div id="tree"> <div id="tree">
<a href="#" id="detree">🍞...</a> <div id="treeh">
<a href="#" class="btn" step="2" id="twobytwo">+</a> <a href="#" id="detree">🍞...</a>
<a href="#" class="btn" step="-2" id="twig">&ndash;</a> <a href="#" class="btn" step="2" id="twobytwo">+</a>
<a href="#" class="tgl btn" id="dyntree">a</a> <a href="#" class="btn" step="-2" id="twig">&ndash;</a>
<a href="#" class="tgl btn" id="dyntree">a</a>
</div>
<ul id="treeul"></ul> <ul id="treeul"></ul>
<div id="thx_ff">&nbsp;</div> <div id="thx_ff">&nbsp;</div>
</div> </div>

View File

@@ -42,6 +42,39 @@ var have_webp = null;
})(); })();
var mpl = (function () {
ebi('op_player').innerHTML = (
'<h3>audio equalizer</h3><div id="audio_eq"></div>' +
'<h3>playback mode</h3><div id="pb_mode">' +
'<a href="#" class="tgl btn">🔁 loop-folder</a>' +
'<a href="#" class="tgl btn">📂 next-folder</a>' +
'</div>');
var r = {
"pb_mode": sread('pb_mode') || 'loop-folder'
};
function draw_pb_mode() {
var btns = QSA('#pb_mode>a');
for (var a = 0, aa = btns.length; a < aa; a++) {
clmod(btns[a], 'on', btns[a].textContent.indexOf(r.pb_mode) != -1);
btns[a].onclick = set_pb_mode;
}
}
draw_pb_mode();
function set_pb_mode(e) {
ev(e);
r.pb_mode = this.textContent.split(' ').slice(-1)[0];
swrite('pb_mode', r.pb_mode);
draw_pb_mode();
}
return r;
})();
// extract songs + add play column // extract songs + add play column
function MPlayer() { function MPlayer() {
this.id = Date.now(); this.id = Date.now();
@@ -162,8 +195,9 @@ var widget = (function () {
m = ck + 'np: '; m = ck + 'np: ';
for (var a = 1, aa = th.length; a < aa; a++) { for (var a = 1, aa = th.length; a < aa; a++) {
var tk = a == 1 ? '' : th[a].getAttribute('name').split('/').slice(-1)[0]; var tv = tr[a].textContent,
var tv = tr[a].getAttribute('html') || tr[a].textContent; tk = a == 1 ? '' : th[a].getAttribute('name').split('/').slice(-1)[0];
m += tk + '(' + cv + tv + ck + ') // '; m += tk + '(' + cv + tv + ck + ') // ';
} }
@@ -407,7 +441,7 @@ function song_skip(n) {
if (tid !== null) if (tid !== null)
play(mp.order.indexOf(tid) + n); play(mp.order.indexOf(tid) + n);
else else
play(mp.order[0]); play(mp.order[n == -1 ? mp.order.length - 1 : 0]);
} }
@@ -512,26 +546,35 @@ var audio_eq = (function () {
var r = { var r = {
"en": false, "en": false,
"bands": [31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000], "bands": [31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
"gains": [0, -1, -2, -3, -4, -4, -3, -2, -1, 0], "gains": [4, 3, 2, 1, 0, 0, 1, 2, 3, 4],
"filters": [], "filters": [],
"last_au": null "last_au": null
}; };
var cfg = [ // hz, q, g
[31.25 * 0.88, 0, 1.4], // shelf
[31.25 * 1.04, 0.7, 0.96], // peak
[62.5, 0.7, 1],
[125, 0.8, 1],
[250, 0.9, 1.03],
[500, 0.9, 1.1],
[1000, 0.9, 1.1],
[2000, 0.9, 1.105],
[4000, 0.88, 1.05],
[8000 * 1.006, 0.73, 1.24],
[16000 * 0.89, 0.7, 1.26], // peak
[16000 * 1.13, 0.82, 1.09], // peak
[16000 * 1.205, 0, 1.9] // shelf
];
try { try {
r.gains = jread('au_eq_gain', r.gains); var gains = jread('au_eq_gain', r.gains);
if (r.gains.length == gains.length)
r.gains = gains;
} }
catch (ex) { } catch (ex) { }
r.draw = function () { r.draw = function () {
var max = 0;
for (var a = 0; a < r.gains.length; a++)
if (max < r.gains[a])
max = r.gains[a];
if (max > 0)
for (var a = 0; a < r.gains.length; a++)
r.gains[a] -= max;
jwrite('au_eq_gain', r.gains); jwrite('au_eq_gain', r.gains);
var txt = QSA('input.eq_gain'); var txt = QSA('input.eq_gain');
@@ -568,24 +611,43 @@ var audio_eq = (function () {
mp.acs = mp.ac.createMediaElementSource(mp.au); mp.acs = mp.ac.createMediaElementSource(mp.au);
} }
r.filters = [];
if (!r.en) { if (!r.en) {
mp.acs.connect(mp.ac.destination); mp.acs.connect(mp.ac.destination);
return; return;
} }
r.filters = []; var max = 0;
for (var a = 0; a < r.bands.length; a++) { for (var a = 0; a < r.gains.length; a++)
if (max < r.gains[a])
max = r.gains[a];
var gains = []
for (var a = 0; a < r.gains.length; a++)
gains.push(r.gains[a] - max);
var t = gains[gains.length - 1];
gains.push(t);
gains.push(t);
gains.unshift(gains[0]);
for (var a = 0; a < cfg.length; a++) {
var fi = mp.ac.createBiquadFilter(); var fi = mp.ac.createBiquadFilter();
fi.frequency.value = r.bands[a]; fi.frequency.value = cfg[a][0];
fi.gain.value = r.gains[a]; fi.gain.value = cfg[a][2] * gains[a];
fi.Q.value = a == 0 ? 0 : 1; fi.Q.value = cfg[a][1];
fi.type = a == 0 ? 'lowshelf' : a == r.bands.length - 1 ? 'highshelf' : 'peaking'; fi.type = a == 0 ? 'lowshelf' : a == cfg.length - 1 ? 'highshelf' : 'peaking';
r.filters.push(fi); r.filters.push(fi);
} }
for (var a = r.bands.length - 1; a >= 0; a--) { for (var a = r.filters.length - 1; a >= 0; a--) {
r.filters[a].connect(a > 0 ? r.filters[a - 1] : mp.ac.destination); r.filters[a].connect(a > 0 ? r.filters[a - 1] : mp.ac.destination);
} }
mp.acs.connect(r.filters[r.filters.length - 1]); fi = mp.ac.createGain();
fi.gain.value = '0.94'; // +.137 dB measured; now -.25 dB and almost bitperfect
mp.acs.connect(fi);
fi.connect(r.filters[r.filters.length - 1]);
r.filters.push(fi);
} }
function eq_step(e) { function eq_step(e) {
@@ -639,8 +701,7 @@ var audio_eq = (function () {
h4.push('<td><a href="#" class="eq_step" step="-0.5" band="' + a + '">&ndash;</a></td>'); h4.push('<td><a href="#" class="eq_step" step="-0.5" band="' + a + '">&ndash;</a></td>');
h3.push('<td><input type="text" class="eq_gain" band="' + a + '" value="' + r.gains[a] + '" /></td>'); h3.push('<td><input type="text" class="eq_gain" band="' + a + '" value="' + r.gains[a] + '" /></td>');
} }
html.push('</tr><tr>'); html = html.join('\n') + '</tr><tr>';
html = html.join('\n');
html += h2.join('\n') + '</tr><tr>'; html += h2.join('\n') + '</tr><tr>';
html += h3.join('\n') + '</tr><tr>'; html += h3.join('\n') + '</tr><tr>';
html += h4.join('\n') + '</tr><table>'; html += h4.join('\n') + '</tr><table>';
@@ -678,11 +739,25 @@ function play(tid, seek, call_depth) {
if ((tn + '').indexOf('f-') === 0) if ((tn + '').indexOf('f-') === 0)
tn = mp.order.indexOf(tn); tn = mp.order.indexOf(tn);
while (tn >= mp.order.length) if (tn >= mp.order.length) {
tn -= mp.order.length; if (mpl.pb_mode == 'loop-folder') {
tn = 0;
}
else if (mpl.pb_mode == 'next-folder') {
treectl.ls_cb = function () { song_skip(1); };
return tree_neigh(1);
}
}
while (tn < 0) if (tn < 0) {
tn += mp.order.length; if (mpl.pb_mode == 'loop-folder') {
tn = mp.order.length - 1;
}
else if (mpl.pb_mode == 'next-folder') {
treectl.ls_cb = function () { song_skip(-1); };
return tree_neigh(-1);
}
}
tid = mp.order[tn]; tid = mp.order[tn];
@@ -1439,7 +1514,8 @@ document.onkeydown = function (e) {
var treectl = (function () { var treectl = (function () {
var treectl = { var treectl = {
"hidden": false "hidden": false,
"ls_cb": null
}, },
entreed = false, entreed = false,
fixedpos = false, fixedpos = false,
@@ -1539,6 +1615,11 @@ var treectl = (function () {
onscroll(); onscroll();
} }
treectl.goto = function (url, push) {
get_tree("", url, true);
reqls(url, push);
}
function get_tree(top, dst, rst) { function get_tree(top, dst, rst) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.top = top; xhr.top = top;
@@ -1733,6 +1814,12 @@ var treectl = (function () {
msel.render(); msel.render();
reload_tree(); reload_tree();
reload_browser(); reload_browser();
var fun = treectl.ls_cb;
if (fun) {
treectl.ls_cb = null;
fun();
}
} }
function parsetree(res, top) { function parsetree(res, top) {
@@ -1797,9 +1884,7 @@ var treectl = (function () {
return; return;
var url = new URL(e.state, "https://" + document.location.host); var url = new URL(e.state, "https://" + document.location.host);
url = url.pathname; treectl.goto(url.pathname);
get_tree("", url, true);
reqls(url);
}; };
if (window.history && history.pushState) { if (window.history && history.pushState) {
@@ -1924,17 +2009,34 @@ var filecols = (function () {
var add_btns = function () { var add_btns = function () {
var ths = QSA('#files th>span'); var ths = QSA('#files th>span');
for (var a = 0, aa = ths.length; a < aa; a++) { for (var a = 0, aa = ths.length; a < aa; a++) {
var th = ths[a].parentElement, var th = ths[a].parentElement;
is_hidden = has(hidden, ths[a].textContent); th.innerHTML = '<div class="cfg"><a href="#">-</a></div>' + ths[a].outerHTML;
th.innerHTML = '<div class="cfg"><a href="#">' +
(is_hidden ? '+' : '-') + '</a></div>' + ths[a].outerHTML;
th.getElementsByTagName('a')[0].onclick = ev_row_tgl; th.getElementsByTagName('a')[0].onclick = ev_row_tgl;
} }
}; };
function hcols_click(e) {
ev(e);
var t = e.target;
if (t.tagName != 'A')
return;
toggle(t.textContent);
}
var set_style = function () { var set_style = function () {
hidden.sort();
var html = [],
hcols = ebi('hcols');
for (var a = 0; a < hidden.length; a++) {
html.push('<a href="#" class="btn">' + esc(hidden[a]) + '</a>');
}
hcols.previousSibling.style.display = html.length ? 'block' : 'none';
hcols.innerHTML = html.join('\n');
hcols.onclick = hcols_click;
add_btns(); add_btns();
var ohidden = [], var ohidden = [],
@@ -1959,22 +2061,8 @@ var filecols = (function () {
var cls = has(ohidden, a) ? 'min' : '', var cls = has(ohidden, a) ? 'min' : '',
tds = QSA('#files>tbody>tr>td:nth-child(' + (a + 1) + ')'); tds = QSA('#files>tbody>tr>td:nth-child(' + (a + 1) + ')');
for (var b = 0, bb = tds.length; b < bb; b++) { for (var b = 0, bb = tds.length; b < bb; b++)
tds[b].setAttribute('class', cls); tds[b].setAttribute('class', cls);
if (a < 2)
continue;
if (cls) {
if (!tds[b].hasAttribute('html')) {
tds[b].setAttribute('html', tds[b].innerHTML);
tds[b].innerHTML = '...';
}
}
else if (tds[b].hasAttribute('html')) {
tds[b].innerHTML = tds[b].getAttribute('html');
tds[b].removeAttribute('html');
}
}
} }
}; };
set_style(); set_style();
@@ -1993,15 +2081,13 @@ var filecols = (function () {
try { try {
var ci = find_file_col('dur'), var ci = find_file_col('dur'),
i = ci[0], i = ci[0],
min = ci[1],
rows = ebi('files').tBodies[0].rows; rows = ebi('files').tBodies[0].rows;
if (!min) for (var a = 0, aa = rows.length; a < aa; a++) {
for (var a = 0, aa = rows.length; a < aa; a++) { var c = rows[a].cells[i];
var c = rows[a].cells[i]; if (c && c.textContent)
if (c && c.textContent) c.textContent = s2ms(c.textContent);
c.textContent = s2ms(c.textContent); }
}
} }
catch (ex) { } catch (ex) { }

View File

@@ -0,0 +1,61 @@
var ofun = audio_eq.apply.bind(audio_eq);
audio_eq.apply = function () {
var ac1 = mp.ac;
ofun();
var ac = mp.ac,
w = 2048,
h = 256;
if (!audio_eq.filters.length) {
audio_eq.ana = null;
return;
}
var can = ebi('fft_can');
if (!can) {
can = mknod('canvas');
can.setAttribute('id', 'fft_can');
can.style.cssText = 'position:absolute;left:0;bottom:5em;width:' + w + 'px;height:' + h + 'px;z-index:9001';
document.body.appendChild(can);
can.width = w;
can.height = h;
}
var cc = can.getContext('2d');
if (!ac)
return;
var ana = ac.createAnalyser();
ana.smoothingTimeConstant = 0;
ana.fftSize = 8192;
audio_eq.filters[0].connect(ana);
audio_eq.ana = ana;
var buf = new Uint8Array(ana.frequencyBinCount),
colw = can.width / buf.length;
cc.fillStyle = '#fc0';
function draw() {
if (ana == audio_eq.ana)
requestAnimationFrame(draw);
ana.getByteFrequencyData(buf);
cc.clearRect(0, 0, can.width, can.height);
/*var x = 0, w = 1;
for (var a = 0; a < buf.length; a++) {
cc.fillRect(x, h - buf[a], w, h);
x += w;
}*/
var mul = Math.pow(w, 4) / buf.length;
for (var x = 0; x < w; x++) {
var a = Math.floor(Math.pow(x, 4) / mul),
v = buf[a];
cc.fillRect(x, h - v, 1, v);
}
}
draw();
};
audio_eq.apply();

95
docs/biquad.html Normal file
View File

@@ -0,0 +1,95 @@
<!DOCTYPE html><html><head></head><body><script>
setTimeout(location.reload.bind(location), 700);
document.documentElement.scrollLeft = 0;
var can = document.createElement('canvas'),
cc = can.getContext('2d'),
w = 2048,
h = 1024;
w = 2048;
can.width = w;
can.height = h;
document.body.appendChild(can);
can.style.cssText = 'width:' + w + 'px;height:' + h + 'px';
cc.fillStyle = '#000';
cc.fillRect(0, 0, w, h);
var cfg = [ // hz, q, g
[31.25 * 0.88, 0, 1.4], // shelf
[31.25 * 1.04, 0.7, 0.96], // peak
[62.5, 0.7, 1],
[125, 0.8, 1],
[250, 0.9, 1.03],
[500, 0.9, 1.1],
[1000, 0.9, 1.1],
[2000, 0.9, 1.105],
[4000, 0.88, 1.05],
[8000 * 1.006, 0.73, 1.24],
//[16000 * 1.00, 0.5, 1.75], // peak.v1
//[16000 * 1.19, 0, 1.8] // shelf.v1
[16000 * 0.89, 0.7, 1.26], // peak
[16000 * 1.13, 0.82, 1.09], // peak
[16000 * 1.205, 0, 1.9] // shelf
];
var freqs = new Float32Array(22000),
sum = new Float32Array(freqs.length),
ac = new AudioContext(),
step = w / freqs.length,
colors = [
'rgba(255, 0, 0, 0.7)',
'rgba(0, 224, 0, 0.7)',
'rgba(0, 64, 255, 0.7)'
];
var order = [];
for (var a = 0; a < cfg.length; a += 2)
order.push(a);
for (var a = 1; a < cfg.length; a += 2)
order.push(a);
for (var ia = 0; ia < order.length; ia++) {
var a = order[ia],
fi = ac.createBiquadFilter(),
mag = new Float32Array(freqs.length),
phase = new Float32Array(freqs.length);
for (var b = 0; b < freqs.length; b++)
freqs[b] = b;
fi.type = a == 0 ? 'lowshelf' : a == cfg.length - 1 ? 'highshelf' : 'peaking';
fi.frequency.value = cfg[a][0];
fi.Q.value = cfg[a][1];
fi.gain.value = 1;
fi.getFrequencyResponse(freqs, mag, phase);
cc.fillStyle = colors[a % colors.length];
for (var b = 0; b < sum.length; b++) {
mag[b] -= 1;
sum[b] += mag[b] * cfg[a][2];
var y = h - (mag[b] * h * 3);
cc.fillRect(b * step, y, step, h - y);
cc.fillRect(b * step - 1, y - 1, 3, 3);
}
}
var min = 999999, max = 0;
for (var a = 0; a < sum.length; a++) {
min = Math.min(min, sum[a]);
max = Math.max(max, sum[a]);
}
cc.fillStyle = 'rgba(255,255,255,1)';
for (var a = 0; a < sum.length; a++) {
var v = (sum[a] - min) / (max - min);
cc.fillRect(a * step, 0, step, v * h / 2);
}
cc.fillRect(0, 460, w, 1);
</script></body></html>

View File

@@ -167,7 +167,7 @@ find .. -type f \( -name .DS_Store -or -name ._.DS_Store \) -delete
find .. -type f -name ._\* | while IFS= read -r f; do cmp <(printf '\x00\x05\x16') <(head -c 3 -- "$f") && rm -f -- "$f"; done find .. -type f -name ._\* | while IFS= read -r f; do cmp <(printf '\x00\x05\x16') <(head -c 3 -- "$f") && rm -f -- "$f"; done
echo use smol web deps echo use smol web deps
rm -f copyparty/web/deps/*.full.* copyparty/web/Makefile rm -f copyparty/web/deps/*.full.* copyparty/web/dbg-* copyparty/web/Makefile
# it's fine dw # it's fine dw
grep -lE '\.full\.(js|css)' copyparty/web/* | grep -lE '\.full\.(js|css)' copyparty/web/* |