Audio samples belong to a clock, not merely to a numbered array
Relate sample counts to physical time, quantify clock drift, and distinguish filtered rate conversion from relabeling, decimation, and offline boundary handling.
On this page
The question for today
What you’ll understand
- Convert sample counts and clock error into durations with explicit units.
- Calculate rational resampling ratios and an unfiltered alias example.
- Explain filter state, fractional phase, and causality requirements for continuous conversion.
A sample rate describes how sample indices map to time. Changing a file header from forty-eight kilohertz to sixteen kilohertz does not convert its waveform correctly; it changes the interpreted duration and pitch. Even devices configured for the same nominal rate can have slightly different physical clocks, gradually filling or emptying a buffer. A reliable speech pipeline therefore tracks sample provenance and clock domains, converts rates with appropriate filtering, and distinguishes an offline convenience function from a stateful low-latency streaming implementation.
Separate nominal rate, measured rate, and transport timestamps
Record the capture device's nominal rate, channel count, sample format, and timestamps tied to a defined clock. Count sample frames separately from interleaved scalar values: one stereo frame contains two channel samples but represents one sampling instant. A consumer that advances at exactly the nominal rate can slowly diverge from a producer whose oscillator is fast or slow. Network arrival variation is another effect; neither a packet timestamp nor a large queue alone tells whether drift came from the source clock, the receiver clock, or scheduling delays.
Clock error is often expressed in parts per million. Multiplying the fractional error by nominal samples per second gives an approximate sample imbalance per second when the consumer follows the nominal clock. Over long sessions, even a small error can cause repeated overflows or underflows if no correction exists. Use timestamp and occupancy trends to estimate rate mismatch, then apply a controlled correction such as asynchronous resampling where appropriate. Arbitrarily deleting individual samples can produce clicks and timing discontinuities instead of preserving a smooth waveform.
Rate conversion filters before discarding information
A rational converter raises the internal sampling grid, applies an appropriate low-pass filter, and selects output samples on the new grid. Downsampling needs suppression of frequencies that would fold into the output band; simply keeping every third sample preserves neither arbitrary high-frequency content nor a clean speech band. Real filters need a transition band, so the useful passband is not an ideal brick wall extending exactly to the new Nyquist frequency. Specify passband ripple, stopband attenuation, and latency for the intended application rather than calling every converter equivalent.
SciPy 1.16.0 documents resample_poly as polyphase conversion with a zero-phase low-pass FIR and explicit boundary-extension choices. That offline interface can center its result and use samples on both sides of an output position. A live causal converter must retain filter history and fractional phase across chunks, and it incurs a delay or a different boundary policy. Calling an offline routine independently on each packet with zero padding invents artificial boundaries. Preserve the continuous stream's conversion state instead of treating transport packet edges as signal endpoints.
Validate time continuity as well as waveform quality
Test long runs with known oscillator mismatch, impulses, tones near the band edge, and varying packet sizes. Compare total emitted sample counts, timestamp mapping, boundary transients, and spectral distortion with a continuous reference. Account for startup and final filter delay rather than silently trimming a different amount on every chunk. Audio format conversion also needs explicit clipping, channel mixing, and integer-to-floating scaling rules. A model that expects mono sixteen-kilohertz input should receive that representation through a verified converter, not through a renamed buffer whose actual clock and layout remain unchanged.
The waves lab illustrates only a consequence of phase mismatch between equal-frequency signals. Reset, explicitly set BOTH phase=0 degrees and amplitude ratio=1, predict resultant amplitude two, then Play or Step. Reset and re-set BOTH phase=180 degrees and ratio=1; predict zero. Edits retain t. This model does not advance independent sample clocks, filter a stream, resample data, or estimate drift. The controlled phase comparison motivates timing care, while the sample-count and rate calculations provide the actual clock accounting for this lesson.
Work it through
Convert rate, identify a possible alias, and count drift
A mono source is nominally 48000 samples/second and is converted to 16000. Consider a hypothetical eighteen-kilohertz tone before filtering. Separately, assume the capture clock is fifty parts per million fast relative to a nominal-rate consumer for sixty seconds.
The rate ratio is 16000/48000=1/3. A nominal one-second input of 48000 sample frames corresponds to 16000 output frames under the stated conversion and boundary convention.
Naively taking every third sample would fold the eighteen-kilohertz tone to |18000−16000|=2000 Hz. An appropriate antialias filter suppresses this unwanted component before rate reduction.
Clock mismatch gives 48000×50×10⁻⁶×60=144 excess input frames, or 144/48000=0.003 seconds. A three-millisecond occupancy drift is different from network packet jitter and requires a clock-aware response.
Rate conversion, alias suppression, and clock-drift correction are connected but distinct responsibilities.
The living notebook
Explore the model
Interactive lab · waves
Timing phase changes how aligned signals combine
For EACH run Reset, set BOTH phase and amplitude ratio, predict, then Play or Step. Ratio 1 with phase 0 degrees has resultant amplitude 2; phase 180 degrees has amplitude 0. Edits retain t. These two equal-frequency analytic waves do not implement sample clocks, drift, antialias filters, or a streaming resampler.
- Sum at x = 0
- 0.866
- Resultant amplitude
- 1.732
- Phase difference
- 60°
Two waves share the same frequency and wave number. Playback advances t in sin(2x − t) + a sin(2x − t + phase). Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA waveform's timing relationship matters; sample-clock and filter continuity still need explicit implementation and tests.
Pause & reason
Check your understanding
Your turn
Try it yourself
Convert a nominal two-second 44100-Hz stream to 16000 Hz. Give the reduced rational ratio and nominal output count. A sixteen-kilohertz producer then runs one hundred ppm fast for a minute against a nominal consumer; calculate excess frames and duration.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Reduce 16000/44100, then apply the fractional drift to samples per second and elapsed seconds.
Compare with the solution
The ratio is 160/441 and 88200 input frames correspond nominally to 32000 output frames. Drift is 16000×100×10⁻⁶×60=96 excess frames, corresponding to 96/16000=0.006 seconds, or six milliseconds, before any corrective policy.
Keep the idea
Take it with you
- Sample indices, channel layout, nominal rate, and physical clock rate are distinct information.
- Rate reduction requires a filtering and timing contract rather than metadata relabeling.
- Streaming conversion preserves filter history, fractional phase, and explicit latency across packet boundaries.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.