fix: address CodeRabbit review - shelf Q round-trip, IIR gain setters, import persistence, tooltip sum
This commit is contained in:
parent
91eaa1f1dc
commit
55b49cc77a
3 changed files with 59 additions and 36 deletions
|
|
@ -718,6 +718,23 @@ class AudioContextManager {
|
|||
/**
|
||||
* Set gain for a specific band
|
||||
*/
|
||||
/**
|
||||
* Replace an IIR shelf filter node with updated coefficients and reconnect the chain.
|
||||
*/
|
||||
_replaceShelfFilter(index) {
|
||||
const filter = this.filters[index];
|
||||
if (!filter?._shelfType || !this.audioContext) return;
|
||||
const type = this.currentTypes?.[index] || filter._shelfType;
|
||||
const freq = this.frequencies[index];
|
||||
const gain = this.currentGains[index] || 0;
|
||||
const q = this.currentQs?.[index] > 0 ? this.currentQs[index] : this._calculateQ(index);
|
||||
const coeffs = computeShelfCoefficients(type, freq, gain, q, this.audioContext.sampleRate);
|
||||
const iir = this.audioContext.createIIRFilter(coeffs.feedforward, coeffs.feedback);
|
||||
iir._shelfType = type;
|
||||
try { filter.disconnect(); } catch { /* ignore */ }
|
||||
this.filters[index] = iir;
|
||||
}
|
||||
|
||||
setBandGain(bandIndex, gainDb) {
|
||||
if (bandIndex < 0 || bandIndex >= this.bandCount) return;
|
||||
|
||||
|
|
@ -725,8 +742,13 @@ class AudioContextManager {
|
|||
this.currentGains[bandIndex] = clampedGain;
|
||||
|
||||
if (this.filters[bandIndex] && this.audioContext) {
|
||||
const now = this.audioContext.currentTime;
|
||||
this.filters[bandIndex].gain.setTargetAtTime(clampedGain, now, 0.01);
|
||||
if (this.filters[bandIndex]._shelfType) {
|
||||
this._replaceShelfFilter(bandIndex);
|
||||
this._connectGraph();
|
||||
} else {
|
||||
const now = this.audioContext.currentTime;
|
||||
this.filters[bandIndex].gain.setTargetAtTime(clampedGain, now, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
equalizerSettings.setGains(this.currentGains);
|
||||
|
|
@ -745,16 +767,26 @@ class AudioContextManager {
|
|||
}
|
||||
|
||||
const now = this.audioContext?.currentTime || 0;
|
||||
let needsReconnect = false;
|
||||
|
||||
adjustedGains.forEach((gain, index) => {
|
||||
const clampedGain = this._clampGain(gain);
|
||||
this.currentGains[index] = clampedGain;
|
||||
|
||||
if (this.filters[index]) {
|
||||
this.filters[index].gain.setTargetAtTime(clampedGain, now, 0.01);
|
||||
if (this.filters[index]._shelfType) {
|
||||
this._replaceShelfFilter(index);
|
||||
needsReconnect = true;
|
||||
} else {
|
||||
this.filters[index].gain.setTargetAtTime(clampedGain, now, 0.01);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (needsReconnect) {
|
||||
this._connectGraph();
|
||||
}
|
||||
|
||||
equalizerSettings.setGains(this.currentGains);
|
||||
}
|
||||
|
||||
|
|
@ -949,15 +981,9 @@ class AudioContextManager {
|
|||
sortedBands.forEach((band, index) => {
|
||||
if (index >= count) return;
|
||||
const filterType = band.type === 'lowshelf' ? 'LSC' : band.type === 'highshelf' ? 'HSC' : 'PK';
|
||||
if (band.type === 'lowshelf' || band.type === 'highshelf') {
|
||||
lines.push(
|
||||
`Filter ${index + 1}: ON ${filterType} Fc ${newFrequencies[index]} Hz Gain ${newGains[index].toFixed(1)} dB`
|
||||
);
|
||||
} else {
|
||||
lines.push(
|
||||
`Filter ${index + 1}: ON ${filterType} Fc ${newFrequencies[index]} Hz Gain ${newGains[index].toFixed(1)} dB Q ${newQs[index].toFixed(2)}`
|
||||
);
|
||||
}
|
||||
lines.push(
|
||||
`Filter ${index + 1}: ON ${filterType} Fc ${newFrequencies[index]} Hz Gain ${newGains[index].toFixed(1)} dB Q ${newQs[index].toFixed(2)}`
|
||||
);
|
||||
});
|
||||
|
||||
return lines.join('\n');
|
||||
|
|
@ -976,17 +1002,11 @@ class AudioContextManager {
|
|||
const gain = this.currentGains[index] || 0;
|
||||
const type = (this.currentTypes && this.currentTypes[index]) || 'peaking';
|
||||
const filterType = type === 'lowshelf' ? 'LSC' : type === 'highshelf' ? 'HSC' : 'PK';
|
||||
const q = this.currentQs && this.currentQs[index] > 0 ? this.currentQs[index] : this._calculateQ(index);
|
||||
const filterNum = index + 1;
|
||||
if (type === 'lowshelf' || type === 'highshelf') {
|
||||
lines.push(
|
||||
`Filter ${filterNum}: ON ${filterType} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB`
|
||||
);
|
||||
} else {
|
||||
const q = this.currentQs && this.currentQs[index] > 0 ? this.currentQs[index] : this._calculateQ(index);
|
||||
lines.push(
|
||||
`Filter ${filterNum}: ON ${filterType} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB Q ${q.toFixed(2)}`
|
||||
);
|
||||
}
|
||||
lines.push(
|
||||
`Filter ${filterNum}: ON ${filterType} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB Q ${q.toFixed(2)}`
|
||||
);
|
||||
});
|
||||
|
||||
return lines.join('\n');
|
||||
|
|
@ -1067,7 +1087,8 @@ class AudioContextManager {
|
|||
this._connectGraph();
|
||||
}
|
||||
|
||||
// Persist all band settings
|
||||
// Persist all band settings including custom frequencies
|
||||
equalizerSettings.setCustomFrequencies(this.frequencies);
|
||||
equalizerSettings.setGains(this.currentGains);
|
||||
equalizerSettings.setBandTypes(this.currentTypes);
|
||||
equalizerSettings.setBandQs(this.currentQs);
|
||||
|
|
|
|||
|
|
@ -625,13 +625,9 @@ export class Equalizer {
|
|||
const type = filter ? filter.type : 'peaking';
|
||||
const typeMap = { peaking: 'PK', lowshelf: 'LSC', highshelf: 'HSC' };
|
||||
const typeStr = typeMap[type] || 'PK';
|
||||
const q = filter && !filter._shelfType ? filter.Q.value : this._calculateQ(index);
|
||||
const filterNum = index + 1;
|
||||
if (type === 'lowshelf' || type === 'highshelf') {
|
||||
lines.push(`Filter ${filterNum}: ON ${typeStr} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB`);
|
||||
} else {
|
||||
const q = filter ? filter.Q.value : this._calculateQ(index);
|
||||
lines.push(`Filter ${filterNum}: ON ${typeStr} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB Q ${q.toFixed(2)}`);
|
||||
}
|
||||
lines.push(`Filter ${filterNum}: ON ${typeStr} Fc ${freq} Hz Gain ${gain.toFixed(1)} dB Q ${q.toFixed(2)}`);
|
||||
});
|
||||
|
||||
return lines.join('\n');
|
||||
|
|
|
|||
|
|
@ -2210,17 +2210,23 @@ export async function initializeSettings(scrobbler, player, api, ui) {
|
|||
// Show tooltip on drag
|
||||
if (isDragged) {
|
||||
ctx.save();
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.8)';
|
||||
const txt = `${Math.round(band.freq)} Hz ${band.gain > 0 ? '+' : ''}${band.gain.toFixed(1)} dB Q${band.q.toFixed(2)}`;
|
||||
ctx.font = 'bold 11px system-ui, sans-serif';
|
||||
const tw = ctx.measureText(txt).width + 12;
|
||||
const tx = Math.min(x - tw / 2, rect.width - tw - 5);
|
||||
const ty = y - 28;
|
||||
ctx.fillRect(tx, ty, tw, 20);
|
||||
const line1 = `${Math.round(band.freq)} Hz ${band.gain > 0 ? '+' : ''}${band.gain.toFixed(1)} dB Q${band.q.toFixed(2)}`;
|
||||
const line2 = `Sum: ${nodeGain > 0 ? '+' : ''}${nodeGain.toFixed(1)} dB`;
|
||||
const tw1 = ctx.measureText(line1).width;
|
||||
const tw2 = ctx.measureText(line2).width;
|
||||
const tw = Math.max(tw1, tw2) + 12;
|
||||
const th = 34;
|
||||
const tx = Math.max(5, Math.min(x - tw / 2, rect.width - tw - 5));
|
||||
const ty = y - 44;
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.8)';
|
||||
ctx.fillRect(tx, ty, tw, th);
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(txt, tx + tw / 2, ty + 10);
|
||||
ctx.fillText(line1, tx + tw / 2, ty + 10);
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.7)';
|
||||
ctx.fillText(line2, tx + tw / 2, ty + 24);
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue