diff --git a/js/audio-context.js b/js/audio-context.js index 10a1588..fed7887 100644 --- a/js/audio-context.js +++ b/js/audio-context.js @@ -12,6 +12,12 @@ function generateFrequencies(bandCount, minFreq = 20, maxFreq = 20000) { const safeMin = Math.max(10, minFreq); const safeMax = Math.min(96000, maxFreq); + if (bandCount <= 1) { + // Single band: use geometric mean of range + frequencies.push(Math.round(Math.sqrt(safeMin * safeMax))); + return frequencies; + } + for (let i = 0; i < bandCount; i++) { // Logarithmic interpolation const t = i / (bandCount - 1); @@ -175,7 +181,7 @@ class AudioContextManager { this.frequencies = generateFrequencies(newCount, this.freqRange.min, this.freqRange.max); // Interpolate current gains to new band count - const newGains = equalizerSettings._interpolateGains(this.currentGains, newCount); + const newGains = equalizerSettings.interpolateGains(this.currentGains, newCount); this.currentGains = newGains; equalizerSettings.setGains(newGains); @@ -1079,7 +1085,7 @@ class AudioContextManager { // Ensure gains array matches current band count let adjustedGains = gains; if (gains.length !== this.bandCount) { - adjustedGains = equalizerSettings._interpolateGains(gains, this.bandCount); + adjustedGains = equalizerSettings.interpolateGains(gains, this.bandCount); } const now = this.audioContext?.currentTime || 0; @@ -1535,7 +1541,7 @@ class AudioContextManager { const oldGains = this.geqGains; this.geqBandCount = newCount; this.geqFrequencies = generateFrequencies(newCount, this.geqFreqRange.min, this.geqFreqRange.max); - this.geqGains = equalizerSettings._interpolateGains(oldGains, newCount); + this.geqGains = equalizerSettings.interpolateGains(oldGains, newCount); equalizerSettings.setGraphicEqBandCount(newCount); equalizerSettings.setGraphicEqGains(this.geqGains); diff --git a/js/equalizer.js b/js/equalizer.js index ad7ca14..2125d3c 100644 --- a/js/equalizer.js +++ b/js/equalizer.js @@ -201,7 +201,7 @@ export class Equalizer { this.frequencyLabels = generateFrequencyLabels(this.frequencies); // Interpolate current gains to new band count - const newGains = equalizerSettings._interpolateGains(this.currentGains, newCount); + const newGains = equalizerSettings.interpolateGains(this.currentGains, newCount); this.currentGains = newGains; equalizerSettings.setGains(newGains); @@ -455,7 +455,7 @@ export class Equalizer { // Ensure gains array matches current band count let adjustedGains = gains; if (gains.length !== this.bandCount) { - adjustedGains = equalizerSettings._interpolateGains(gains, this.bandCount); + adjustedGains = equalizerSettings.interpolateGains(gains, this.bandCount); } const now = this.audioContext?.currentTime || 0; diff --git a/js/hrtf-generator.js b/js/hrtf-generator.js index 30b0bf3..8a114b4 100644 --- a/js/hrtf-generator.js +++ b/js/hrtf-generator.js @@ -65,8 +65,9 @@ export function generateHRTF(audioContext, azimuthDeg, elevationDeg = 0) { const contraData = sourceOnRight ? leftData : rightData; // Generate ipsilateral (near ear) IR — mostly a delayed impulse with slight coloring - const ipsiDelay = Math.max(0, sourceOnRight ? 0 : itdSamples); - const contraDelay = Math.max(0, sourceOnRight ? itdSamples : 0); + // Ipsilateral ear (near source) receives sound first; contralateral ear is delayed by ITD + const ipsiDelay = 0; + const contraDelay = Math.abs(itdSamples); // Create frequency-domain representation for head shadow const fftSize = IR_LENGTH; diff --git a/js/settings.js b/js/settings.js index ae71483..246528c 100644 --- a/js/settings.js +++ b/js/settings.js @@ -1512,7 +1512,7 @@ export async function initializeSettings(scrobbler, player, api, ui) { const newCount = Math.max(3, Math.min(32, parseInt(geqBandCountInput.value, 10) || 16)); geqBandCountInput.value = newCount; if (newCount === geqBandCount) return; - geqGains = equalizerSettings._interpolateGains(geqGains, newCount); + geqGains = equalizerSettings.interpolateGains(geqGains, newCount); geqBandCount = newCount; equalizerSettings.setGraphicEqGains(geqGains); audioContextManager.setGraphicEqBandCount(newCount); @@ -1778,7 +1778,7 @@ export async function initializeSettings(scrobbler, player, api, ui) { return; } const adjusted = - gains.length !== geqBandCount ? equalizerSettings._interpolateGains(gains, geqBandCount) : gains; + gains.length !== geqBandCount ? equalizerSettings.interpolateGains(gains, geqBandCount) : gains; geqGains = adjusted.map((g) => { const n = Number(g); return Number.isFinite(n) @@ -2446,7 +2446,6 @@ export async function initializeSettings(scrobbler, player, api, ui) { else if (meas) graphShift = 75 - getNormalizationOffset(meas); } - const sampleRate = autoeqSampleRate ? parseInt(autoeqSampleRate.value, 10) : 48000; let closest = -1, closestDist = Infinity; activeBands.forEach((band, i) => { diff --git a/js/storage.js b/js/storage.js index 27a598d..74237b2 100644 --- a/js/storage.js +++ b/js/storage.js @@ -1329,7 +1329,7 @@ export const equalizerSettings = { } // If different band count, try to interpolate or return flat if (gains.length > 0) { - return this._interpolateGains(gains, count); + return this.interpolateGains(gains, count); } } } @@ -1425,7 +1425,7 @@ export const equalizerSettings = { } // Interpolate stored Qs to match requested band count instead of discarding if (Array.isArray(qs) && qs.length >= this.MIN_BANDS) { - return this._interpolateGains(qs, count); + return this.interpolateGains(qs, count); } } } catch { @@ -1473,7 +1473,7 @@ export const equalizerSettings = { /** * Interpolate gains array to match target band count */ - _interpolateGains(sourceGains, targetCount) { + interpolateGains(sourceGains, targetCount) { if (sourceGains.length === targetCount) { return [...sourceGains]; } @@ -1808,7 +1808,7 @@ export const equalizerSettings = { return parsed.map((v) => (Number.isFinite(v) ? v : 0)); } if (Array.isArray(parsed) && parsed.length > 0) { - return this._interpolateGains(parsed, expectedCount); + return this.interpolateGains(parsed, expectedCount); } } } catch { @@ -1944,7 +1944,8 @@ export const binauralDspSettings = { setWideningAmount(amount) { const all = this._getAll(); - all.wideningAmount = Math.max(0, Math.min(2, amount)); + const n = Number(amount); + all.wideningAmount = Number.isFinite(n) ? Math.max(0, Math.min(2, n)) : 1.0; this._setAll(all); },