Add import/export for legacy graphic EQ
Export outputs EqualizerAPO-compatible format with all 16 bands. Import accepts EqualizerAPO format or simple freq/gain pairs, maps to nearest GEQ band by log-frequency distance, and ignores Q values since legacy mode uses fixed dB sliders. https://claude.ai/code/session_01AgSx7SP1dH5KFmpGXCAUvU
This commit is contained in:
parent
c6a967dc3a
commit
ae9446cbd1
2 changed files with 116 additions and 0 deletions
20
index.html
20
index.html
|
|
@ -4352,6 +4352,26 @@
|
|||
<button id="legacy-graphic-eq-reset-btn" class="btn-secondary">
|
||||
Reset
|
||||
</button>
|
||||
<button
|
||||
id="legacy-geq-import-btn"
|
||||
class="btn-secondary"
|
||||
title="Import EQ from text file (frequency/gain pairs, Q values ignored)"
|
||||
>
|
||||
Import
|
||||
</button>
|
||||
<button
|
||||
id="legacy-geq-export-btn"
|
||||
class="btn-secondary"
|
||||
title="Export EQ to text file"
|
||||
>
|
||||
Export
|
||||
</button>
|
||||
<input
|
||||
type="file"
|
||||
id="legacy-geq-import-file"
|
||||
accept=".txt"
|
||||
style="display: none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1383,6 +1383,102 @@ export async function initializeSettings(scrobbler, player, api, ui) {
|
|||
});
|
||||
});
|
||||
|
||||
// Legacy EQ Import / Export
|
||||
const GEQ_FREQUENCIES = [25, 40, 63, 100, 160, 250, 400, 630, 1000, 1600, 2500, 4000, 6300, 10000, 16000, 20000];
|
||||
const legacyGeqExportBtn = document.getElementById('legacy-geq-export-btn');
|
||||
const legacyGeqImportBtn = document.getElementById('legacy-geq-import-btn');
|
||||
const legacyGeqImportFile = document.getElementById('legacy-geq-import-file');
|
||||
|
||||
if (legacyGeqExportBtn) {
|
||||
legacyGeqExportBtn.addEventListener('click', () => {
|
||||
const lines = [`Preamp: ${geqPreamp.toFixed(1)} dB`];
|
||||
GEQ_FREQUENCIES.forEach((freq, i) => {
|
||||
lines.push(`Filter ${i + 1}: ON PK Fc ${freq} Hz Gain ${geqGains[i].toFixed(1)} dB Q 1.41`);
|
||||
});
|
||||
const blob = new Blob([lines.join('\n')], { type: 'text/plain' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'legacy-eq.txt';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
}
|
||||
|
||||
if (legacyGeqImportBtn && legacyGeqImportFile) {
|
||||
legacyGeqImportBtn.addEventListener('click', () => legacyGeqImportFile.click());
|
||||
legacyGeqImportFile.addEventListener('change', (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
try {
|
||||
const text = event.target.result;
|
||||
const lines = text.split('\n');
|
||||
let preamp = 0;
|
||||
const importedPoints = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const preampMatch = line.match(/Preamp:\s*([-\d.]+)\s*dB/i);
|
||||
if (preampMatch) {
|
||||
preamp = parseFloat(preampMatch[1]);
|
||||
continue;
|
||||
}
|
||||
// EqualizerAPO format: Filter N: ON PK Fc XXXX Hz Gain X.X dB Q X.XX
|
||||
const filterMatch = line.match(
|
||||
/Filter\s+\d+:\s*ON\s+\w+\s+Fc\s+([\d.]+)\s*Hz\s+Gain\s+([-\d.]+)\s*dB/i
|
||||
);
|
||||
if (filterMatch) {
|
||||
importedPoints.push({ freq: parseFloat(filterMatch[1]), gain: parseFloat(filterMatch[2]) });
|
||||
continue;
|
||||
}
|
||||
// Simple two-column format: freq gain (whitespace/tab/comma separated)
|
||||
const simpleMatch = line.trim().match(/^([\d.]+)[,\s\t]+([-\d.]+)/);
|
||||
if (simpleMatch) {
|
||||
importedPoints.push({ freq: parseFloat(simpleMatch[1]), gain: parseFloat(simpleMatch[2]) });
|
||||
}
|
||||
}
|
||||
|
||||
if (importedPoints.length === 0) return;
|
||||
|
||||
// Sort by frequency
|
||||
importedPoints.sort((a, b) => a.freq - b.freq);
|
||||
|
||||
// Map imported points to the 16 GEQ bands using nearest-frequency matching
|
||||
const newGains = GEQ_FREQUENCIES.map((targetFreq) => {
|
||||
// Find the closest imported point by log-frequency distance
|
||||
let closest = importedPoints[0];
|
||||
let minDist = Math.abs(Math.log10(targetFreq) - Math.log10(closest.freq));
|
||||
for (let j = 1; j < importedPoints.length; j++) {
|
||||
const dist = Math.abs(Math.log10(targetFreq) - Math.log10(importedPoints[j].freq));
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closest = importedPoints[j];
|
||||
}
|
||||
}
|
||||
// Clamp to slider range
|
||||
return Math.max(parseFloat(geqRange.min), Math.min(parseFloat(geqRange.max), closest.gain));
|
||||
});
|
||||
|
||||
geqGains = newGains;
|
||||
geqPreamp = Math.max(-20, Math.min(20, preamp));
|
||||
equalizerSettings.setGraphicEqGains(geqGains);
|
||||
equalizerSettings.setGraphicEqPreamp(geqPreamp);
|
||||
audioContextManager.setGraphicEqAllGains(geqGains);
|
||||
audioContextManager.setGraphicEqPreamp(geqPreamp);
|
||||
geqSyncAllSliders();
|
||||
geqPreampSliders.forEach((s) => (s.value = geqPreamp));
|
||||
geqPreampValues.forEach((v) => (v.textContent = `${geqPreamp.toFixed(1)} dB`));
|
||||
geqPresetSelects.forEach((s) => (s.value = ''));
|
||||
} catch (err) {
|
||||
console.error('[Legacy GEQ Import] Failed:', err);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
e.target.value = '';
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Precision AutoEQ - Redesigned Equalizer
|
||||
// ========================================
|
||||
|
|
|
|||
Loading…
Reference in a new issue