Resample a tone by a rational factor L/M in the sandbox, and predict — before you read it off the screen — the reduced rate factor the two sampling rates give, the new sample count, the anti-alias cutoff, and which interpolation kernel reconstructs the waveform best.
Rational resampling changes the sample rate by L/M: upsample by L, filter, then downsample by M. The factor reduces by the gcd of the two rates — 48000 to 44100 is 147/160, not the raw 48000/44100. The new record has round(N·L/M) samples, and one lowpass at f_c = min(f_s, f_s')/2 does both jobs: it rejects the images upsampling creates and band-limits before downsampling. Downsample without that anti-alias filter and any tone above f_s'/2 folds back as an alias you can never remove. And the kernel matters: a windowed-sinc — the ideal lowpass — beats linear, which beats a zero-order hold.
Open the sandbox. It opens on exactly this state — a 6000 Hz tone resampled from 48000 Hz to 44100 Hz with a windowed-sinc kernel and the anti-alias filter on — so a Reset gets you here too. Each step names the one knob to change; leave everything else alone.
Signal -> Tone f0 -> 6000 Hz N -> 40
Rates -> 48000 -> 44100 Kernel -> windowed-sinc Anti-alias -> on
Watch the L/M readout, the output-length readout, the cutoff readout and the RMS-error readout — every number you predict is printed there.
Keep the defaults: input 48000 Hz, target 44100 Hz. The resampler needs the ratio in lowest terms — divide both rates by their gcd. Predict L and M, then read the L/M readout.
The rate factor is L/M = 147/160 — 48000 and 44100 share gcd = 300, so L = 44100/300 = 147 and M = 48000/300 = 160, not the raw 48000/44100.
Now switch to a clean 2× upsample: set the input rate to 8000 Hz and the target to 16000 Hz, so L/M = 2/1, and set the input length to N = 100. The output has round(N·L/M) samples. Predict it, then read the output-length readout.
The output has N' = round(100 · 2/1) = 200 samples — exactly twice the input, because upsampling by 2 inserts a new sample between every pair. A non-integer factor would round; 2/1 is exact.
Set the rates back to 48000 → 44100 (Reset does this). One lowpass has to protect the lower of the two Nyquist limits — f_c = min(f_s, f_s')/2. Predict the cutoff in hertz, then read the cutoff readout. Then toggle the anti-alias filter off while downsampling: a tone above f_s'/2 folds back as an alias.
The cutoff is f_c = min(48000, 44100)/2 = 22050 Hz — the output Nyquist, the lower of the two. With the filter off while downsampling, any energy above 22050 Hz folds back into the band as an alias you cannot remove afterwards.
Reset, then raise the tone to f0 = 20000 Hz — close to the 22050 Hz Nyquist, where a kernel is tested hardest. Compare the RMS reconstruction error by switching the kernel between windowed-sinc, linear and zero-order hold. Predict the ranking — which is smallest — then read the RMS-error readout for each.
Linear interpolation leaves an RMS error near 0.418, while the windowed-sinc leaves about 0.0087 — roughly 48x smaller — and the zero-order hold is worst at about 0.69. The ranking is sinc < linear < ZOH: the windowed-sinc is the ideal lowpass, so it alone reconstructs a near-Nyquist tone faithfully.
Everything above is waiting in the sandbox. Sweep the input and target rates to watch L/M reduce and the output length track it, drag the tone up toward Nyquist and switch the kernel to watch the reconstruction error climb or fall, and toggle the anti-alias filter off while downsampling to see a high tone fold back into the band as an alias.
- Reduced 48000/44100 to its lowest terms, L/M = 147/160
- Found the new sample count of a 2× upsample, round(100·2/1) = 200
- Read the anti-alias cutoff f_c = min(48000, 44100)/2 = 22050 Hz, and saw a tone alias when you switched the filter off
- Ranked the kernels — windowed-sinc (~0.0087) < linear (~0.418) < ZOH (~0.69) — on a near-Nyquist tone
- Every value you predicted is the demo's own resampling arithmetic, not a picture