diff --git a/src/components/LinearGraph/LinearGraph.tsx b/src/components/LinearGraph/LinearGraph.tsx index 9c877b7..509c94b 100644 --- a/src/components/LinearGraph/LinearGraph.tsx +++ b/src/components/LinearGraph/LinearGraph.tsx @@ -33,7 +33,7 @@ export interface LinearGraphProps { yMin: number; yMax: number; yStep?: number; - /** 'log' requires xMin > 0. Ticks are drawn at 1/2/5-per-decade mantissas, with decade (power-of-10) lines highlighted. */ + /** 'log' requires xMin > 0. */ xScale?: AxisScale; /** 'log' requires yMin > 0. */ yScale?: AxisScale; @@ -150,7 +150,7 @@ export const LinearGraph = forwardRef(funct const topBase = cq.h * 3; const rightBase = cq.w * 5; const bottomBase = cq.h * 4; - const leftBase = cq.w * 2; + const leftBase = cq.w * 7; const xLabelSpace = xLabel ? cq.h * 7 : 0; const yLabelSpace = yLabel ? Math.min(cq.w * 6, 24) : 0; @@ -221,7 +221,7 @@ export const LinearGraph = forwardRef(funct ctx.clearRect(0, 0, cssW, cssH); const plot = { - x: pad.left + cq.w * 2, + x: pad.left, y: pad.top, width: Math.max(1, cssW - pad.left - pad.right - cq.w * 2), height: Math.max(1, cssH - pad.top - pad.bottom), @@ -271,14 +271,14 @@ export const LinearGraph = forwardRef(funct ctx.fillRect(plot.x, plot.y, plot.width, plot.height); } - const clipPad = 2; + const borderInset = 1; // Avoid clipping outside graph bounds ctx.save(); ctx.beginPath(); ctx.rect( - plot.x - clipPad, - plot.y - clipPad, - plot.width + clipPad * 2, - plot.height + clipPad * 2 + plot.x + borderInset, + plot.y + borderInset, + plot.width - borderInset * 2, + plot.height - borderInset * 2 ); ctx.clip(); diff --git a/src/features/dsp408/components/GainSection/GainSection.tsx b/src/features/dsp408/components/GainSection/GainSection.tsx index 1181a9a..1e083d2 100644 --- a/src/features/dsp408/components/GainSection/GainSection.tsx +++ b/src/features/dsp408/components/GainSection/GainSection.tsx @@ -413,7 +413,7 @@ function GainSection({ const { yMin: inputYMin, yMax: inputYMax } = computeYAxisBounds( inputCurves, GRAPH_Y_MIN, - GRAPH_Y_MAX, + 12, Y_AXIS_STEP ); const { yMin: outputYMin, yMax: outputYMax } = computeYAxisBounds( @@ -457,7 +457,18 @@ function GainSection({ yLabel="dB" showGrid={true} formatX={(v) => Math.round(v).toString()} - formatY={(v) => Math.round(v).toString()} + formatY={(v) => { + // Always label 0. + if (v === 0) return '0'; + + // Positive side: label every 12 dB. + if (v > 0) { + return v % 12 === 0 ? `+${Math.round(v)}` : ''; + } + + // Negative side: label every 15 dB. + return Math.abs(v) % 15 === 0 ? Math.round(v).toString() : ''; + }} draw={({ ctx, toPx }) => { drawCurves({ ctx, diff --git a/src/features/dsp408/constants.ts b/src/features/dsp408/constants.ts index 13b0c97..2af5fe1 100644 --- a/src/features/dsp408/constants.ts +++ b/src/features/dsp408/constants.ts @@ -179,8 +179,16 @@ export const DELAY_RANGES: Record = { }; // ------ Graph constants ------ -export const GRAPH_X_MIN = 14; -export const GRAPH_X_MAX = 27000; +const REAL_X_MIN = 20; +const REAL_X_MAX = 20000; +const X_LOG_PADDING = 0.05; + +const logMin = Math.log10(REAL_X_MIN); +const logMax = Math.log10(REAL_X_MAX); +const logRange = logMax - logMin; + +export const GRAPH_X_MIN = Math.floor(Math.pow(10, logMin - logRange * X_LOG_PADDING)); +export const GRAPH_X_MAX = Math.ceil(Math.pow(10, logMax + logRange * X_LOG_PADDING)); export const GRAPH_Y_MIN = -21; export const GRAPH_Y_MAX = 21;