feat: add behaviour to hp/lp filters
This commit is contained in:
@@ -13,8 +13,8 @@
|
||||
"windows": [
|
||||
{
|
||||
"title": "thomann-dsp-app",
|
||||
"width": 1200,
|
||||
"height": 800,
|
||||
"width": 1600,
|
||||
"height": 950,
|
||||
"minWidth": 1200,
|
||||
"minHeight": 600
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type VerticalSliderProps = {
|
||||
onChange?: (value: number) => Promise<boolean>;
|
||||
onInput?: (value: number) => void;
|
||||
|
||||
unit?: string;
|
||||
unit?: string | ((value: number) => string);
|
||||
formatValue?: (value: number, decimals: number) => string;
|
||||
|
||||
showTicks?: boolean;
|
||||
@@ -198,6 +198,8 @@ export default function VerticalSlider({
|
||||
|
||||
const formattedValue = (formatValue ?? formatValueDefault)(displayValue, decimals);
|
||||
|
||||
const displayUnit = typeof unit === 'function' ? unit(displayValue) : unit;
|
||||
|
||||
function normalizeValue(input: number) {
|
||||
const clamped = Math.min(max, Math.max(min, input));
|
||||
|
||||
@@ -434,7 +436,7 @@ export default function VerticalSlider({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{unit && <span className="value-unit">{unit}</span>}
|
||||
{displayUnit && <span className="value-unit">{' ' + displayUnit}</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -208,7 +208,7 @@ function GeqSection({
|
||||
}) {
|
||||
const [activeChannel, setActiveChannel] = useState<InputChannel>(INPUT_ORDER[0]);
|
||||
const [liveGeq, setLiveGeq] = useState<Partial<Record<InputChannel, LiveBands>>>({});
|
||||
const [resetting, setResetting] = useState(false); // NEW
|
||||
const [resetting, setResetting] = useState(false);
|
||||
|
||||
const handleLiveValue = (channel: InputChannel, band: DiscreteFrequency, value: number) => {
|
||||
setLiveGeq((prev) => ({
|
||||
@@ -231,7 +231,11 @@ function GeqSection({
|
||||
return success;
|
||||
};
|
||||
|
||||
// NEW: sequential per-band reset, since hardware has no bulk reset command.
|
||||
const handleBypassClick = () => {
|
||||
setGeqBypass(activeChannel, !activeGeq.bypass);
|
||||
};
|
||||
|
||||
// Sequential per-band reset, since hardware has no bulk reset command.
|
||||
const handleReset = async (channel: InputChannel) => {
|
||||
if (resetting) return;
|
||||
setResetting(true);
|
||||
@@ -251,10 +255,6 @@ function GeqSection({
|
||||
const activeGeq = activeInputState.geq;
|
||||
const activeLiveBands = liveGeq[activeChannel];
|
||||
|
||||
const handleBypassClick = () => {
|
||||
setGeqBypass(activeChannel, !activeGeq.bypass);
|
||||
};
|
||||
|
||||
const channelOptions = INPUT_ORDER.map((channel) => ({
|
||||
channel,
|
||||
label: dsp.state.current_config.input_states[channel].name,
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
.crossover-panel {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
aspect-ratio: 0.28;
|
||||
aspect-ratio: 0.3;
|
||||
flex: 0 0 auto;
|
||||
|
||||
display: flex;
|
||||
|
||||
@@ -6,7 +6,7 @@ import VerticalSlider, {
|
||||
// ASSUMPTION: an InputChannel enum exists alongside OutputChannel, mapping
|
||||
// input pages 1-8 similarly (In1 -> 0, In2 -> 1, ...). Adjust import/values
|
||||
// if the actual enum differs.
|
||||
import { InputChannel, Channel, PEQBand, PEQFilter, PEQ, Meter } from '../../types';
|
||||
import { InputChannel, Channel, PEQBand, PEQFilter, PEQ, Meter, Crossover } from '../../types';
|
||||
import { DSP408 as DSP } from '../../../../types';
|
||||
import { CrossoverFilter } from '../../types';
|
||||
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
|
||||
@@ -15,6 +15,15 @@ import './InputSection.css';
|
||||
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
|
||||
import Button from '../../../../components/Button/Button';
|
||||
import MeterBar from '../../../../components/MeterBar/MeterBar';
|
||||
import {
|
||||
FREQUENCY_MAX,
|
||||
FREQUENCY_MIN,
|
||||
FREQUENCY_QUANTIZATION,
|
||||
GRAPH_X_MAX,
|
||||
GRAPH_X_MIN,
|
||||
GRAPH_Y_MAX,
|
||||
GRAPH_Y_MIN,
|
||||
} from '../../constants';
|
||||
|
||||
const PEQ_BANDS: PEQBand[] = [
|
||||
PEQBand.B1,
|
||||
@@ -67,7 +76,7 @@ type SetPEQFn = (
|
||||
|
||||
type PeqParamKey = 'frequency' | 'q' | 'gain';
|
||||
|
||||
type PEQValues = {
|
||||
type PEQValue = {
|
||||
frequency: number;
|
||||
q: number;
|
||||
gain: number;
|
||||
@@ -91,7 +100,7 @@ function PeqPanelSliders({
|
||||
const inputState = dsp.state.current_config.input_states[channel];
|
||||
const peq = inputState.peq_chain.bands[band] as PEQ;
|
||||
|
||||
const commit = (overrides: Partial<PEQValues>) => {
|
||||
const commit = (overrides: Partial<PEQValue>) => {
|
||||
const next = { ...peq, ...overrides };
|
||||
return setPEQ(
|
||||
{ Input: channel },
|
||||
@@ -118,7 +127,7 @@ function PeqPanelSliders({
|
||||
unit={param.unit}
|
||||
value={peq[param.key]}
|
||||
// onInput={(value) => onLiveValue(channel, param.key, value)}
|
||||
onChange={(value) => commit({ [param.key]: value } as Partial<PEQValues>)}
|
||||
onChange={(value) => commit({ [param.key]: value } as Partial<PEQValue>)}
|
||||
style={{ width: '100%', flex: '1 1 auto' }}
|
||||
/>
|
||||
<div className="input-panel__cell-label">{param.label}</div>
|
||||
@@ -129,45 +138,49 @@ function PeqPanelSliders({
|
||||
);
|
||||
}
|
||||
|
||||
const FREQ_MIN = 19.7;
|
||||
const FREQ_MAX = 20160;
|
||||
const FREQ_POINTS = 300;
|
||||
const FREQ_STEP = makeLogStep(FREQ_MIN, FREQ_MAX, FREQ_POINTS);
|
||||
const FREQ_QUANTIZE = makeLogQuantize(FREQ_MIN, FREQ_MAX, FREQ_POINTS);
|
||||
|
||||
function CrossoverPanel({
|
||||
channel,
|
||||
dsp,
|
||||
crossover,
|
||||
title,
|
||||
setCrossover,
|
||||
onLiveValue,
|
||||
}: {
|
||||
channel: Channel;
|
||||
dsp: DSP;
|
||||
crossover: Crossover;
|
||||
title: string;
|
||||
setCrossover: (
|
||||
channel: Channel,
|
||||
frequency: number,
|
||||
filter_type: CrossoverFilter
|
||||
) => Promise<boolean>;
|
||||
setCrossover: (frequency: number, filter_type: CrossoverFilter) => Promise<boolean>;
|
||||
onLiveValue: (value: number) => void;
|
||||
}) {
|
||||
const channelState =
|
||||
'Input' in channel
|
||||
? dsp.state?.current_config.input_states[channel.Input]
|
||||
: dsp.state?.current_config.output_states[channel.Output];
|
||||
const frequency = crossover.frequency;
|
||||
const filter_type = crossover.slope;
|
||||
const bypass = filter_type === CrossoverFilter.Bypass;
|
||||
|
||||
const crossover = channelState?.crossover;
|
||||
const lastFilterType = useRef<CrossoverFilter>(
|
||||
filter_type !== CrossoverFilter.Bypass ? filter_type : CrossoverFilter.Lk24
|
||||
);
|
||||
|
||||
const frequency = crossover.high_pass.frequency;
|
||||
const filter_type = crossover.high_pass.slope;
|
||||
const bypass = false;
|
||||
|
||||
const commit = (overrides: {
|
||||
const commit = async (overrides: {
|
||||
frequency?: number;
|
||||
filter_type?: CrossoverFilter;
|
||||
bypass?: boolean;
|
||||
}) => {
|
||||
const next = { frequency, filter_type, bypass, ...overrides };
|
||||
return setCrossover(channel, next.frequency, next.filter_type);
|
||||
const nextFrequency = overrides.frequency ?? frequency;
|
||||
|
||||
const selectedFilterType =
|
||||
overrides.filter_type !== undefined
|
||||
? overrides.filter_type
|
||||
: bypass
|
||||
? lastFilterType.current
|
||||
: filter_type;
|
||||
|
||||
// Always remember the latest non-bypass selection.
|
||||
if (selectedFilterType !== CrossoverFilter.Bypass) {
|
||||
lastFilterType.current = selectedFilterType;
|
||||
}
|
||||
|
||||
const nextBypass = overrides.bypass ?? bypass;
|
||||
|
||||
const nextFilterType = nextBypass ? CrossoverFilter.Bypass : selectedFilterType;
|
||||
|
||||
return setCrossover(nextFrequency, nextFilterType);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -175,20 +188,24 @@ function CrossoverPanel({
|
||||
<div className="crossover-panel__title">{title}</div>
|
||||
|
||||
<VerticalSlider
|
||||
min={FREQ_MIN}
|
||||
max={FREQ_MAX}
|
||||
min={FREQUENCY_MIN}
|
||||
max={FREQUENCY_MAX}
|
||||
scale="log"
|
||||
step={FREQ_STEP}
|
||||
quantize={FREQ_QUANTIZE}
|
||||
unit=" Hz"
|
||||
step={makeLogStep(FREQUENCY_MIN, FREQUENCY_MAX, FREQUENCY_QUANTIZATION)}
|
||||
quantize={makeLogQuantize(FREQUENCY_MIN, FREQUENCY_MAX, FREQUENCY_QUANTIZATION)}
|
||||
unit={(value) => (value >= 1000 ? 'kHz' : 'Hz')}
|
||||
value={frequency}
|
||||
formatValue={(value) =>
|
||||
value >= 1000 ? `${(value / 1000).toFixed(2)}` : `${Math.round(value)}`
|
||||
}
|
||||
onChange={(value) => commit({ frequency: value })}
|
||||
onInput={(value) => onLiveValue(value)}
|
||||
style={{ width: '100%', flex: '1 1 auto' }}
|
||||
/>
|
||||
|
||||
<select
|
||||
className="crossover-panel__select"
|
||||
value={filter_type}
|
||||
value={bypass ? lastFilterType.current : filter_type}
|
||||
onChange={(e) => commit({ filter_type: e.target.value as CrossoverFilter })}
|
||||
>
|
||||
{FILTER_TYPE_OPTIONS.map((opt) => (
|
||||
@@ -233,7 +250,7 @@ function PeqBandList({
|
||||
}) {
|
||||
const inputState = dsp.state.current_config.input_states[channel];
|
||||
|
||||
const commit = (band: PEQBand, overrides: Partial<PEQValues>) => {
|
||||
const commit = (band: PEQBand, overrides: Partial<PEQValue>) => {
|
||||
const peq = inputState.peq_chain.bands[band] as PEQ;
|
||||
const next = { ...peq, ...overrides };
|
||||
return setPEQ(
|
||||
@@ -364,76 +381,88 @@ function InputSection({
|
||||
setPeq: setPeqBandFn;
|
||||
setPeqBypass: (channel: Channel, bypass: boolean) => Promise<boolean>;
|
||||
}) {
|
||||
// UI variables
|
||||
const [activeBand, setActiveBand] = useState<PEQBand>(PEQBand.B1);
|
||||
|
||||
const [liveHpFreq, setLiveHpFreq] = useState<number>(19.7);
|
||||
const [liveLpFreq, setLiveLpFreq] = useState<number>(20.16);
|
||||
const [livePeq, setLivePeq] = useState<Partial<Record<PEQBand, PEQValues>>>({});
|
||||
// Live values
|
||||
const [liveHpFreq, setLiveHpFreq] = useState<number>(FREQUENCY_MIN);
|
||||
const [liveLpFreq, setLiveLpFreq] = useState<number>(FREQUENCY_MAX);
|
||||
const [livePeq, setLivePeq] = useState<Partial<Record<PEQBand, PEQValue>>>({});
|
||||
|
||||
const inputState = dsp.state.current_config.input_states[channel];
|
||||
// DSP values
|
||||
const activeInputState = dsp.state.current_config.input_states[channel];
|
||||
const ActiveHighPassFilter = activeInputState.crossover.high_pass;
|
||||
const ActiveLowPassFilter = activeInputState.crossover.low_pass;
|
||||
const ActivePeq = activeInputState.peq_chain;
|
||||
|
||||
const hp = inputState.crossover.high_pass;
|
||||
const lp = inputState.crossover.low_pass;
|
||||
const activePeq = livePeq[activeBand] ?? (inputState.peq_chain.bands[activeBand] as PEQValues);
|
||||
// Live handlers
|
||||
const handleLiveHighPassValue = (value: number) => {
|
||||
setLiveHpFreq(value);
|
||||
};
|
||||
|
||||
const bypassed = hp.slope === CrossoverFilter.Bypass;
|
||||
const activeFilterType = bypassed && lp.slope !== CrossoverFilter.Bypass ? lp.slope : hp.slope;
|
||||
const handleLiveLowPassValue = (value: number) => {
|
||||
setLiveLpFreq(value);
|
||||
};
|
||||
|
||||
// Remembers the last non-bypass slope so the Bypass button can restore it.
|
||||
// const lastNonBypassType = useRef<CrossoverFilter>(
|
||||
// activeFilterType === CrossoverFilter.Bypass ? DEFAULT_FILTER_TYPE : activeFilterType
|
||||
// );
|
||||
// if (activeFilterType !== CrossoverFilter.Bypass) {
|
||||
// lastNonBypassType.current = activeFilterType;
|
||||
// }
|
||||
const handleLivePEQValue = (band: PEQBand, value: PEQValue) => {
|
||||
setLivePeq((prev) => ({
|
||||
...prev,
|
||||
[band]: value,
|
||||
}));
|
||||
};
|
||||
|
||||
const hpFreq = liveHpFreq ?? hp.frequency;
|
||||
const lpFreq = liveLpFreq ?? lp.frequency;
|
||||
// Real dsp value handlers
|
||||
const commitHighPass = async (freq: number, filterType: CrossoverFilter) => {
|
||||
const success = await setHighPass({ Input: channel }, freq, filterType);
|
||||
if (success) {
|
||||
setLiveHpFreq(freq);
|
||||
}
|
||||
return success;
|
||||
};
|
||||
|
||||
// const commitHighPass = async (freq: number, filterType: CrossoverFilter) => {
|
||||
// const success = await set_high_pass({ Input: channel }, freq, filterType);
|
||||
// if (success) setLiveHpFreq(null);
|
||||
// return success;
|
||||
// };
|
||||
const commitLowPass = async (freq: number, filterType: CrossoverFilter) => {
|
||||
const success = await setLowPass({ Input: channel }, freq, filterType);
|
||||
if (success) {
|
||||
setLiveLpFreq(freq);
|
||||
}
|
||||
return success;
|
||||
};
|
||||
|
||||
// const commitLowPass = async (freq: number, filterType: CrossoverFilter) => {
|
||||
// const success = await set_low_pass({ Input: channel }, freq, filterType);
|
||||
// if (success) setLiveLpFreq(null);
|
||||
// return success;
|
||||
// };
|
||||
|
||||
// const handleFilterTypeChange = (filterType: CrossoverFilter) => {
|
||||
// // Applying a slope change always takes the crossover out of bypass.
|
||||
// void commitHighPass(hpFreq, filterType);
|
||||
// void commitLowPass(lpFreq, filterType);
|
||||
// };
|
||||
|
||||
// const handleBypassToggle = () => {
|
||||
// if (bypassed) {
|
||||
// const restore = lastNonBypassType.current;
|
||||
// void commitHighPass(hpFreq, restore);
|
||||
// void commitLowPass(lpFreq, restore);
|
||||
// } else {
|
||||
// void commitHighPass(hpFreq, CrossoverFilter.Bypass);
|
||||
// void commitLowPass(lpFreq, CrossoverFilter.Bypass);
|
||||
// }
|
||||
// };
|
||||
const commitPEQ = async (
|
||||
band: PEQBand,
|
||||
gain: number,
|
||||
frequency: number,
|
||||
q: number,
|
||||
filter_type: PEQFilter,
|
||||
bypass: boolean
|
||||
) => {
|
||||
const success = await setPeq({ Input: channel }, band, gain, frequency, q, filter_type, bypass);
|
||||
if (success) {
|
||||
setLivePeq((prev) => {
|
||||
const channelLive = prev[band];
|
||||
if (!channelLive || !(band in channelLive)) return prev;
|
||||
const next = { ...channelLive };
|
||||
return { ...prev, [channel]: next };
|
||||
});
|
||||
}
|
||||
return success;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="input-graph-section">
|
||||
<div className="input-graph-panel">
|
||||
<div className="input-graph__title">{inputState.name} - Filters</div>
|
||||
|
||||
{/* TODO: draw HP/LP transfer curves here once filter math is defined,
|
||||
same pattern as LimiterSection's `draw` prop. */}
|
||||
<div className="input-graph__title">{activeInputState.name} - Filters</div>
|
||||
<LinearGraph
|
||||
xMin={20}
|
||||
xMax={20000}
|
||||
yMin={-30}
|
||||
yMax={6}
|
||||
xMin={GRAPH_X_MIN}
|
||||
xMax={GRAPH_X_MAX}
|
||||
xScale="log"
|
||||
yMin={GRAPH_Y_MIN}
|
||||
yMax={GRAPH_Y_MAX}
|
||||
yStep={3}
|
||||
xLabel="Hz"
|
||||
yLabel="dB"
|
||||
showGrid={true}
|
||||
formatX={(v) => Math.round(v).toString()}
|
||||
formatY={(v) => Math.round(v).toString()}
|
||||
draw={() => {}}
|
||||
@@ -456,76 +485,18 @@ function InputSection({
|
||||
|
||||
<ChannelGroup title="CrossOver">
|
||||
<CrossoverPanel
|
||||
channel={{ Input: channel }}
|
||||
dsp={dsp}
|
||||
crossover={ActiveLowPassFilter}
|
||||
title="LowPass"
|
||||
setCrossover={setHighPass}
|
||||
setCrossover={commitLowPass}
|
||||
onLiveValue={handleLiveLowPassValue}
|
||||
/>
|
||||
<CrossoverPanel
|
||||
channel={{ Input: channel }}
|
||||
dsp={dsp}
|
||||
crossover={ActiveHighPassFilter}
|
||||
title="HighPass"
|
||||
setCrossover={setHighPass}
|
||||
setCrossover={commitHighPass}
|
||||
onLiveValue={handleLiveHighPassValue}
|
||||
/>
|
||||
</ChannelGroup>
|
||||
{/* <div className="input-control-panel__sliders">
|
||||
<div className="input-control-panel__cell input-control-panel__cell--high-pass">
|
||||
<VerticalSlider
|
||||
min={FREQ_MIN}
|
||||
max={FREQ_MAX}
|
||||
step={FREQ_STEP}
|
||||
unit=" Hz"
|
||||
value={hpFreq}
|
||||
// disabled={bypassed}
|
||||
onInput={(value) => setLiveHpFreq(value)}
|
||||
onChange={(value) => commitHighPass(value, activeFilterType)}
|
||||
style={{ width: '100%', flex: '1 1 auto' }}
|
||||
/>
|
||||
<div className="input-control-panel__cell-label">High Pass</div>
|
||||
</div>
|
||||
|
||||
<div className="input-control-panel__cell input-control-panel__cell--low-pass">
|
||||
<VerticalSlider
|
||||
min={FREQ_MIN}
|
||||
max={FREQ_MAX}
|
||||
step={FREQ_STEP}
|
||||
unit=" Hz"
|
||||
value={lpFreq}
|
||||
// disabled={bypassed}
|
||||
onInput={(value) => setLiveLpFreq(value)}
|
||||
onChange={(value) => commitLowPass(value, activeFilterType)}
|
||||
style={{ width: '100%', flex: '1 1 auto' }}
|
||||
/>
|
||||
<div className="input-control-panel__cell-label">Low Pass</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="input-control-panel__side">
|
||||
<label className="input-control-panel__select">
|
||||
<span className="input-control-panel__select-label">Filter Type</span>
|
||||
<select
|
||||
value={activeFilterType}
|
||||
disabled={bypassed}
|
||||
onChange={(e) => handleFilterTypeChange(e.target.value as CrossoverFilter)}
|
||||
>
|
||||
{FILTER_TYPE_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className={`input-control-panel__bypass-btn${
|
||||
bypassed ? ' input-control-panel__bypass-btn--active' : ''
|
||||
}`}
|
||||
onClick={handleBypassToggle}
|
||||
>
|
||||
{bypassed ? 'Bypassed' : 'Bypass'}
|
||||
</button>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -93,6 +93,11 @@ export const GEQ_GAIN_MIN = -12;
|
||||
export const GEQ_GAIN_MAX = 12;
|
||||
export const GEQ_GAIN_STEP = 0.1;
|
||||
|
||||
// ------ Filter constants ------
|
||||
export const FREQUENCY_MIN = 19.7;
|
||||
export const FREQUENCY_MAX = 20160;
|
||||
export const FREQUENCY_QUANTIZATION = 300;
|
||||
|
||||
// ------ Matrix constants ------
|
||||
export const MATRIX_GAIN_MIN = -60;
|
||||
export const MATRIX_GAIN_MAX = 0;
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
PEQFilter,
|
||||
PEQBand,
|
||||
InputSource,
|
||||
Crossover,
|
||||
} from './types';
|
||||
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from '../../dsp/dspShared';
|
||||
import { registerPollStopper } from '../../dsp/pollRegistry';
|
||||
@@ -1144,9 +1145,10 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
if (!d.state) return d;
|
||||
|
||||
const cfg = d.state.current_config;
|
||||
const lowPass = {
|
||||
|
||||
const lowPass: Crossover = {
|
||||
frequency: freq,
|
||||
filter_type: filterType,
|
||||
slope: filterType,
|
||||
};
|
||||
|
||||
if ('Input' in channel) {
|
||||
@@ -1160,11 +1162,14 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
...cfg.input_states,
|
||||
[channel.Input]: {
|
||||
...cfg.input_states[channel.Input],
|
||||
crossover: {
|
||||
...cfg.input_states[channel.Input].crossover,
|
||||
low_pass: lowPass,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1178,11 +1183,14 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
...cfg.output_states,
|
||||
[channel.Output]: {
|
||||
...cfg.output_states[channel.Output],
|
||||
crossover: {
|
||||
...cfg.output_states[channel.Output].crossover,
|
||||
low_pass: lowPass,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -1227,9 +1235,10 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
if (!d.state) return d;
|
||||
|
||||
const cfg = d.state.current_config;
|
||||
const highPass = {
|
||||
|
||||
const highPass: Crossover = {
|
||||
frequency: freq,
|
||||
filter_type: filterType,
|
||||
slope: filterType,
|
||||
};
|
||||
|
||||
if ('Input' in channel) {
|
||||
@@ -1243,11 +1252,14 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
...cfg.input_states,
|
||||
[channel.Input]: {
|
||||
...cfg.input_states[channel.Input],
|
||||
crossover: {
|
||||
...cfg.input_states[channel.Input].crossover,
|
||||
high_pass: highPass,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1261,11 +1273,14 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
||||
...cfg.output_states,
|
||||
[channel.Output]: {
|
||||
...cfg.output_states[channel.Output],
|
||||
crossover: {
|
||||
...cfg.output_states[channel.Output].crossover,
|
||||
high_pass: highPass,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user