style: auto-fix linting issues
This commit is contained in:
parent
d4d1fe8494
commit
77f9e10fdc
4 changed files with 164 additions and 59 deletions
|
|
@ -2,7 +2,6 @@
|
|||
// Target Curves & Data Parser - Ported from Seap Engine
|
||||
// Contains target frequency response curves and raw data parser
|
||||
|
||||
|
||||
// Raw content synchronized with features/autoeq/Targets/ directory
|
||||
|
||||
const RAW_HARMAN_OE_2018 = `
|
||||
|
|
@ -2713,7 +2712,6 @@ const RAW_HIFI_ENDGAME_2026_MKII = `
|
|||
20000.00 72.378
|
||||
`;
|
||||
|
||||
|
||||
const RAW_PEQDB_ULTRA = `
|
||||
20.00 83.153
|
||||
20.36 83.149
|
||||
|
|
@ -3487,7 +3485,6 @@ const RAW_PEQDB_DIAMOND_BETA = `
|
|||
20000.00 72.028
|
||||
`;
|
||||
|
||||
|
||||
const RAW_SEAP = `
|
||||
20.00 82.982
|
||||
20.36 82.975
|
||||
|
|
@ -4301,7 +4298,6 @@ const RAW_FLAT_LINE = `
|
|||
20000.00 75.000
|
||||
`;
|
||||
|
||||
|
||||
// --- PARSER ---
|
||||
/**
|
||||
* Parse raw frequency/gain text data into [{freq, gain}] arrays
|
||||
|
|
@ -4331,15 +4327,17 @@ function parseRawData(raw) {
|
|||
|
||||
const hasHeader = /[a-zA-Z]/.test(firstLine);
|
||||
if (hasHeader) {
|
||||
const headers = firstLine.split(delimiter).map(h => h.trim().toLowerCase().replace(/['"]+/g, ''));
|
||||
const fIdx = headers.findIndex(h => h.includes('freq') || h === 'f');
|
||||
const headers = firstLine.split(delimiter).map((h) => h.trim().toLowerCase().replace(/['"]+/g, ''));
|
||||
const fIdx = headers.findIndex((h) => h.includes('freq') || h === 'f');
|
||||
if (fIdx > -1) freqIdx = fIdx;
|
||||
|
||||
const rIdx = headers.findIndex(h => h === 'raw');
|
||||
const rIdx = headers.findIndex((h) => h === 'raw');
|
||||
if (rIdx > -1) {
|
||||
gainIdx = rIdx;
|
||||
} else {
|
||||
const splIdx = headers.findIndex(h => h.includes('spl') || h.includes('gain') || h.includes('db') || h.includes('mag'));
|
||||
const splIdx = headers.findIndex(
|
||||
(h) => h.includes('spl') || h.includes('gain') || h.includes('db') || h.includes('mag')
|
||||
);
|
||||
if (splIdx > -1 && splIdx !== freqIdx) gainIdx = splIdx;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,42 +21,55 @@ const DB_DIVISOR = 40;
|
|||
function calculateBiquadResponse(f, band, sr = DEFAULT_SR) {
|
||||
if (!band.enabled) return 0;
|
||||
if (!band.type || band.type.length === 0) return 0;
|
||||
const w = 2 * PI * band.freq / sr;
|
||||
const p = 2 * PI * f / sr;
|
||||
const w = (2 * PI * band.freq) / sr;
|
||||
const p = (2 * PI * f) / sr;
|
||||
const s = Math.sin(w) / (2 * band.q);
|
||||
const A = Math.pow(DB_BASE, band.gain / DB_DIVISOR);
|
||||
const c = Math.cos(w);
|
||||
let b0 = 0, b1 = 0, b2 = 0, a0 = 0, a1 = 0, a2 = 0;
|
||||
let b0 = 0,
|
||||
b1 = 0,
|
||||
b2 = 0,
|
||||
a0 = 0,
|
||||
a1 = 0,
|
||||
a2 = 0;
|
||||
|
||||
const t = band.type[0];
|
||||
|
||||
if (t === 'p') {
|
||||
b0 = 1 + s * A; b1 = -2 * c; b2 = 1 - s * A;
|
||||
a0 = 1 + s / A; a1 = -2 * c; a2 = 1 - s / A;
|
||||
b0 = 1 + s * A;
|
||||
b1 = -2 * c;
|
||||
b2 = 1 - s * A;
|
||||
a0 = 1 + s / A;
|
||||
a1 = -2 * c;
|
||||
a2 = 1 - s / A;
|
||||
} else if (t === 'l') {
|
||||
const sq = 2 * Math.sqrt(A) * s;
|
||||
b0 = A * ((A + 1) - (A - 1) * c + sq);
|
||||
b1 = 2 * A * ((A - 1) - (A + 1) * c);
|
||||
b2 = A * ((A + 1) - (A - 1) * c - sq);
|
||||
a0 = (A + 1) + (A - 1) * c + sq;
|
||||
a1 = -2 * ((A - 1) + (A + 1) * c);
|
||||
a2 = (A + 1) + (A - 1) * c - sq;
|
||||
b0 = A * (A + 1 - (A - 1) * c + sq);
|
||||
b1 = 2 * A * (A - 1 - (A + 1) * c);
|
||||
b2 = A * (A + 1 - (A - 1) * c - sq);
|
||||
a0 = A + 1 + (A - 1) * c + sq;
|
||||
a1 = -2 * (A - 1 + (A + 1) * c);
|
||||
a2 = A + 1 + (A - 1) * c - sq;
|
||||
} else if (t === 'h') {
|
||||
const sq = 2 * Math.sqrt(A) * s;
|
||||
b0 = A * ((A + 1) + (A - 1) * c + sq);
|
||||
b1 = -2 * A * ((A - 1) + (A + 1) * c);
|
||||
b2 = A * ((A + 1) + (A - 1) * c - sq);
|
||||
a0 = (A + 1) - (A - 1) * c + sq;
|
||||
a1 = 2 * ((A - 1) - (A + 1) * c);
|
||||
a2 = (A + 1) - (A - 1) * c - sq;
|
||||
b0 = A * (A + 1 + (A - 1) * c + sq);
|
||||
b1 = -2 * A * (A - 1 + (A + 1) * c);
|
||||
b2 = A * (A + 1 + (A - 1) * c - sq);
|
||||
a0 = A + 1 - (A - 1) * c + sq;
|
||||
a1 = 2 * (A - 1 - (A + 1) * c);
|
||||
a2 = A + 1 - (A - 1) * c - sq;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const _a0 = 1 / a0;
|
||||
const b0n = b0 * _a0, b1n = b1 * _a0, b2n = b2 * _a0;
|
||||
const a1n = a1 * _a0, a2n = a2 * _a0;
|
||||
const cp = Math.cos(p), c2p = Math.cos(2 * p);
|
||||
const b0n = b0 * _a0,
|
||||
b1n = b1 * _a0,
|
||||
b2n = b2 * _a0;
|
||||
const a1n = a1 * _a0,
|
||||
a2n = a2 * _a0;
|
||||
const cp = Math.cos(p),
|
||||
c2p = Math.cos(2 * p);
|
||||
const n = b0n * b0n + b1n * b1n + b2n * b2n + 2 * (b0n * b1n + b1n * b2n) * cp + 2 * b0n * b2n * c2p;
|
||||
const d = 1 + a1n * a1n + a2n * a2n + 2 * (a1n + a1n * a2n) * cp + 2 * a2n * c2p;
|
||||
return 10 * Math.log10(n / d);
|
||||
|
|
@ -74,7 +87,10 @@ function interpolate(freq, data) {
|
|||
if (freq >= data[data.length - 1].freq) return data[data.length - 1].gain;
|
||||
for (let i = 0; i < data.length - 1; i++) {
|
||||
if (freq >= data[i].freq && freq <= data[i + 1].freq) {
|
||||
return data[i].gain + (freq - data[i].freq) / (data[i + 1].freq - data[i].freq) * (data[i + 1].gain - data[i].gain);
|
||||
return (
|
||||
data[i].gain +
|
||||
((freq - data[i].freq) / (data[i + 1].freq - data[i].freq)) * (data[i + 1].gain - data[i].gain)
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -86,7 +102,8 @@ function interpolate(freq, data) {
|
|||
* @returns {number} Average gain in midrange
|
||||
*/
|
||||
function getNormalizationOffset(data) {
|
||||
let sum = 0, count = 0;
|
||||
let sum = 0,
|
||||
count = 0;
|
||||
for (const p of data) {
|
||||
if (p.freq >= 250 && p.freq <= 2500) {
|
||||
sum += p.gain;
|
||||
|
|
@ -108,18 +125,29 @@ function getNormalizationOffset(data) {
|
|||
* @param {number} maxQ - Maximum Q factor
|
||||
* @returns {Array<{id: number, type: string, freq: number, gain: number, q: number, enabled: boolean}>}
|
||||
*/
|
||||
function runAutoEqAlgorithm(measurement, target, bandCount, maxFreq = 16000, minFreq = 20, maxQ = 5.0, sampleRate = DEFAULT_SR) {
|
||||
function runAutoEqAlgorithm(
|
||||
measurement,
|
||||
target,
|
||||
bandCount,
|
||||
maxFreq = 16000,
|
||||
minFreq = 20,
|
||||
maxQ = 5.0,
|
||||
sampleRate = DEFAULT_SR
|
||||
) {
|
||||
if (minFreq > maxFreq) return [];
|
||||
const off = getNormalizationOffset(target) - getNormalizationOffset(measurement);
|
||||
let err = measurement.map(p => ({ freq: p.freq, gain: (p.gain + off) - interpolate(p.freq, target) }));
|
||||
let err = measurement.map((p) => ({ freq: p.freq, gain: p.gain + off - interpolate(p.freq, target) }));
|
||||
|
||||
const hasInRangePoints = err.some(p => p.freq >= minFreq && p.freq <= maxFreq);
|
||||
const hasInRangePoints = err.some((p) => p.freq >= minFreq && p.freq <= maxFreq);
|
||||
if (!hasInRangePoints) return [];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (let i = 0; i < bandCount; i++) {
|
||||
let maxDev = 0, maxWeightedDev = 0, peakFreq = 1000, peakIdx = 0;
|
||||
let maxDev = 0,
|
||||
maxWeightedDev = 0,
|
||||
peakFreq = 1000,
|
||||
peakIdx = 0;
|
||||
|
||||
// Scan for maximum weighted error
|
||||
for (let j = 0; j < err.length; j++) {
|
||||
|
|
@ -158,8 +186,10 @@ function runAutoEqAlgorithm(measurement, target, bandCount, maxFreq = 16000, min
|
|||
if (Math.abs(gain) < 0.2) break;
|
||||
|
||||
// Q factor calculation from error bandwidth (half-gain points)
|
||||
let upperFreq = peakFreq, lowerFreq = peakFreq;
|
||||
let foundLower = false, foundUpper = false;
|
||||
let upperFreq = peakFreq,
|
||||
lowerFreq = peakFreq;
|
||||
let foundLower = false,
|
||||
foundUpper = false;
|
||||
const thresholdError = maxDev / 2;
|
||||
for (let k = peakIdx; k >= 0; k--) {
|
||||
if (Math.abs(err[k].gain) < Math.abs(thresholdError)) {
|
||||
|
|
@ -179,9 +209,9 @@ function runAutoEqAlgorithm(measurement, target, bandCount, maxFreq = 16000, min
|
|||
// If half-gain boundary not found on one side, mirror the other side
|
||||
// to avoid degenerate bandwidth = 0 producing extremely narrow filters
|
||||
if (!foundLower && foundUpper) {
|
||||
lowerFreq = peakFreq * peakFreq / upperFreq;
|
||||
lowerFreq = (peakFreq * peakFreq) / upperFreq;
|
||||
} else if (!foundUpper && foundLower) {
|
||||
upperFreq = peakFreq * peakFreq / lowerFreq;
|
||||
upperFreq = (peakFreq * peakFreq) / lowerFreq;
|
||||
} else if (!foundLower && !foundUpper) {
|
||||
// Neither boundary found — use 1 octave default
|
||||
lowerFreq = peakFreq / Math.SQRT2;
|
||||
|
|
@ -212,7 +242,7 @@ function runAutoEqAlgorithm(measurement, target, bandCount, maxFreq = 16000, min
|
|||
out.push(newBand);
|
||||
|
||||
// Update error curve by applying the new band's response
|
||||
err = err.map(p => ({ ...p, gain: p.gain + calculateBiquadResponse(p.freq, newBand, sampleRate) }));
|
||||
err = err.map((p) => ({ ...p, gain: p.gain + calculateBiquadResponse(p.freq, newBand, sampleRate) }));
|
||||
}
|
||||
|
||||
return out.sort((a, b) => a.freq - b.freq).map((b, i) => ({ ...b, id: i }));
|
||||
|
|
|
|||
|
|
@ -12,23 +12,83 @@ const CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours
|
|||
// 5 most popular headphones — pre-loaded as defaults and shown in the headphone select
|
||||
// All measured on Rtings B&K 5128 rig for consistency
|
||||
const POPULAR_HEADPHONES = [
|
||||
{ name: 'Sony WH-1000XM5 (Rtings)', type: 'over-ear', path: 'Rtings/Bruel & Kjaer 5128 over-ear/Sony WH-1000XM5', fileName: 'Sony WH-1000XM5.csv' },
|
||||
{ name: 'Apple AirPods Pro2 (Rtings)', type: 'in-ear', path: 'Rtings/Bruel & Kjaer 5128 in-ear/Apple AirPods Pro2', fileName: 'Apple AirPods Pro2.csv' },
|
||||
{ name: 'Sony WF-1000XM5 (Rtings)', type: 'in-ear', path: 'Rtings/Bruel & Kjaer 5128 in-ear/Sony WF-1000XM5', fileName: 'Sony WF-1000XM5.csv' },
|
||||
{ name: 'Samsung Galaxy Buds3 Pro (Rtings)', type: 'in-ear', path: 'Rtings/Bruel & Kjaer 5128 in-ear/Samsung Galaxy Buds3 Pro', fileName: 'Samsung Galaxy Buds3 Pro.csv' },
|
||||
{ name: 'Sennheiser HD 600 (Rtings)', type: 'over-ear', path: 'Rtings/Bruel & Kjaer 5128 over-ear/Sennheiser HD 600', fileName: 'Sennheiser HD 600.csv' },
|
||||
{
|
||||
name: 'Sony WH-1000XM5 (Rtings)',
|
||||
type: 'over-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 over-ear/Sony WH-1000XM5',
|
||||
fileName: 'Sony WH-1000XM5.csv',
|
||||
},
|
||||
{
|
||||
name: 'Apple AirPods Pro2 (Rtings)',
|
||||
type: 'in-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 in-ear/Apple AirPods Pro2',
|
||||
fileName: 'Apple AirPods Pro2.csv',
|
||||
},
|
||||
{
|
||||
name: 'Sony WF-1000XM5 (Rtings)',
|
||||
type: 'in-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 in-ear/Sony WF-1000XM5',
|
||||
fileName: 'Sony WF-1000XM5.csv',
|
||||
},
|
||||
{
|
||||
name: 'Samsung Galaxy Buds3 Pro (Rtings)',
|
||||
type: 'in-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 in-ear/Samsung Galaxy Buds3 Pro',
|
||||
fileName: 'Samsung Galaxy Buds3 Pro.csv',
|
||||
},
|
||||
{
|
||||
name: 'Sennheiser HD 600 (Rtings)',
|
||||
type: 'over-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 over-ear/Sennheiser HD 600',
|
||||
fileName: 'Sennheiser HD 600.csv',
|
||||
},
|
||||
];
|
||||
|
||||
// Static fallback list in case GitHub API fails — popular picks + additional well-known models
|
||||
const FALLBACK_INDEX = [
|
||||
...POPULAR_HEADPHONES,
|
||||
{ name: 'Sennheiser HD 600 (Filk)', type: 'over-ear', path: 'Filk/over-ear/Sennheiser HD 600', fileName: 'Sennheiser HD 600.csv' },
|
||||
{ name: 'Sennheiser HD 600 (Innerfidelity)', type: 'over-ear', path: 'Innerfidelity/over-ear/Sennheiser HD 600', fileName: 'Sennheiser HD 600.csv' },
|
||||
{ name: 'Samsung Galaxy Buds2 Pro (Rtings)', type: 'in-ear', path: 'Rtings/Bruel & Kjaer 5128 in-ear/Samsung Galaxy Buds2 Pro', fileName: 'Samsung Galaxy Buds2 Pro.csv' },
|
||||
{ name: 'Sony WF-1000XM5 (Kazi)', type: 'in-ear', path: 'Kazi/in-ear/Sony WF-1000XM5', fileName: 'Sony WF-1000XM5.csv' },
|
||||
{ name: 'Samsung Galaxy Buds3 Pro (DHRME)', type: 'in-ear', path: 'DHRME/in-ear/Samsung Galaxy Buds3 Pro', fileName: 'Samsung Galaxy Buds3 Pro.csv' },
|
||||
{ name: 'Apple AirPods Pro (Super Review)', type: 'in-ear', path: 'Super Review/in-ear/Apple AirPods Pro', fileName: 'Apple AirPods Pro.csv' },
|
||||
{ name: 'Sennheiser HD 600 (2020) (Kuulokenurkka)', type: 'over-ear', path: 'Kuulokenurkka/over-ear/Sennheiser HD 600 (2020)', fileName: 'Sennheiser HD 600 (2020).csv' },
|
||||
{
|
||||
name: 'Sennheiser HD 600 (Filk)',
|
||||
type: 'over-ear',
|
||||
path: 'Filk/over-ear/Sennheiser HD 600',
|
||||
fileName: 'Sennheiser HD 600.csv',
|
||||
},
|
||||
{
|
||||
name: 'Sennheiser HD 600 (Innerfidelity)',
|
||||
type: 'over-ear',
|
||||
path: 'Innerfidelity/over-ear/Sennheiser HD 600',
|
||||
fileName: 'Sennheiser HD 600.csv',
|
||||
},
|
||||
{
|
||||
name: 'Samsung Galaxy Buds2 Pro (Rtings)',
|
||||
type: 'in-ear',
|
||||
path: 'Rtings/Bruel & Kjaer 5128 in-ear/Samsung Galaxy Buds2 Pro',
|
||||
fileName: 'Samsung Galaxy Buds2 Pro.csv',
|
||||
},
|
||||
{
|
||||
name: 'Sony WF-1000XM5 (Kazi)',
|
||||
type: 'in-ear',
|
||||
path: 'Kazi/in-ear/Sony WF-1000XM5',
|
||||
fileName: 'Sony WF-1000XM5.csv',
|
||||
},
|
||||
{
|
||||
name: 'Samsung Galaxy Buds3 Pro (DHRME)',
|
||||
type: 'in-ear',
|
||||
path: 'DHRME/in-ear/Samsung Galaxy Buds3 Pro',
|
||||
fileName: 'Samsung Galaxy Buds3 Pro.csv',
|
||||
},
|
||||
{
|
||||
name: 'Apple AirPods Pro (Super Review)',
|
||||
type: 'in-ear',
|
||||
path: 'Super Review/in-ear/Apple AirPods Pro',
|
||||
fileName: 'Apple AirPods Pro.csv',
|
||||
},
|
||||
{
|
||||
name: 'Sennheiser HD 600 (2020) (Kuulokenurkka)',
|
||||
type: 'over-ear',
|
||||
path: 'Kuulokenurkka/over-ear/Sennheiser HD 600 (2020)',
|
||||
fileName: 'Sennheiser HD 600 (2020).csv',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +99,11 @@ const FALLBACK_INDEX = [
|
|||
*/
|
||||
async function fetchAutoEqIndex() {
|
||||
// Migrate: remove old localStorage cache to free quota
|
||||
try { localStorage.removeItem(OLD_LS_CACHE_KEY); } catch { /* ignore */ }
|
||||
try {
|
||||
localStorage.removeItem(OLD_LS_CACHE_KEY);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
// 1. Try loading from IndexedDB cache
|
||||
try {
|
||||
|
|
@ -61,7 +125,9 @@ async function fetchAutoEqIndex() {
|
|||
const timeoutId = setTimeout(() => controller.abort(), 8000);
|
||||
let response;
|
||||
try {
|
||||
response = await fetch('https://api.github.com/repos/jaakkopasanen/AutoEq/git/trees/master?recursive=1', { signal: controller.signal });
|
||||
response = await fetch('https://api.github.com/repos/jaakkopasanen/AutoEq/git/trees/master?recursive=1', {
|
||||
signal: controller.signal,
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
|
@ -73,7 +139,9 @@ async function fetchAutoEqIndex() {
|
|||
console.warn('[AutoEQ] GitHub API limit reached. Using stale cache.');
|
||||
return cached.data;
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
console.warn('[AutoEQ] GitHub API error. Using fallback.');
|
||||
return FALLBACK_INDEX;
|
||||
}
|
||||
|
|
@ -92,13 +160,15 @@ async function fetchAutoEqIndex() {
|
|||
const fileNameLower = fileName.toLowerCase();
|
||||
|
||||
// Skip non-measurement files (EQ presets, not raw frequency response)
|
||||
if (fileNameLower.includes('parametriceq') ||
|
||||
if (
|
||||
fileNameLower.includes('parametriceq') ||
|
||||
fileNameLower.includes('fixedbandeq') ||
|
||||
fileNameLower.includes('graphiceq') ||
|
||||
fileNameLower.includes('convolution') ||
|
||||
fileNameLower.includes('fixed band eq') ||
|
||||
fileNameLower.includes('parametric eq') ||
|
||||
fileNameLower.includes('graphic eq')) {
|
||||
fileNameLower.includes('graphic eq')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +214,9 @@ async function fetchAutoEqIndex() {
|
|||
try {
|
||||
const cached = await db.getSetting(CACHE_KEY);
|
||||
if (cached?.data) return cached.data;
|
||||
} catch { /* ignore */ }
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
} else {
|
||||
console.error('[AutoEQ] Failed to fetch index:', err);
|
||||
}
|
||||
|
|
@ -205,12 +277,12 @@ function searchHeadphones(query, entries, typeFilter = 'all', limit = 100) {
|
|||
let filtered = entries;
|
||||
|
||||
if (typeFilter !== 'all') {
|
||||
filtered = filtered.filter(e => e.type === typeFilter);
|
||||
filtered = filtered.filter((e) => e.type === typeFilter);
|
||||
}
|
||||
|
||||
if (query && query.trim()) {
|
||||
const lower = query.toLowerCase().trim();
|
||||
filtered = filtered.filter(e => e.name.toLowerCase().includes(lower));
|
||||
filtered = filtered.filter((e) => e.name.toLowerCase().includes(lower));
|
||||
}
|
||||
|
||||
return filtered.slice(0, limit);
|
||||
|
|
|
|||
|
|
@ -7910,6 +7910,7 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn {
|
|||
background: rgb(255 255 255 / 0.5);
|
||||
border: 1px dashed rgb(255 255 255 / 0.3);
|
||||
}
|
||||
|
||||
.legend-corrected .legend-dot {
|
||||
background: #f472b6;
|
||||
}
|
||||
|
|
@ -8109,6 +8110,7 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn {
|
|||
.autoeq-status.error {
|
||||
color: var(--destructive);
|
||||
}
|
||||
|
||||
.autoeq-status.success {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
|
@ -8941,12 +8943,15 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn {
|
|||
.speaker-eq-slider-value.bass {
|
||||
color: #22d3ee;
|
||||
}
|
||||
|
||||
.speaker-eq-slider-value.room {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.speaker-eq-section .autoeq-control-label.bass {
|
||||
color: #22d3ee;
|
||||
}
|
||||
|
||||
.speaker-eq-section .autoeq-control-label.room {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue