Each frame in a packet is compressed with a range coder. Its contents are in the order given in RFC 6716 sections 4.2 (SILK) and 4.3 (CELT), and the fields are not byte-aligned: their widths depend on probability tables, so a frame can only be read by decoding it.
The range coder
Frames use an arithmetic range coder. The decoder is initialised from the frame’s first bytes, and each symbol is read with a table of cumulative probabilities or as uniform raw bits. Raw bits come from the end of the frame, working backwards, while range-coded symbols work forwards from the front. A SILK frame uses range-coded symbols only; CELT uses both, sharing bytes from either end.
SILK layer
SILK is a linear-prediction codec for speech, at 8, 12 or 16 kHz internally. In a packet, SILK frames come in groups that make up the packet’s duration. In order:
| Part | Fields |
|---|---|
| Flags | one VAD (voice activity) flag per 20 ms SILK frame, then an LBRR flag for the packet |
| LBRR | per-frame LBRR flags, then low-bitrate redundancy data (a copy of the frame for packet loss recovery) |
| Stereo | a mid-side prediction weight, and a flag giving whether the side channel is coded |
| Frame type | a signal type (inactive, unvoiced or voiced) and quantisation offset type |
| Gains | one subframe gain each for every 5 ms, coded in a log scale, independently or as a difference |
| LSF coefficients | normalised line spectral frequencies, from a two-stage vector quantiser |
| Interpolation | a factor to mix with the previous frame’s LSFs on 20 ms frames |
| Pitch lags | a lag per subframe, for voiced frames |
| LTP | long-term prediction filters per subframe, and a scale for them |
| Seed | a value for the excitation noise generator |
| Excitation | the rate level, pulse counts in shell blocks, shell splits, low bits and the signs of the non-zero samples |
CELT layer
CELT is a transform codec based on the modified discrete cosine transform, for music and low delay. Its bands are coded at 48 kHz in 21 bands. In order:
| Field | What it says |
|---|---|
| Silence | a flag: this frame is silent |
| Post-filter | a flag, then pitch period, gain and tapset for the pitch post-filter |
| Transient | the frame uses several short MDCTs instead of one long one |
| Intra | the coarse energy uses no prediction from the previous frame |
| Coarse energy | band energies, using a Laplace distribution by band |
| tf_change | per-band changes to time or frequency resolution |
| tf_select | selects the table of those resolutions |
| Spread | a spreading decision for the rotation of PVQ vectors |
| Dynamic allocation | extra bits for particular bands |
| Allocation trim | tilts the bit allocation towards low or high bands |
| Skip | which high bands are not coded at all |
| Intensity, dual stereo | the stereo method for the bands |
| Fine energy | more precise band energies in raw bits |
| Shape | each band’s normalised vector, coded by PVQ with a band-splitting scheme |
| Anti-collapse | a flag that prevents collapse in transients |
| Energy finalisation | extra fine energy from leftover bits |
Hybrid frames and transitions
A Hybrid frame has a SILK layer for the low frequencies and a CELT layer above 8 kHz. Mode changes between SILK and CELT can be cross-faded using a short redundant CELT frame, which sits at the end of the frame and is signalled with one extra bit.
Links
- RFC 6716 – definition of the Opus audio codec