import { useState } from "react" import { useTranslation } from "react-i18next" import { Slider } from "@/components/ui/slider" import { cn } from "@/lib/utils" interface EQBand { frequency: number gain: number q: number type: BiquadFilterType } interface EqualizerProps { onBandChange?: (bandIndex: number, band: EQBand) => void className?: string } const DEFAULT_BANDS: EQBand[] = [ { frequency: 60, gain: 0, q: 0.7, type: "highshelf" }, { frequency: 150, gain: 0, q: 0.7, type: "peaking" }, { frequency: 400, gain: 0, q: 0.7, type: "peaking" }, { frequency: 1000, gain: 0, q: 0.7, type: "peaking" }, { frequency: 3000, gain: 0, q: 0.7, type: "peaking" }, { frequency: 8000, gain: 0, q: 0.7, type: "peaking" }, { frequency: 12000, gain: 0, q: 0.7, type: "lowshelf" }, ] function formatFrequency(freq: number): string { if (freq >= 1000) { return `${(freq / 1000).toFixed(1)}k` } return `${freq}` } export function Equalizer({ onBandChange, className }: EqualizerProps) { const { t } = useTranslation() const [bands, setBands] = useState(DEFAULT_BANDS) const [selectedBand, setSelectedBand] = useState(null) const handleGainChange = (bandIndex: number, gain: number) => { const newBands = [...bands] newBands[bandIndex] = { ...newBands[bandIndex], gain } setBands(newBands) onBandChange?.(bandIndex, newBands[bandIndex]) } const handleFrequencyChange = (bandIndex: number, frequency: number) => { const newBands = [...bands] newBands[bandIndex] = { ...newBands[bandIndex], frequency } setBands(newBands) onBandChange?.(bandIndex, newBands[bandIndex]) } const handleQChange = (bandIndex: number, q: number) => { const newBands = [...bands] newBands[bandIndex] = { ...newBands[bandIndex], q } setBands(newBands) onBandChange?.(bandIndex, newBands[bandIndex]) } const resetBand = (bandIndex: number) => { const newBands = [...bands] newBands[bandIndex] = { ...DEFAULT_BANDS[bandIndex] } setBands(newBands) onBandChange?.(bandIndex, newBands[bandIndex]) } const resetAll = () => { setBands([...DEFAULT_BANDS]) DEFAULT_BANDS.forEach((band, index) => { onBandChange?.(index, band) }) } return (

{t("fairlightAudio.effects.equalizer.title")}

{/* EQ Display */}
{/* Grid lines */} {/* Horizontal lines (gain) */} {[-12, -6, 0, 6, 12].map((db) => { const y = 50 - (db / 24) * 100 return ( ) })} {/* Vertical lines (frequency) */} {[100, 1000, 10000].map((freq, i) => { const x = (i + 1) * 25 return ( ) })} {/* EQ curve */} {/* Band points */} {bands.map((band, index) => { const x = frequencyToX(band.frequency) const y = gainToY(band.gain) return ( setSelectedBand(index)} /> ) })}
{/* Band controls */}
{bands.map((band, index) => (
{/* Frequency label */}
setSelectedBand(index)}> {formatFrequency(band.frequency)}
{/* Gain slider */}
handleGainChange(index, value)} min={-12} max={12} step={0.5} className="h-full" />
{/* Gain value */}
{band.gain > 0 ? "+" : ""} {band.gain.toFixed(1)}
))}
{/* Selected band controls */} {selectedBand !== null && (
{t("fairlightAudio.effects.equalizer.band")} {selectedBand + 1} -{" "} {formatFrequency(bands[selectedBand].frequency)}Hz
{/* Frequency control */}
{t("fairlightAudio.effects.equalizer.frequency")} handleFrequencyChange(selectedBand, 10 ** value)} min={Math.log10(20)} max={Math.log10(20000)} step={0.01} className="flex-1" /> {formatFrequency(bands[selectedBand].frequency)}
{/* Q control */}
{t("fairlightAudio.effects.equalizer.quality")} handleQChange(selectedBand, value)} min={0.1} max={10} step={0.1} className="flex-1" /> {bands[selectedBand].q.toFixed(1)}
)}
) } // Helper functions for visualization function frequencyToX(freq: number): number { // Logarithmic scale from 20Hz to 20kHz const minLog = Math.log10(20) const maxLog = Math.log10(20000) const freqLog = Math.log10(freq) return ((freqLog - minLog) / (maxLog - minLog)) * 100 } function gainToY(gain: number): number { // Linear scale from -12dB to +12dB return 50 - (gain / 24) * 100 } function generateEQCurve(bands: EQBand[]): string { const points: string[] = [] // Generate curve points for (let x = 0; x <= 100; x += 1) { const freq = 10 ** ((x / 100) * (Math.log10(20000) - Math.log10(20)) + Math.log10(20)) let totalGain = 0 // Sum contributions from all bands bands.forEach((band) => { const distance = Math.abs(Math.log10(freq) - Math.log10(band.frequency)) const influence = Math.exp(-distance * distance * band.q * 2) totalGain += band.gain * influence }) const y = gainToY(totalGain) points.push(`${x},${y}`) } return `M ${points.join(" L ")}` }