effectcraft-opusenc
Clean-room, pure-Rust Opus encoder for EffectCraft's WebM export audio (layer L0, std only,
no unsafe, builds for wasm32-unknown-unknown).
All three Opus modes, 20 ms packets (one frame per packet), 48 kHz float input, mono or stereo:
- CELT (fullband): MDCT transform coding, constant packet size.
- SILK (narrowband 8 kHz, mediumband 12 kHz, wideband 16 kHz internal rate): linear prediction with long-term (pitch) prediction; packet size varies around the target bitrate.
- Hybrid (super-wideband, fullband): SILK wideband codes 0–8 kHz and CELT codes bands 17 and up (8 kHz and above) in the same range-coded frame; constant packet size.
use effectcraft_opusenc::{Application, OpusEncoder};
let mut enc = OpusEncoder::with_application(2, 48_000, Application::Voip);
let packet = enc.encode_float(&vec![0.0; OpusEncoder::FRAME_SIZE * 2]);
// enc.mode(), enc.bandwidth(), enc.pre_skip(), enc.opus_head() ...
OpusEncoder::new(channels, bitrate) is with_application(.., Application::Audio).
OpusEncoder::with_mode(channels, bitrate, mode, bandwidth) forces a mode/bandwidth pair
(SILK: NB/MB/WB; hybrid: SWB/FB; CELT: FB).
Mode table
Chosen once per stream (constant-bitrate export, no in-stream switching) from the bitrate per channel (bitrate / channels; the total is clamped to 6 kb/s per channel … 510 kb/s):
| per-channel bitrate | Application::Voip |
Application::Audio (default) |
|---|---|---|
| < 10 kb/s | SILK narrowband (8 kHz) | SILK wideband |
| 10–12 kb/s | SILK mediumband (12 kHz) | SILK wideband |
| 12–16 kb/s | SILK wideband (16 kHz) | SILK wideband |
| 16–18 kb/s | SILK wideband | hybrid fullband |
| 18–28 kb/s | hybrid super-wideband | hybrid fullband |
| 28–36 kb/s | hybrid fullband | hybrid fullband |
| 36–40 kb/s | hybrid fullband | CELT fullband |
| ≥ 40 kb/s | CELT fullband | CELT fullband |
TOC configurations (RFC 6716 §3.1, Table 2): SILK NB/MB/WB 20 ms = 1/5/9, hybrid SWB/FB 20 ms = 13/15, CELT FB 20 ms = 31; the stereo bit is set for two channels; frame-count code 0.
pre_skip() is 120 samples in every mode: the CELT MDCT overlap, and for SILK/hybrid the
decimator delay (83 samples at 48 kHz, 88 for narrowband) plus the decoder's SILK delay (one
internal-rate sample and the resampler delay of RFC 6716 Table 54). The SILK and CELT halves of a
hybrid frame are therefore aligned without extra buffering.
What is implemented
SILK (RFC 6716 §4.2, encoder direction; own analysis and search design):
- 48 kHz → 8/12/16 kHz decimation with a linear-phase Kaiser-windowed-sinc FIR.
- Per frame: energy VAD (inactive / unvoiced / voiced), open-loop pitch search (normalised correlation with octave checks, joint lag + contour codebook choice, §4.2.7.6.1), windowed autocorrelation LPC (Levinson, lag window, bandwidth expansion), LPC → NLSF by root search, NLSF quantisation (stage-1 preselection by weighted distance, backwards-predictive stage-2 scalar quantiser reproducing the decoder's dequantisation exactly, rate-distortion choice), LTP codebook search over the three periodicity codebooks, independent + delta gain coding.
- Analysis-by-synthesis excitation: every sample is chosen by running the decoder's exact
fixed-point reconstruction (LTP from the decoder's own past output, LPC synthesis with the Q12
coefficients of the dequantised NLSFs, gain rescaling between subframes, quantisation
offsets, the LCG sign sequence), so encoder and decoder never drift. A noise-feedback loop
shapes the coding noise by
1/A(z/γ)(γ 0.75–0.9, coarser quantisation → more shaping), and a small rate penalty biases pulses towards zero. - Excitation coding: rate level, per-block pulse counts with LSB escapes, shell coding, LSBs and signs (§4.2.7.8).
- Rate control: per-frame search over a gain offset (integer bracket, then bisection) to the frame budget; SILK-only streams carry a bit reservoir across frames (packet sizes vary).
- Stereo: mid/side with the decoder's stereo prediction (§4.2.7.1, §4.2.8; ridge-regularised least-squares weights, quantised to the decoder grid, interpolation mirrored), mid-only frames when the predicted side is negligible, side gains floored at the mid gains.
- Not implemented: LBRR (in-band FEC), NLSF interpolation, 10/40/60 ms frames, DTX.
Hybrid (§4.3 with start band 17): the SILK frame is written first, then the redundancy flag (always 0) when there is room, then a CELT frame coding bands 17–18 (SWB) or 17–20 (FB) in the same range coder with the remaining packet bytes (no silence flag or post-filter in hybrid frames, decoder band-energy reset for uncoded bands mirrored). SILK gets 72 % (SWB) / 62 % (FB) of the per-channel bitrate, at most the bitrate minus 6 kb/s, and never more than leaves CELT a fifth of the packet (at least 80 bits).
CELT (unchanged): forward MDCT with the low-overlap window, band energies with inter/intra coarse prediction, fine and final energy bits, the decoder's exact bit allocation, spreading, recursive band splitting, greedy PVQ search. Not implemented: transient frames, TF changes, pitch post-filter, intensity stereo, dynamic allocation, VBR. All-zero CELT frames become 3-byte silence packets.
Measured (tests in tests/, FilmCraft decoder)
Synthetic speech (glottal pulses 100–200 Hz through three moving formants, syllable envelopes, pauses) and music (three-note harmonic chords); waveform SNR against the input band-limited to the mode's bandwidth (full band for hybrid/CELT), residual delay 0 (±1 for narrowband) after the pre-skip:
| mode / bandwidth | bitrate target → actual | speech SNR | music SNR |
|---|---|---|---|
| SILK NB | 8 → 7.5 kb/s | 15.9 dB | 6.9 dB (9 kb/s) |
| SILK MB | 11 → 10.1 kb/s | 21.8 dB | 7.9 dB |
| SILK WB | 12 → 10.9 kb/s | 21.5 dB | 8.1 dB |
| SILK WB | 16 → 14.3 kb/s | 28.1 dB | 12.1 dB |
| SILK WB | 24 → 21.1 kb/s | 37.0 dB | 19.7 dB |
| hybrid SWB | 24 kb/s (CBR) | 28.7 dB | 13.0 dB |
| hybrid FB | 32 kb/s (CBR) | 32.1 dB | 15.6 dB |
| CELT FB | 12 kb/s (CBR) | 13.0 dB | — |
At 12 kb/s mono, SILK wideband beats the CELT path on speech by ~8 dB (21.0 vs 13.0 dB full-band SNR). SILK bitrates land within −13 % … 0 % of the target (speech spends little in pauses), hybrid is exact. Stereo SILK WB at 32 kb/s: 41 dB dual-mono, 40/37 dB panned, 22/19 dB for two independent speech signals.
ffmpeg (external oracle, Ogg Opus written by the test) decodes every mode with both its native
opus decoder and libopus without errors, honouring pre-skip and end trimming, with the same
SNRs (libopus residual delay 0, ffmpeg's native decoder 0–4 samples). The only message tolerated
is ffmpeg's raw-PCM muxer timestamp complaint that its native decoder also prints for
narrowband files encoded by libopus itself.
Specifications
- RFC 6716, Definition of the Opus Audio Codec (September 2012), with the RFC 8251 updates (October 2017) as implemented by the decoder we round-trip against.
- RFC 7845, Ogg Encapsulation for the Opus Audio Codec (April 2016), §5.1
OpusHeadand §4.2 pre-skip.
Provenance
Implemented from the RFC text. Constant tables (CELT band edges, eMeans, the coarse-energy
Laplace model, the allocation table, ICDFs; all SILK probability tables and codebooks: NLSF
stage-1/2 codebooks and prediction weights, gain, pitch, contour, LTP and pulse ICDFs, stereo
weights) and the decoder-side normative arithmetic the encoder must reproduce bit-exactly (CELT
allocation; SILK NLSF dequantisation and stabilisation, NLSF → LPC conversion, log2lin, the
fixed-point division/inverse helpers and the LPC analysis filter) are mirrored from FilmCraft's
first-party, spec-derived filmcraft-opus decoder (MIT OR Apache-2.0), which is also the
round-trip oracle in tests/ and crates/export/tests/opus_roundtrip.rs (ffmpeg is a second,
external oracle when installed). All encoder-side analysis and search (pitch, LPC, NLSF and
LTP search, noise feedback, rate control, stereo prediction, the decimator) is our own design.
No third-party encoder or decoder source (libopus or otherwise) was consulted.