Audio Kernels Deep Dive: From WAV to Encoder Tokens, Kernel by Kernel
src/kernels/audio_kernels.c and include/ckernel_audio.h — numerically explicit
FP32 reference kernels. Every stage below is a named C function with a PyTorch oracle, not hidden preprocessing.
Pipeline overview: Concepts — Audio Frontend;
operator commands: v8 Runbook; evidence: Whisper Tiny End-to-End.
The Whisper Tiny frontend turns a PCM16 WAV into the [1500 × 384] token matrix the audio
encoder consumes. CK breaks that transformation into seven circuit operations across six frontend stages —
STFT table construction and STFT execution are separate ops — each with one job, one layout contract, and one
parity oracle. This page walks each kernel the same way the DeltaNet deep dive walks the recurrent update:
the math, the way the C actually computes it, the memory layout, and the evidence that pins it to PyTorch.
Table of Contents
- 1. WAV Decode —
audio_wav_decode_memory_pcm16_mono_f32 - 2. Resample —
audio_resample_linear_f32/audio_resample_windowed_sinc_f32 - 3. Pad / Truncate —
audio_pad_or_truncate_f32 - 4. STFT Power —
audio_stft_power_fft400_f32(20×20 mixed radix) - 5. Mel Filters —
audio_whisper_mel_filters_slaney_f32 - 6. Log-Mel —
audio_whisper_log_mel_from_power_reference_f32 - 7. Conv1D Stem —
audio_conv1d_channel_major_f32 - 8. Token Transpose —
audio_transpose_channel_to_token_f32 - 9. Supporting Kernels — position embeddings, erf GELU, head-major attention
- 10. The Encoder Body — four bidirectional blocks
- 11. Transformer-XL Relative Attention — position table, fused scores, relative shift
- 12. The FastConformer Convolution Module — GLU, depthwise Conv1D, inference BatchNorm
- 13. The LSTM Step — IFGO gates in PyTorch order
- 14. One Log-Mel Family, Three Contracts — Whisper vs Parakeet vs Cohere
- Parity & Nightly Coverage
1. WAV Decode: Bytes With a Contract, Not a Library Call
Most pipelines hand WAV parsing to a media library. CK walks the RIFF container by hand because the frontend's
input contract is part of the numerical evidence: PCM (format tag 1), 16-bit, any channel count, any sample
rate — anything else is rejected with a distinct error code before a single float is produced.
audio_wav_parse_memory validates the container, audio_wav_decode_pcm16_mono_f32 turns it
into mono f32, and the frontend circuit's map-owned provider audio_wav_decode_memory_pcm16_mono_f32
fuses the two into the single call the generated code makes. For audio that is already interleaved int16 in memory,
audio_pcm_s16_to_mono_f32 applies the same conversion without the container walk.
How The C Reads
- The chunk walker starts at offset 12 and hops chunk-to-chunk, adding a pad byte for odd-sized chunks — RIFF alignment is part of the format.
- Only the first
fmtanddatachunks are honored; everything else is skipped, so metadata-heavy WAVs (LIST, cue, bext) parse fine. - Multi-channel audio is downmixed by mean, not by taking channel 0 — stereo and mono files produce the same scale.
Why Not libsndfile
The frontend's whole job is to be a numerical contract. A hand-rolled 60-line parser means the exact set of accepted inputs is auditable, the downmix rule is explicit, and no platform codec version can drift the parity gates. The generated artifact owns WAV-to-encoder execution through ck_model_run_audio_wav; the transformer body itself never sees a WAV — it consumes the log-Mel tensors this kernel chain guarantees.
2. Resample: Two Explicit Paths to 16 kHz
Whisper expects 16 kHz mono. CK exposes two named resamplers and the contract records which one a run used:
audio_resample_linear_f32 for the fast path, and audio_resample_windowed_sinc_f32 for the
band-limited path. Both share one frame-count convention — audio_resampled_frame_count returns
1 + (n_in − 1) · r_out / r_in, preserving both endpoints of the signal, so a file never grows or
shrinks silently by a rounding choice.
How The C Reads
- All position math is double (
source = frame · r_in / r_out), so long files do not accumulate phase drift. - The linear path does its interpolation in integer numerator arithmetic plus one
fmaflerp — no float division per sample. - Out-of-range taps are skipped, not clamped; the
Σwdenominator makes the surviving window exact at both signal edges. radiusis bounded to[2, 128]— the kernel support is part of the validated contract.
Why Two Kernels Instead of One Flag
A boolean fast=true inside one function would hide which numerical path produced the evidence. Two named entry points mean the run report can say which resampler fed the STFT, and the parity gate can pin each one separately. Whisper Tiny at 16 kHz input skips this kernel entirely — but the contract has to exist for the day a 44.1 kHz file shows up.
3. Pad / Truncate: The Fixed 480,000-Sample Contract
Everything downstream of resampling assumes a fixed time extent: the STFT frame count, the encoder's positional
embedding table, and the 1500-token cross-attention bridge all derive from exactly 480,000 samples
(30 s at 16 kHz). audio_pad_or_truncate_f32 is the kernel that makes that true for
arbitrary input — short clips are zero-padded, long clips are truncated (not chunked), and the function
returns how many frames were real.
How The C Reads
memmove, notmemcpy— the copy is overlap-safe even if caller and callee ever share a buffer.- Only the tail beyond
copiedis zeroed; real samples are never touched, so a full 30 s clip is a pure pass-through. - The return value is the real frame count — downstream stages can distinguish signal from padding without a side channel.
Why Not Implicit In Resample
Extent normalization is a separate circuit operation (audio_pad_or_truncate) because the 30 s limit is a policy with numerical consequences — zero-padding changes the STFT energy and truncation loses content. Naming it keeps the policy auditable, keeps the resampler's contract purely about rate, and lets the limitation docs point at one honest line: longer files are truncated, not chunked.
4. STFT Power: Whisper Geometry as a 20×20 Mixed-Radix FFT
The spectrum is where the frontend spends nearly all of its FLOPs, and where parity is easiest to break.
Whisper's geometry is fixed: n_fft = 400, hop = 160, 201 bins, a
periodic Hann window, and center = true with reflect padding.
CK has three implementations of the same contract — a table-driven direct DFT
(audio_stft_power_precomputed_f32), a Whisper-specialized mixed-radix FFT
(audio_stft_power_fft400_f32), and the fully self-contained reference
(audio_whisper_stft_power_reference_f32) that the nightly gate runs against PyTorch.
How The C Reads
audio_stft_precompute_tables_f32builds the window and the full[bins × n_fft]cos/sin tables once — the per-frame kernels never callcosf/sinfin the hot loop.- The direct kernel is one
fmafper (sample, bin) per component: simple, obviously correct, and the reference every other variant is checked against. - The fft400 kernel treats 400 as 20×20: stage 1 computes twenty 20-point DFTs over the stride-20 subsequences, stage 2 combines them per output bin with a second twiddle lookup. Scratch is exactly
2 × 400floats. reflect_indexis a loop, not anabs— double reflections at very short signals still land in range.
Why Keep Three Implementations
Same pattern as the DeltaNet reference-first policy: the reference kernel is what the nightly PyTorch gate pins (tones, noise, and impulse signals). The precomputed and fft400 kernels are performance variants whose outputs must agree with that reference — so a faster FFT can never silently change the numbers the model was validated with. The circuit picks the variant; the contract keeps them equal.
5. Mel Filters: The Slaney Filterbank, Built Once
Between the STFT power grid and the log-Mel projection sits the filterbank itself: 80 triangular filters over the
201 power bins, spaced evenly on the Slaney mel scale between 0 Hz and Nyquist.
audio_whisper_mel_filters_slaney_f32 constructs the matrix once at table-build time — in double
precision — so the per-frame work stays a single f32 matmul and the triangle geometry can never drift between
runs.
How The C Reads
- All geometry is computed in
double— mel conversions, triangle edges, and the area normalization — then stored as f32; the table is built once and reused for every frame. - Triangles come from
n_mels + 2mel-spaced points converted back to Hz; each bin's weight ismax(0, min(lower, upper))scaled by2/(right−left). - Arguments are validated with typed rejections (−1 null, −2 bad geometry: odd
n_fft, non-positive rates or counts).
Why A Separate Circuit Op
The filterbank used to live inside the composite log-Mel reference. Promoting it to its own operation (audio_mel_filters) makes the Slaney identity a named, parity-gated artifact: the mel scale choice, the +2 point convention, and the area normalization each appear in the numerical contract, and the generated frontend passes the matrix into log-Mel as data — the way PyTorch passes a buffer, not a re-computation.
6. Log-Mel: Perceptual Compression With a Global Clamp
audio_whisper_log_mel_from_power_reference_f32 turns the [201 × T] power spectrum
into the [80 × T] log-Mel matrix the conv stem consumes. Three distinct numerical decisions live
here, and all three match whisper.log_mel_spectrogram exactly: a Slaney-style triangular mel
filterbank, a floored log10, and a global dynamic-range clamp before the final affine
rescale. The fused entry point audio_whisper_log_mel_reference_f32 is just STFT + this kernel composed
— the nightly gate checks the composition as well as the stages.
How The C Reads
- The filterbank is constructed in planned memory by
audio_whisper_mel_filters_slaney_f32and passed in as a[n_mels × 201]matrix — this kernel owns the contraction, while the mel-filter op upstream owns the design. - Pass one computes
log10(max(M, 1e-10))per entry while tracking the global maximum; pass two applies the floor and the(x+4)/4rescale in place. - The output layout is mel-major (
log_mel[mel · T + frame]) — which is precisely the channel-major layout the Conv1D stem wants, so no copy sits between the two kernels.
Why The Clamp Is Global
A per-frame clamp would renormalize silence up to the same range as speech and the encoder would see phantom structure in quiet regions. Whisper's max − 8 floor (80 dB below the loudest frame of the utterance) preserves relative energy across time. It is one line of C — and one of the easiest places for a reimplementation to quietly diverge, which is why the impulse-signal oracle exists.
7. Conv1D Stem: The Only Learned Layers Before Attention
audio_conv1d_channel_major_f32 is the frontend's first weighted kernel — everything
before it is fixed signal processing. The Whisper stem is two 3-tap convolutions with GELU between them:
80 → 384 at stride 1, then 384 → 384 at stride 2, which halves the
time axis from 3000 log-Mel frames to the 1500 audio tokens the encoder (and the decoder's
cross-attention) is built around. The kernel is deliberately generic — channels, kernel size, stride, and
padding are parameters — because the same contraction serves any 1D conv frontend.
How The C Reads
- Output-frame count is validated up front:
(T + 2p − k)/s + 1— a mismatched caller gets-3, not a buffer overrun. - Zero padding is a bounds check (
in_frame >= 0 && in_frame < T), not a padded buffer — no scratch allocation, no memset. - The accumulation starts from
bias[o]and runsfmafover (in_channel, tap) — deterministic FP32, one rounding per multiply-add. - Channel-major layout means each input row is contiguous, so the inner loop streams memory instead of striding across planes.
Why Stride 2 Is The Whole Point
Attention cost grows quadratically with sequence length. Halving the time axis before the transformer body is what makes 30 seconds of audio a 1500-token problem instead of a 3000-token one — a 4× attention saving, bought with a single 3-tap convolution. It is also the origin of the number 1500 that shows up everywhere downstream: encoder rows, cross-attention K/V rows, the Q=1, K=1500 decode oracle.
8. Token Transpose: The Named Layout Seam
audio_transpose_channel_to_token_f32 is eight lines of C and one of the most important kernels in the
frontend. Everything upstream is channel-major ([C × T]) because convolutions want
contiguous channels; everything downstream is token-major ([T × C]) because
attention wants one row per sequence element. This kernel is the single explicit point where the layout flips —
after it, the learned positional embedding is added and the matrix is literally the 1500-token sequence the encoder
reads.
How The C Reads
- Two loops, one assignment:
out[t·C + c] = in[c·T + t]— the reference is deliberately naive so the layout contract is unmistakable. - It is the only place the audio pipeline reorders memory; an optimized tile/blocked variant can replace it later as long as the contract (and the parity gate) holds.
- The positional embedding kernel operates token-major immediately after — the same
position_embeddings_add_*family the vision encoder uses, reused, not duplicated.
Why A Kernel, Not A Comment
Layout bugs are the silent killer of bring-up: the model runs, the shapes match, and the output is plausible-but-wrong. Making the transpose a named kernel means the circuit JSON can declare logical_layout: token_major at its output checkpoint, the x-ray probe can compare that checkpoint against PyTorch directly, and any future fused frontend must still honor the same boundary.
9. Supporting Kernels: The Shared Glue
Three library kernels complete the audio path without being Whisper-specific. position_embeddings_add
applies the learned 1D table after the token transpose — the same kernel the vision lane uses for its 2D table.
gelu_pytorch_erf_f32_inplace is the exact erf GELU the stem contracts pin (note the naming trap:
gelu_exact_inplace is historically the tanh approximation despite its name). And
attention_forward_query_key_head_major_f32 serves both attention oracles — the batched causal
self-attention transition and the Q=1, K=1500 cross-attention decode step — with head-major rows
that keep the cached K/V slices contiguous.
Why They Are Not Whisper Kernels
- Each already has a numerical contract from the text or vision lanes — the audio path inherits parity rather than re-proving it.
- This is the concrete form of "no Whisper model-name branch in codegen": the encoder is assembled from library pieces whose oracles predate Whisper.
Where They Are Pinned
unittest/test_audio_encoder.py exercises the erf GELU oracle (max diff ≤ 5e-7) and the
head-major attention oracles — including the Q=1, K=1500 cross case — against PyTorch
softmax(Q·Kᵗ/√d)·V. The positional add is pinned by the same suite's encoder
checkpoint-by-checkpoint X-ray.
10. The Encoder Body: Four Bidirectional Blocks
Everything so far produced tokens. The encoder's job is to contextualize them: four identical
pre-LayerNorm blocks turn the raw [1500 × 384] frame sequence into a memory where each frame's
vector has absorbed meaning from the whole 30 seconds. The block contract is explicit in
audio_transformer_encoder.json: layernorm → q/k/v_proj → attn → out_proj →
residual → layernorm → mlp_up → gelu → mlp_down → residual, then one final LayerNorm.
The attention itself is where the audio encoder differs from the decoder you already know. Three facts,
all declared in the circuit's attention_contract: it is dense bidirectional
(causal: false) — the score grid is the full 1500×1500 square, not the decoder's causal
triangle, so the frame under the word "country" borrows from frames before and after it. There is
no RoPE — position comes from the absolute learned table added back at the transpose. And the
K/V are ephemeral (ephemeral_full_context) — computed per layer, used once, freed;
caching belongs to the decoder, not here. Per head (6 heads × 64 dims) the math is the usual
softmax(Q·Kᵗ/√64)·V — softmax row-normalizes the square, so each frame's output
is a weighted mixture of all 1500 value rows.
What The Encoder Buys The Decoder
- Context per frame: after 4 layers, row
tis no longer "20 ms of spectrum" — it is that spectrum disambiguated by its acoustic surroundings, which is what makes cross-attention retrieval meaningful. - A stable retrieval target: because the memory is immutable for the segment, the decoder can project K/V from it once and cache them — the measured 79× decode win lives downstream of exactly this property.
Where It Is Pinned
The 79-edge PyTorch X-ray (compare_whisper_encoder_pytorch_v8.py) checkpoints the encoder
block by block — stem, positional add, per-layer attention and MLP, final norm — with
max abs ≈ 5.05e-4 and RMSE ≈ 6.7e-6 in FP32. The encoder is the dominant stage at
≈11.15 s of the ≈12.22 s end-to-end run, which is why it carries the deepest parity
evidence on this page.
11. Transformer-XL Relative Attention: One Position Table, Two Score Kernels
The FastConformer encoders in Parakeet and Cohere do not use learned absolute positions or RoPE. Position
enters only through the attention scores, Transformer-XL style: a sinusoidal table over relative offsets,
two learned per-head bias vectors bias_u/bias_v, and a score that is the sum of a
content term and a position term. CKE implements this as three providers.
audio_relative_sinusoidal_position_f32 builds the [2T-1, E] table once per forward
(descending offsets T-1 .. -(T-1), sin/cos interleaved). Each layer projects it with the existing
GEMM provider into a head-interleaved relative_key. Then either the scores are computed fused
— Parakeet's audio_conformer_relative_attention_f32 — or a full raw position-score
matrix is materialized and re-indexed by audio_relative_shift_f32, which is the composition
Cohere's encoder uses.
How The C Reads
- The position kernel is serial and allocation-free: one
powfper channel pair, onesinf/cosfper element, rows written position-major so the attention kernel'sr[T-1+k-q]row is one contiguous 1024-float read. - The attention kernel partitions heads across the threadpool, then walks queries and keys; content and position dots accumulate in scalar FP32 over the 128-dim head slice, and the row max is tracked during the score pass so softmax is exactly two passes with no third pass.
- The score scratch is
[heads, frames]and caller-owned — one row per head, no heap allocation inside the kernel (a v8 runtime invariant). - The shift kernel does no arithmetic at all:
output[key] = raw[origin+key]withorigin = T-1-q, threadpool overH*Trows — its contract is the exactness of the index map, which the map states asraw[h,q,T-1+k-q] -> scores[h,q,k].
Why Two Score Kernels for One Idea
Cohere's pinned encoder composes Transformer-XL the textbook way — a full raw [H,T,2T-1] position-score product followed by a shift — so the shift is a named provider with its own oracle. Parakeet's pinned reference computes the same scores by direct indexing, so CKE fuses bias-u/v, the relative lookup, softmax, and the value product into one head-parallel provider and never materializes the shifted matrix. Both are pinned against PyTorch in unittest/test_audio_encoder.py (check_relative_sinusoidal_position, check_relative_shift, check_conformer_relative_attention), and the Parakeet end-to-end encoder RMSE is 9.08e-6 against a 2e-5 gate. Claim boundary: this is eager FP32 reference math — head-parallel, not flash — and the checkpoint's 5,000-position limit bounds the full-attention path.
12. The FastConformer Convolution Module: GLU, Depthwise Conv1D, Inference BatchNorm
Every FastConformer block carries a convolution module between the attention and the second Macaron FFN:
pointwise Conv1D (1024→2048) → GLU → depthwise Conv1D (K=9) → BatchNorm →
SiLU → pointwise Conv1D (1024→1024), wrapped in a residual add. Three of its stages are the
new providers — audio_conv1d_channel_major_grouped_f32 (one kernel covering pointwise,
grouped, and depthwise via the groups argument, with an optional bias), audio_glu_split_channel_major_f32,
and audio_batch_norm_inference_channel_major_f32. All of them operate on the same
channel-major [C, T] layout: one contiguous 93-float row per channel on the
worked fixture (width 1024, 93 frames after subsampling).
How The C Reads
- The grouped Conv1D derives the group from the output channel (
group = c_out / (C_out/G)); a depthwise conv is justG = C, so one provider covers pointwise, grouped, and depthwise — validated againsttorch.nn.functional.conv1d'sgroupsparameter. - Interior output frames run AVX2+FMA eight at a time (with a contiguous stride-2 load path and a gather fallback); the edge frames use the scalar
fmafloop with bounds-checked taps, so zero padding is index math and never materialized. - The GLU is layout-free elementwise over
C*T: because the input is[2C, T]channel-major, value and gate are two contiguousC*Tblocks —out[i] = value[i] * sigmoid(gate[i]), threadpool over elements. - BatchNorm folds to a per-channel affine:
scaleandoffsetare computed once per channel, then the frame loop is one multiply-add per element. Running statistics are read-only — the checkpoint's 24 training counters are excluded at conversion by contract, and a nonfinite or non-positivevar+epsreturns an error instead of producing NaNs.
Why Channel-Major Inside
Depthwise conv and BatchNorm both stream one channel across all frames; in channel-major that is one contiguous 93-float row — unit-stride loads for the AVX2 interior and trivial prefetch. Token-major would straddle 1024 floats per tap. The module pays two transposes at its boundary (host-side value.T copies in the runner) so every kernel inside keeps the layout it is vectorized for — the layout seam is explicit in the orchestration, not hidden behind a kernel flag. Parakeet's depthwise weights carry no bias, so the provider's bias pointer is optional; the same contract serves Cohere's biased convolutions. Pinned in unittest/test_audio_encoder.py (check_grouped_conv1d, check_split_glu, check_batch_norm_inference, check_conv_stride2_production_equivalence).
13. The LSTM Step: IFGO Gates in PyTorch Order, One Token at a Time
Parakeet's prediction network is a two-layer, 640-wide LSTM — the language-model half of the TDT
transducer. audio_lstm_step_f32 advances it by exactly one token: one gate preactivation over the
fused [4H, I]/[4H, H] weight matrices, one IFGO nonlinearity pass in PyTorch's gate
order, and an in-place state update. The kernel is deliberately a step: the next input token depends on
an argmax over the joint head, which depends on this LSTM's output, so there is no sequence to batch. State
(h, c) is session-owned and persists across decode steps; the 4H gate buffer is
caller-owned scratch shared by both layers; the kernel never touches the heap.
How The C Reads
- The gate preactivation is 4H independent serial dot products — input dims first, then hidden dims, single FP32 accumulator seeded with
b_ih + b_hh— so the result is deterministic regardless of thread count (the map declares the kernel serial). - The nonlinearity pass walks IFGO slices of the same scratch buffer — PyTorch's gate order, which is exactly what the checkpoint's fused
weight_ih_l*tensors assume. Getting the order wrong still produces finite numbers, just the wrong transcript; the oracle exists for that reason. handcare updated in place from their old values, and the runner passes distinct per-layer state slices — two decode sessions never share mutable state (guarded bytests/test_v8_parakeet_native.py).
Why a Step Kernel, Not a Sequence Kernel
The transducer's next input token depends on an argmax over the joint head, which depends on this LSTM's output — a classic recurrent decode dependency with nothing to batch. A single-step provider with session-owned state is the honest shape: the prediction network runs only after nonblank emissions (44 times on the 50-step fixture trajectory), state lifetime is the decode session, and reset/reuse semantics live in the runner rather than in kernel flags. Evidence: check_lstm_step against torch.nn.LSTM single-step FP32 CPU in unittest/test_audio_encoder.py, and 50/50 token IDs plus 50/50 durations exact against the pinned Transformers reference end to end.
14. One Log-Mel Family, Three Contracts: Whisper vs Parakeet vs Cohere
Sections 4–6 walked the Whisper log-mel. Parakeet and Cohere reuse the same Conformer frontend provider
family — pre-emphasis, centered STFT, Slaney mel, natural-log projection, per-feature normalization —
but the contract differs at five points, and each difference changes the numbers the encoder was
trained to expect. The table below is the exact divergence map, grounded in the two circuit contracts
(parakeet_tdt.json, cohere_transcribe.json) and the two session runners that select
the provider arguments.
Why Seven Providers Cover All Three
The frontend family is dimension-general by design: audio_preemphasis_f32 takes the coefficient, audio_stft_power_centered_window_f32 takes n_fft/window/hop/centering, audio_whisper_mel_filters_slaney_f32 builds any bank size (its legacy name notwithstanding), audio_log_mel_time_major_f32 takes its epsilon as an argument, and audio_feature_normalize_per_feature_f32 takes the frame span. What differs per lane is contract, not code: which epsilon, which window source, which frames count as live. Whisper is the odd one out — log10, a global data-dependent clamp, no normalization — because its (x+4)/4 squash is the scaling contract the Whisper encoder was trained with.
Claim Boundary
Three distinct numerical contracts, three distinct oracles: Whisper against the torch.stft-style reference (log-Mel max ≤ 1.1e-3), Parakeet against the pinned Transformers feature extractor (frontend RMSE 4.06e-4, gate 5e-4), Cohere against CrispASR stage dumps (32/32 token IDs exact). Feeding one model's audio through another's contract is wrong by construction, not by tolerance. One wrinkle worth knowing: the cohere_transcribe circuit contract string says per_feature_population_variance_all_frames, but the selected provider computes a sample variance (N−1) over all frames — the certified behavior, pinned exact against CrispASR; the contract label and the implementation disagree, and the oracle pins the implementation.
Parity & Nightly Coverage
Where Every Kernel Above Is Pinned
make test-audio→unittest/test_audio.py: log-Mel frontend vs PyTorch (torch.stft, periodic Hann, reflect pad) across tones, noise, and impulse signals — power relative max ≤ 2e-5, log-Mel max ≤ 1.1e-3, RMSE ≤ 9e-5 — plus a stage-composition check that STFT + log-Mel equals the fused reference.unittest/test_audio_encoder.py: Whisper stem-1 / stem-2 Conv1D oracles, GELU erf (approximate='none') oracle, batched causal self-attention and persistent KV-cache transition oracles, and theQ=1, K=1500cross-attention decode oracle.tests/test_v8_audio_contract.pyandtests/test_v8_audio_encoder_contract.py: the portable v8 circuit/codegen regressions, including the checkpoint-by-checkpoint encoder x-ray driven bycompare_whisper_encoder_pytorch_v8.py.make test-whisper-e2e-auto(opt-in): full model-and-WAV transcription against the reference token sequence — the JFK sample matches Hugging Face token for token.
Operator commands live in the v8 Runbook; the pipeline and evidence live in Whisper Tiny End-to-End; the kernel-level math is summarized in Concepts — Audio Frontend & Cross-Attention. For the same treatment of a recurrent kernel family, see the Gated DeltaNet Deep Dive.
The Parakeet TDT lane reuses this frontend family (pre-emphasis, centered STFT, Slaney log-mel, per-feature
normalization, grouped Conv2D subsampling) and adds five FastConformer/transducer providers — grouped
Conv1D, relative sinusoidal position, relative attention, inference BatchNorm, and a stateful LSTM step —
whose PyTorch oracles run in the same unittest/test_audio_encoder.py suite. Sections
11–14 walk those kernels and the
three-way log-mel contract split; see
Parakeet TDT Native CPU Bring-up for the architecture, decode semantics,
and runbook.