Update Vite configuration to deduplicate React and React-DOM; enhance DeviceContext with syncPeqCatalog method for improved PEQ state management; refactor LuxsinAPI to streamline PEQ filter updates; replace range input with ThumbOnlyRangeSlider in Home component for better user experience.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import { getFilterShortName } from "@/lib/peqAudio";
|
||||
import {
|
||||
BAND_FREQ_MAX,
|
||||
BAND_FREQ_MIN,
|
||||
BAND_GAIN_MAX,
|
||||
BAND_GAIN_MIN,
|
||||
BAND_Q_MAX,
|
||||
BAND_Q_MIN,
|
||||
} from "./eqConstants";
|
||||
import type { BandParamKind } from "./types";
|
||||
|
||||
export function eqInterp(template: string | undefined, vars: Record<string, string | number>): string {
|
||||
if (!template) return "";
|
||||
let s = template;
|
||||
for (const [k, v] of Object.entries(vars)) {
|
||||
s = s.split(`{{${k}}}`).join(String(v));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
export function formatBandFreqDisplay(freq: number) {
|
||||
return freq >= 1000
|
||||
? `${(freq / 1000).toFixed(2).replace(/\.?0+$/, "")} kHz`
|
||||
: `${freq} Hz`;
|
||||
}
|
||||
|
||||
export function formatBandParamForInput(
|
||||
kind: BandParamKind,
|
||||
band: { freq: number; gain: number; q: number },
|
||||
) {
|
||||
switch (kind) {
|
||||
case "freq":
|
||||
return String(band.freq);
|
||||
case "gain":
|
||||
return band.gain.toFixed(1);
|
||||
case "q":
|
||||
return band.q.toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
export function parseBandParamInput(
|
||||
kind: BandParamKind,
|
||||
raw: string,
|
||||
messages: { invalid: string; outOfRange: string },
|
||||
): { ok: true; value: number } | { ok: false; message: string } {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return { ok: false, message: messages.invalid };
|
||||
|
||||
if (kind === "freq") {
|
||||
let s = trimmed.replace(/\s+/g, "").toLowerCase().replace(/hz$/, "");
|
||||
const kHz = /k(hz)?$/.test(s);
|
||||
if (kHz) s = s.replace(/k(hz)?$/, "");
|
||||
const num = Number.parseFloat(s);
|
||||
if (!Number.isFinite(num)) return { ok: false, message: messages.invalid };
|
||||
const hz = Math.round(kHz ? num * 1000 : num);
|
||||
if (hz < BAND_FREQ_MIN || hz > BAND_FREQ_MAX) {
|
||||
return { ok: false, message: messages.outOfRange };
|
||||
}
|
||||
return { ok: true, value: hz };
|
||||
}
|
||||
|
||||
if (kind === "gain") {
|
||||
const s = trimmed.replace(/\s*dB\s*$/i, "").trim();
|
||||
const num = Number.parseFloat(s);
|
||||
if (!Number.isFinite(num)) return { ok: false, message: messages.invalid };
|
||||
const gain = Number(num.toFixed(1));
|
||||
if (gain < BAND_GAIN_MIN || gain > BAND_GAIN_MAX) {
|
||||
return { ok: false, message: messages.outOfRange };
|
||||
}
|
||||
return { ok: true, value: gain };
|
||||
}
|
||||
|
||||
const num = Number.parseFloat(trimmed);
|
||||
if (!Number.isFinite(num)) return { ok: false, message: messages.invalid };
|
||||
const q = Number(num.toFixed(2));
|
||||
if (q < BAND_Q_MIN || q > BAND_Q_MAX) {
|
||||
return { ok: false, message: messages.outOfRange };
|
||||
}
|
||||
return { ok: true, value: q };
|
||||
}
|
||||
|
||||
export function normalizeFilterType(type: string | number | undefined): string {
|
||||
if (type === undefined || type === null) return "PEAK";
|
||||
if (typeof type === "number") {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return "LPF";
|
||||
case 1:
|
||||
return "HPF";
|
||||
case 2:
|
||||
return "BPF";
|
||||
case 3:
|
||||
return "NOTCH";
|
||||
case 4:
|
||||
return "PEAK";
|
||||
case 5:
|
||||
return "LSHELF";
|
||||
case 6:
|
||||
return "HSHELF";
|
||||
case 7:
|
||||
return "APF";
|
||||
default:
|
||||
return "PEAK";
|
||||
}
|
||||
}
|
||||
return getFilterShortName(type);
|
||||
}
|
||||
|
||||
export function freqLabel(f: number) {
|
||||
return f >= 1000 ? `${(f / 1000).toFixed(1)}K` : `${f}`;
|
||||
}
|
||||
Reference in New Issue
Block a user