import { FAMILY_LABELS, SIGMA_STOPS, TAP_STOPS, WIDTH_STOPS, frequencyStops, maxCutoffHz, nearestStop, type FilterFamily, type FilterSpec, } from '../model/filters' export interface ControlsProps { sigma: number setSigma: (v: number) => void sampleRateHz: number setSampleRateHz: (v: number) => void spec: FilterSpec setSpec: (v: FilterSpec) => void } function formatHz(hz: number): string { return hz >= 1000 ? `${+(hz / 1000).toFixed(1)} kHz` : `${hz} Hz` } /** A slider that moves between the given values rather than a continuum. */ function StopSlider(props: { label: string stops: number[] value: number format: (v: number) => string onChange: (v: number) => void }) { const { stops } = props const snapped = nearestStop(stops, props.value) const index = stops.indexOf(snapped) return (
props.onChange(stops[Number(e.target.value)])} />
) } export default function Controls(p: ControlsProps) { const { spec } = p const freqStops = frequencyStops(maxCutoffHz(p.sampleRateHz)) const sinc = spec.family === 'lowpass' || spec.family === 'bandpass' return (
String(v)} onChange={p.setSigma} />
{spec.family === 'bandpass' && ( f < spec.highHz)} value={spec.lowHz} format={formatHz} onChange={v => p.setSpec({ ...spec, lowHz: v })} /> )} {sinc && ( f > spec.lowHz) : freqStops} value={spec.highHz} format={formatHz} onChange={v => p.setSpec({ ...spec, highHz: v })} /> )} {sinc && ( `${v} taps`} onChange={v => p.setSpec({ ...spec, taps: v })} /> )} {spec.family === 'movingAverage' && ( `${v} samples`} onChange={v => p.setSpec({ ...spec, width: v })} /> )}
) }