1import { useMemo } from 'react'
2import katex from 'katex'
4function Tex({ tex, display }: { tex: string; display?: boolean }) {
5 const html = useMemo(
6 () => katex.renderToString(tex, { displayMode: !!display, throwOnError: false }),
7 [tex, display],
8 )
9 return <span dangerouslySetInnerHTML={{ __html: html }} />
10}
12/** One term of the formula: the symbol, then what it is. */
13function Def({ tex, children }: { tex: string; children: React.ReactNode }) {
14 return (
15 <>
16 <dt>
17 <Tex tex={tex} />
18 </dt>
19 <dd>{children}</dd>
20 </>
21 )
22}
24/**
25 * The theoretical rate R exactly as `model/theory.ts` computes it, with every
26 * symbol defined, followed by a sketch of the derivation: the dither identity,
27 * the per-mode count with the noise at full variance, and the subadditivity
28 * ceiling that takes over below threshold.
29 */
30export default function MathSection() {
31 return (
32 <div className="math-section">
33 <p>
34 The dashed line on the compression chart is R, the predicted bits per sample — the
35 smaller of a spectral estimate and a rigorous one-sample ceiling:
36 </p>
38 <Tex display tex="R \;=\; \min\big(R_{\mathrm{spec}},\, R_{\mathrm{samp}}\big)" />
39 <Tex display tex="R_{\mathrm{spec}} \;=\; \int_0^1 \tfrac{1}{2}\log_2\!\big(2\pi e\,(S(f) + \nu)\big)\, df, \qquad S(f) \;=\; \sigma^2\,\big|H(f)\big|^2" />
40 <Tex display tex="R_{\mathrm{samp}} \;=\; H\big(\operatorname{round}(\mathcal N(0, v) \,[+\, U(-\tfrac12,\tfrac12)\ \text{with dither}])\big), \qquad v \;=\; \sigma^2 \textstyle\sum_m h_m^2" />
42 <dl className="defs">
43 <Def tex="\sigma">
44 standard deviation of the i.i.d. Gaussian input, in quantization steps (the step is the
45 unit, so rounding is to the nearest integer)
46 </Def>
47 <Def tex="h_0,\dots,h_{L-1}">
48 the FIR kernel the input is convolved with — the taps drawn in the kernel plot, L of
49 them
50 </Def>
51 <Def tex="H(f)">
52 the kernel's frequency response, the quantity plotted in dB as |H(f)|; f is in cycles
53 per sample, symmetric about ½ (Nyquist), and the plots label the same axis in Hz
54 </Def>
55 <Def tex="S(f)">
56 power spectrum of the filtered signal alone, in steps² per unit frequency — the dither
57 is <em>not</em> folded in here
58 </Def>
59 <Def tex="\nu">
60 variance charged to the rounding: 1/12 for the roundoff, 1/6 with dither (the dither's
61 own 1/12 is stored in the integers and adds)
62 </Def>
63 <Def tex="v">
64 variance of a single output sample, the integral of S(f)
65 </Def>
66 <Def tex="R">
67 bits per sample; the compression ratio the chart marks is 16/R, against 16-bit integer
68 storage
69 </Def>
70 </dl>
72 <h3>The spectral branch</h3>
73 <p>
74 The <em>dither identity</em> starts it off: for z = round(y) and u an independent
75 uniform on [-½, ½)<sup>N</sup>, the discrete entropy of z equals the differential
76 entropy of z + u, exactly. When the process is live on the unit-cell scale (v ≳ ¼),
77 z + u has nearly the law of y + u, so R is the entropy rate of the signal plus a white
78 unit-cell noise — the Zamir–Feder universal-quantization rate; with physical dither the
79 smoothing noise is d + u and ν doubles to 1/6.
80 </p>
81 <p>
82 Counting that entropy per Fourier mode, the signal modes are independent Gaussians of
83 variance S(f), and each mode of the i.i.d. cube noise mixes all N samples'
84 contributions — so the central limit theorem Gaussianizes it, and it enters at its{' '}
85 <em>full variance</em> ν. It does not enter at the entropy power 1/(2πe) that a scalar
86 quantizer aligned with the mode would charge: the quantization lattice lives in the
87 sample basis, and only for the trivial kernel do modes and quantizers align. (An earlier
88 version of this app charged entropy power — additive constant 1 instead of 2πe·ν ≈ 1.42
89 — and systematically underestimated the measured rate by up to ~0.23 bits/sample. Its
90 "exact per-mode" refinement was worse still: it modeled the wrong physics more
91 faithfully.) One consequence worth naming: a dead band inside a live process contributes
92 ½log₂(2πe/12) ≈ 0.25 bits per mode, not zero.
93 </p>
95 <h3>The sub-threshold ceiling</h3>
96 <p>
97 When v ≪ 1 nearly every sample rounds to zero and the true rate collapses
98 exponentially, while R<sub>spec</sub> bottoms out at ½log₂(2πe ν) > 0. Subadditivity
99 rescues the estimate rigorously: H(z) ≤ Σ<sub>n</sub> H(z<sub>n</sub>), and each stored
100 sample is exactly round(N(0, v)) — plus the uniform dither first when it is on — so
101 R<sub>samp</sub> is a true upper bound on the rate with exactly the right collapse. The
102 min selects it precisely where the spectral branch fails.
103 </p>
105 <h3>Checks and accuracy</h3>
106 <p>
107 For the identity kernel the two branches agree with the exact i.i.d. entropy at every σ
108 (both carry the Fisher correction log₂e/(24σ²) at large σ; below one step the min
109 switches to the exact R<sub>samp</sub>). At high SNR, R<sub>spec</sub> →
110 ½log₂(2πe σ²) + ∫log₂|H| df — the Kolmogorov formula. What the spectral branch ignores
111 is the cross-mode dependence of the cube noise, at most ½log₂(2πe/12) ≈ 0.2546
112 bits/sample and recoverable only when nearly the whole spectrum is noise-dominated;
113 Monte-Carlo puts the estimate within ~0.01–0.02 bits/sample for v ≳ 0.25, with the
114 worst observed error ~+0.03 near the crossover between branches, slightly positive
115 everywhere — as befits a formula whose sample branch is a genuine bound.
116 </p>
118 <p className="card-note">
119 The integral is evaluated by the midpoint rule on 8192 points over [0, ½] (symmetry
120 supplies the other half). R<sub>samp</sub> sums the exact bin probabilities of the
121 rounded Gaussian — integrated against the triangular dither-overlap window when dither
122 is on. The Monte-Carlo command under the chart estimates the true entropy rate of the
123 same process, for checking R where the approximations are in doubt.
124 </p>
125 </div>
126 )
127}