1import { useMemo } from 'react'
2import katex from 'katex'
4function Display({ tex }: { tex: string }) {
5 const html = useMemo(() => katex.renderToString(tex, { displayMode: true, throwOnError: false }), [tex])
6 return <div dangerouslySetInnerHTML={{ __html: html }} />
7}
9/**
10 * Stub for the full derivation. It states the model and the formula the app
11 * plots; the reasoning connecting them is to come.
12 */
13export default function MathSection() {
14 return (
15 <div className="math-section">
16 <p>
17 The generating model: i.i.d. Gaussian noise, a FIR filter h, optional uniform dither, and
18 rounding to the integer quantization grid (the step is the unit, so σ is measured in
19 steps):
20 </p>
21 <Display tex="x_n \sim \mathcal{N}(0,\sigma^2)\ \text{i.i.d.}, \qquad y = h * x, \qquad z_n = \operatorname{round}(y_n + d_n), \quad d_n \sim \mathcal{U}[-\tfrac12,\tfrac12)\ \text{or}\ 0" />
22 <p>
23 The dashed reference line is the entropy rate of the stationary Gaussian process y,
24 quantized at unit step, in the fine-quantization (high-resolution) limit — the ideal
25 lossless rate in bits per sample:
26 </p>
27 <Display tex="R \;=\; \tfrac12\log_2(2\pi e)\;+\;\int_0^{1/2} \log_2 S(f)\,df, \qquad S(f) = \sigma^2\,|H(f)|^2" />
28 <p>
29 with f in cycles per sample. With no filter this reduces to ½ log₂(2πe σ²). The formula
30 holds when S(f) is well above one step² across the band; where the response dips toward or
31 below the quantization step — deep stopbands, small σ — the true entropy rate is larger
32 than R (and R can even go negative), and no fixed-order predictor fully whitens the
33 process. Quantifying that gap, the effect of dither, and why LPC + ANS is the right
34 yardstick is the subject of the full derivation, still to be written.
35 </p>
36 </div>
37 )
38}