mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 00:52:16 -06:00
add clientside DRC / dynamic range compressor
This commit is contained in:
parent
e1d78d8b23
commit
a4bad62b60
|
@ -1414,14 +1414,17 @@ html.dz input {
|
||||||
.opview input.i {
|
.opview input.i {
|
||||||
width: calc(100% - 16.2em);
|
width: calc(100% - 16.2em);
|
||||||
}
|
}
|
||||||
|
input.drc_v,
|
||||||
input.eq_gain {
|
input.eq_gain {
|
||||||
width: 3em;
|
width: 3em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0 .6em;
|
margin: 0 .6em;
|
||||||
}
|
}
|
||||||
|
#audio_drc table,
|
||||||
#audio_eq table {
|
#audio_eq table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
#audio_drc td,
|
||||||
#audio_eq td {
|
#audio_eq td {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -1430,11 +1433,15 @@ input.eq_gain {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
#au_drc,
|
||||||
#au_eq {
|
#au_eq {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: .5em;
|
margin-top: .5em;
|
||||||
padding: 1.3em .3em;
|
padding: 1.3em .3em;
|
||||||
}
|
}
|
||||||
|
#au_drc {
|
||||||
|
padding: .4em .3em;
|
||||||
|
}
|
||||||
#ico1 {
|
#ico1 {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,6 +233,7 @@ var Ls = {
|
||||||
"ml_tcode": "transcode",
|
"ml_tcode": "transcode",
|
||||||
"ml_tint": "tint",
|
"ml_tint": "tint",
|
||||||
"ml_eq": "audio equalizer",
|
"ml_eq": "audio equalizer",
|
||||||
|
"ml_drc": "dynamic range compressor",
|
||||||
|
|
||||||
"mt_preload": "start loading the next song near the end for gapless playback\">preload",
|
"mt_preload": "start loading the next song near the end for gapless playback\">preload",
|
||||||
"mt_fullpre": "try to preload the entire song;$N✅ enable on <b>unreliable</b> connections,$N❌ <b>disable</b> on slow connections probably\">full",
|
"mt_fullpre": "try to preload the entire song;$N✅ enable on <b>unreliable</b> connections,$N❌ <b>disable</b> on slow connections probably\">full",
|
||||||
|
@ -250,6 +251,7 @@ var Ls = {
|
||||||
"mt_coth": "convert all others (not mp3) to opus\">oth",
|
"mt_coth": "convert all others (not mp3) to opus\">oth",
|
||||||
"mt_tint": "background level (0-100) on the seekbar$Nto make buffering less distracting",
|
"mt_tint": "background level (0-100) on the seekbar$Nto make buffering less distracting",
|
||||||
"mt_eq": "enables the equalizer and gain control;$N$Nboost <code>0</code> = standard 100% volume (unmodified)$N$Nwidth <code>1 </code> = standard stereo (unmodified)$Nwidth <code>0.5</code> = 50% left-right crossfeed$Nwidth <code>0 </code> = mono$N$Nboost <code>-0.8</code> & width <code>10</code> = vocal removal :^)$N$Nenabling the equalizer makes gapless albums fully gapless, so leave it on with all the values at zero (except width = 1) if you care about that",
|
"mt_eq": "enables the equalizer and gain control;$N$Nboost <code>0</code> = standard 100% volume (unmodified)$N$Nwidth <code>1 </code> = standard stereo (unmodified)$Nwidth <code>0.5</code> = 50% left-right crossfeed$Nwidth <code>0 </code> = mono$N$Nboost <code>-0.8</code> & width <code>10</code> = vocal removal :^)$N$Nenabling the equalizer makes gapless albums fully gapless, so leave it on with all the values at zero (except width = 1) if you care about that",
|
||||||
|
"mt_drc": "enables the dynamic range compressor (volume flattener / brickwaller); will also enable EQ to balance the spaghetti, so set all EQ fields except for 'width' to 0 if you don't want it$N$Nlowers the volume of audio above THRESHOLD dB; for every RATIO dB past THRESHOLD there is 1 dB of output, so default values of tresh -24 and ratio 12 means it should never get louder than -22 dB and it is safe to increase the equalizer boost to 0.8, or even 1.8 with ATK 0 and a huge RLS like 90$N$Nplease see wikipedia instead, this is probably wrong",
|
||||||
|
|
||||||
"mb_play": "play",
|
"mb_play": "play",
|
||||||
"mm_hashplay": "play this audio file?",
|
"mm_hashplay": "play this audio file?",
|
||||||
|
@ -710,6 +712,7 @@ var Ls = {
|
||||||
"ml_tcode": "konvertering",
|
"ml_tcode": "konvertering",
|
||||||
"ml_tint": "tint",
|
"ml_tint": "tint",
|
||||||
"ml_eq": "audio equalizer (tonejustering)",
|
"ml_eq": "audio equalizer (tonejustering)",
|
||||||
|
"ml_drc": "compressor (volum-utjevning)",
|
||||||
|
|
||||||
"mt_preload": "hent ned litt av neste sang i forkant,$Nslik at pausen i overgangen blir mindre\">forles",
|
"mt_preload": "hent ned litt av neste sang i forkant,$Nslik at pausen i overgangen blir mindre\">forles",
|
||||||
"mt_fullpre": "hent ned hele neste sang, ikke bare litt:$N✅ skru på hvis nettet ditt er <b>ustabilt</b>,$N❌ skru av hvis nettet ditt er <b>tregt</b>\">full",
|
"mt_fullpre": "hent ned hele neste sang, ikke bare litt:$N✅ skru på hvis nettet ditt er <b>ustabilt</b>,$N❌ skru av hvis nettet ditt er <b>tregt</b>\">full",
|
||||||
|
@ -727,6 +730,7 @@ var Ls = {
|
||||||
"mt_coth": "konverter alt annet (men ikke mp3) til opus\">andre",
|
"mt_coth": "konverter alt annet (men ikke mp3) til opus\">andre",
|
||||||
"mt_tint": "nivå av bakgrunnsfarge på søkestripa (0-100),$Ngjør oppdateringer mindre distraherende",
|
"mt_tint": "nivå av bakgrunnsfarge på søkestripa (0-100),$Ngjør oppdateringer mindre distraherende",
|
||||||
"mt_eq": "aktiver tonekontroll og forsterker;$N$Nboost <code>0</code> = normal volumskala$N$Nwidth <code>1 </code> = normal stereo$Nwidth <code>0.5</code> = 50% blanding venstre-høyre$Nwidth <code>0 </code> = mono$N$Nboost <code>-0.8</code> & width <code>10</code> = instrumental :^)$N$Nreduserer også dødtid imellom sangfiler",
|
"mt_eq": "aktiver tonekontroll og forsterker;$N$Nboost <code>0</code> = normal volumskala$N$Nwidth <code>1 </code> = normal stereo$Nwidth <code>0.5</code> = 50% blanding venstre-høyre$Nwidth <code>0 </code> = mono$N$Nboost <code>-0.8</code> & width <code>10</code> = instrumental :^)$N$Nreduserer også dødtid imellom sangfiler",
|
||||||
|
"mt_drc": "aktiver volum-utjevning (dynamic range compressor); vil også aktivere tonejustering, så sett alle EQ-feltene bortsett fra 'width' til 0 hvis du ikke vil ha noe EQ$N$Nfilteret vil dempe volumet på alt som er høyere enn TRESH dB; for hver RATIO dB over grensen er det 1dB som treffer høyttalerne, så standardverdiene tresh -24 og ratio 12 skal bety at volumet ikke går høyere enn -22 dB, slik at man trygt kan øke boost-verdien i equalizer'n til rundt 0.8, eller 1.8 kombinert med ATK 0 og RLS 90$N$Ngodt mulig jeg har misforstått litt, så wikipedia forklarer nok bedre",
|
||||||
|
|
||||||
"mb_play": "lytt",
|
"mb_play": "lytt",
|
||||||
"mm_hashplay": "spill denne sangen?",
|
"mm_hashplay": "spill denne sangen?",
|
||||||
|
@ -1386,7 +1390,9 @@ var mpl = (function () {
|
||||||
'<input type="text" id="pb_tint" value="0" ' + NOAC + ' style="width:2.4em" tt="' + L.mt_tint + '" />' +
|
'<input type="text" id="pb_tint" value="0" ' + NOAC + ' style="width:2.4em" tt="' + L.mt_tint + '" />' +
|
||||||
'</div></div>' +
|
'</div></div>' +
|
||||||
|
|
||||||
'<div><h3>' + L.ml_eq + '</h3><div id="audio_eq"></div></div>');
|
'<div><h3 id="h_drc">' + L.ml_drc + '</h3><div id="audio_drc"></div></div>' +
|
||||||
|
'<div><h3>' + L.ml_eq + '</h3><div id="audio_eq"></div></div>' +
|
||||||
|
'');
|
||||||
|
|
||||||
var r = {
|
var r = {
|
||||||
"pb_mode": (sread('pb_mode', ['loop', 'next']) || 'next').split('-')[0],
|
"pb_mode": (sread('pb_mode', ['loop', 'next']) || 'next').split('-')[0],
|
||||||
|
@ -2492,8 +2498,13 @@ function start_actx() {
|
||||||
var afilt = (function () {
|
var afilt = (function () {
|
||||||
var r = {
|
var r = {
|
||||||
"eqen": false,
|
"eqen": false,
|
||||||
|
"drcen": 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": [4, 3, 2, 1, 0, 0, 1, 2, 3, 4],
|
"gains": [4, 3, 2, 1, 0, 0, 1, 2, 3, 4],
|
||||||
|
"drcv": [-24, 30, 12, 0.003, 0.25],
|
||||||
|
"drch": ['tresh', 'knee', 'ratio', 'atk', 'rls'],
|
||||||
|
"drck": ['threshold', 'knee', 'ratio', 'attack', 'release'],
|
||||||
|
"drcn": null,
|
||||||
"filters": [],
|
"filters": [],
|
||||||
"filterskip": [],
|
"filterskip": [],
|
||||||
"plugs": [],
|
"plugs": [],
|
||||||
|
@ -2503,16 +2514,18 @@ var afilt = (function () {
|
||||||
"acst": {}
|
"acst": {}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ACtx)
|
function setvis(vis) {
|
||||||
ebi('audio_eq').parentNode.style.display = 'none';
|
ebi('audio_eq').parentNode.style.display = ebi('audio_drc').parentNode.style.display = (vis ? '' : 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
setvis(ACtx);
|
||||||
|
|
||||||
r.init = function () {
|
r.init = function () {
|
||||||
start_actx();
|
start_actx();
|
||||||
if (r.cfg)
|
if (r.cfg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!actx)
|
setvis(actx);
|
||||||
ebi('audio_eq').parentNode.style.display = 'none';
|
|
||||||
|
|
||||||
// some browsers have insane high-frequency boost
|
// some browsers have insane high-frequency boost
|
||||||
// (or rather the actual problem is Q but close enough)
|
// (or rather the actual problem is Q but close enough)
|
||||||
|
@ -2599,12 +2612,20 @@ var afilt = (function () {
|
||||||
mp.acs = mpo.acs = null;
|
mp.acs = mpo.acs = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
r.apply = function () {
|
r.apply = function (v) {
|
||||||
r.init();
|
r.init();
|
||||||
r.draw();
|
r.draw();
|
||||||
|
|
||||||
if (!actx)
|
if (!actx) {
|
||||||
bcfg_set('au_eq', false);
|
bcfg_set('au_eq', r.eqen = false);
|
||||||
|
bcfg_set('au_drc', r.drcen = false);
|
||||||
|
}
|
||||||
|
else if (v === true && r.drcen && !r.eqen)
|
||||||
|
bcfg_set('au_eq', r.eqen = true);
|
||||||
|
else if (v === false && !r.eqen)
|
||||||
|
bcfg_set('au_drc', r.drcen = false);
|
||||||
|
|
||||||
|
r.drcn = null;
|
||||||
|
|
||||||
var plug = false;
|
var plug = false;
|
||||||
for (var a = 0; a < r.plugs.length; a++)
|
for (var a = 0; a < r.plugs.length; a++)
|
||||||
|
@ -2664,6 +2685,17 @@ var afilt = (function () {
|
||||||
fi.gain.value = r.amp + 0.94; // +.137 dB measured; now -.25 dB and almost bitperfect
|
fi.gain.value = r.amp + 0.94; // +.137 dB measured; now -.25 dB and almost bitperfect
|
||||||
r.filters.push(fi);
|
r.filters.push(fi);
|
||||||
|
|
||||||
|
// wait nevermind, drc goes first
|
||||||
|
timer.rm(showdrc);
|
||||||
|
if (r.drcen) {
|
||||||
|
fi = r.drcn = actx.createDynamicsCompressor();
|
||||||
|
for (var a = 0; a < r.drcv.length; a++)
|
||||||
|
fi[r.drck[a]].value = r.drcv[a];
|
||||||
|
|
||||||
|
r.filters.push(fi);
|
||||||
|
timer.add(showdrc);
|
||||||
|
}
|
||||||
|
|
||||||
if (Math.round(r.chw * 25) != 25) {
|
if (Math.round(r.chw * 25) != 25) {
|
||||||
var split = actx.createChannelSplitter(2),
|
var split = actx.createChannelSplitter(2),
|
||||||
merge = actx.createChannelMerger(2),
|
merge = actx.createChannelMerger(2),
|
||||||
|
@ -2736,6 +2768,31 @@ var afilt = (function () {
|
||||||
clmod(that, 'err', err);
|
clmod(that, 'err', err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function adj_drc() {
|
||||||
|
var err = false;
|
||||||
|
try {
|
||||||
|
var n = this.getAttribute('k'),
|
||||||
|
ov = r.drcv[n],
|
||||||
|
vs = this.value,
|
||||||
|
v = parseFloat(vs);
|
||||||
|
|
||||||
|
if (!isNum(v) || v + '' != vs)
|
||||||
|
throw new Error('inval v');
|
||||||
|
|
||||||
|
if (v == ov)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r.drcv[n] = v;
|
||||||
|
jwrite('au_drc', r.drcv);
|
||||||
|
if (r.drcn)
|
||||||
|
r.drcn[r.drck[n]].value = v;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
clmod(this, 'err', err);
|
||||||
|
}
|
||||||
|
|
||||||
function eq_mod(e) {
|
function eq_mod(e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
adj_band(this, 0);
|
adj_band(this, 0);
|
||||||
|
@ -2747,6 +2804,13 @@ var afilt = (function () {
|
||||||
adj_band(this, step);
|
adj_band(this, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showdrc() {
|
||||||
|
if (!r.drcn)
|
||||||
|
return timer.rm(showdrc);
|
||||||
|
|
||||||
|
ebi('h_drc').textContent = f2f(r.drcn.reduction, 1);
|
||||||
|
}
|
||||||
|
|
||||||
var html = ['<table><tr><td rowspan="4">',
|
var html = ['<table><tr><td rowspan="4">',
|
||||||
'<a id="au_eq" class="tgl btn" href="#" tt="' + L.mt_eq + '">enable</a></td>'],
|
'<a id="au_eq" class="tgl btn" href="#" tt="' + L.mt_eq + '">enable</a></td>'],
|
||||||
h2 = [], h3 = [], h4 = [];
|
h2 = [], h3 = [], h4 = [];
|
||||||
|
@ -2776,6 +2840,18 @@ var afilt = (function () {
|
||||||
html += h4.join('\n') + '</tr><table>';
|
html += h4.join('\n') + '</tr><table>';
|
||||||
ebi('audio_eq').innerHTML = html;
|
ebi('audio_eq').innerHTML = html;
|
||||||
|
|
||||||
|
h2 = [];
|
||||||
|
html = ['<table><tr><td rowspan="2">',
|
||||||
|
'<a id="au_drc" class="tgl btn" href="#" tt="' + L.mt_drc + '">enable</a></td>'];
|
||||||
|
|
||||||
|
for (var a = 0; a < r.drch.length; a++) {
|
||||||
|
html.push('<td>' + r.drch[a] + '</td>');
|
||||||
|
h2.push('<td><input type="text" class="drc_v" ' + NOAC + ' k="' + a + '" value="' + r.drcv[a] + '" /></td>');
|
||||||
|
}
|
||||||
|
html = html.join('\n') + '</tr><tr>';
|
||||||
|
html += h2.join('\n') + '</tr><table>';
|
||||||
|
ebi('audio_drc').innerHTML = html;
|
||||||
|
|
||||||
var stp = QSA('a.eq_step');
|
var stp = QSA('a.eq_step');
|
||||||
for (var a = 0, aa = stp.length; a < aa; a++)
|
for (var a = 0, aa = stp.length; a < aa; a++)
|
||||||
stp[a].onclick = eq_step;
|
stp[a].onclick = eq_step;
|
||||||
|
@ -2785,8 +2861,12 @@ var afilt = (function () {
|
||||||
txt[a].oninput = eq_mod;
|
txt[a].oninput = eq_mod;
|
||||||
txt[a].onkeydown = eq_keydown;
|
txt[a].onkeydown = eq_keydown;
|
||||||
}
|
}
|
||||||
|
txt = QSA('input.drc_v');
|
||||||
|
for (var a = 0; a < txt.length; a++)
|
||||||
|
txt[a].oninput = txt[a].onkeydown = adj_drc;
|
||||||
|
|
||||||
bcfg_bind(r, 'eqen', 'au_eq', false, r.apply);
|
bcfg_bind(r, 'eqen', 'au_eq', false, r.apply);
|
||||||
|
bcfg_bind(r, 'drcen', 'au_drc', false, r.apply);
|
||||||
|
|
||||||
r.draw();
|
r.draw();
|
||||||
return r;
|
return r;
|
||||||
|
|
Loading…
Reference in a new issue