LC3 Decoding: Decoder Modules and Bitstream Decoding

 

LC3 Decoding: Decoder Modules and Bitstream Decoding
Chapter 3, Sections 3.4.1 and 3.4.2 — Decoder Pipeline, Side Info Read, Arithmetic Decoding, BEC Detection
Chapter
3 — Sections 3.4.1–3.4.2
Subsections
3.4.1, 3.4.2.1–3.4.2.7
Level
Advanced

Decoding is the reverse of encoding. The decoder reads the payload in the same two-direction fashion: backward from the end to get side information, and forward from the start to run the arithmetic decoder. Everything the encoder computed is reconstructed from these two streams. The decoder also detects corrupt bitstreams (BEC — Bit Error Condition) and can trigger Packet Loss Concealment when corruption is detected.

Keywords

Decoder Pipeline BEC_detect read_bit / read_uint ac_dec_init / ac_decode nf_seed zeroFrameFlag

3.4.1 Decoder Module Pipeline

The decoder reverses the encoder’s steps. The received bitstream is unpacked to restore the spectral coefficients, then the SNS and TNS shaping is undone, and the spectrum is inverse-transformed back to the time domain. Finally, the LTPF postfilter is applied.

When BFI = 1 (bad frame), the decoder skips bitstream decoding entirely and invokes Packet Loss Concealment (PLC) to generate a substitute output frame.

Step Module What It Does Section
1 Bitstream Decoding Reads side info + arithmetic decodes spectral data to get Xq̂ 3.4.2
2 Residual Decoding Applies residual refinement bits to non-zero Xq̂ 3.4.3
3 Noise Filling Fills zero-valued coefficients with random noise at level FNF 3.4.4
4 Global Gain Multiplies Xq̂ by the decoded global gain to restore magnitude 3.4.5
5 TNS Decoder Applies synthesis (all-pole IIR) lattice filter to undo TNS analysis 3.4.6
6 SNS Decoder Decodes scale factors, interpolates, and multiplies to undo SNS 3.4.7
7 Inverse LD-MDCT Converts spectrum back to time domain samples 3.4.8
8 LTPF Decoder Applies pitch-based IIR postfilter to reduce noise in spectral valleys 3.4.9
9 Output Scaling Clips to 16-bit range and scales to output bit depth 3.4.10

3.4.2.1 Bitstream Decoding Overview

Bitstream decoding mirrors bitstream encoding exactly. The decoder reads backward from byte nbytes−1 to get side information, and forward from byte 0 to run the arithmetic decoder. BEC (Bit Error Condition) checks are performed at multiple points — if BEC is detected, BEC_detect = 1 and the decoder stops parsing and may apply PLC.

3.4.2.2 Initialization

bp       = 0;
bp_side  = nbytes − 1;
mask_side = 1;
c        = 0;
BEC_detect = 0;
rateFlag = (nbits > 160 + fsind*160) ? 512 : 0;

3.4.2.3 Side Information Reading

Side information is read in the exact same order it was written. BEC checks are performed for values that must be in known ranges:

Field Read BEC Check
Pbw (bandwidth index) BEC if fsind < Pbw (impossible: bandwidth exceeds sampling rate’s max)
lastnz = (tmp_lastnz+1)×2 BEC if lastnz > NE
lsbMode No check needed (1 bit)
ggind (8 bits) No check needed
TNS activation flags num_tns_filters inferred from Pbw: 1 if Pbw < 3, else 2
pitch_present No check needed (1 bit)
SNS ind_LF, ind_HF (5+5 bits) No check
SNS Stage 2 bits (28 bits) BEC if joint shape index out of valid range for its submode
LTPF data (if pitch_present=1) No check
FNF (3 bits) No check

3.4.2.4 Bandwidth Interpretation

The decoded Pbw value is mapped back to a bandwidth type (NB/WB/SSWB/SWB/FB) using Table 3.6. This bandwidth information controls the TNS filter range (Section 3.4.6) and the noise filling stop frequency bw_stop (Section 3.4.4).

3.4.2.5 Arithmetic Decoding

The arithmetic decoder reads forward from byte 0. It is initialized with the first 3 bytes of the payload, then decodes symbols using the same probability tables as the encoder.

TNS coefficients: For each active TNS filter, rcorder(f) and rci(k, f) are decoded first.

Spectral data: For each 2-tuple k = 0, 2, 4, …, lastnz−2:

  • Decode escape symbols until sym < 16 (max 14 levels — BEC if lev reaches 14)
  • Read LSB bits from backward stream for each escape level
  • Decode MSB symbol sym = |a| + 4×|b| from arithmetic stream
  • Read sign bits from backward stream for non-zero a, b
  • Accumulate magnitude from escape and MSB levels

BEC is also set if the forward pointer bp crosses the backward pointer bp_side by more than 3 bytes during spectral decoding.

3.4.2.6 Residual Data, nf_seed, and zeroFrameFlag

After spectral decoding, coefficients beyond lastnz are set to zero. Then residual bits are read (in lsbMode=0) or LSBs are applied (in lsbMode=1) to refine the decoded spectrum.

Noise Filling Seed (nf_seed): A deterministic seed for the noise-filling pseudo-random generator is derived from the decoded spectrum:

tmp = SUM[k=0..NE−1] |Xq̂(k)| × k
nf_seed = tmp & 0xFFFF

Zero Frame Flag: If the decoded spectrum appears to be all zeros (PLC trigger condition):

zeroFrameFlag = 1 if lastnz=2 AND Xq̂(0)=Xq̂(1)=0 AND ggind=0 AND FNF=7

When zeroFrameFlag=1, noise filling is skipped (Section 3.4.4). This prevents noise from being injected into intentionally silent frames.

3.4.2.7 Helper Functions

/* read_bit: reads 1 bit from backward stream (mirrors write_bit_backward) */
int read_bit(bytes[], *bp, *mask) {
    bit = (bytes[*bp] & *mask) ? 1 : 0;
    if (*mask == 0x80) { *mask = 1; *bp -= 1; }
    else *mask <<= 1;
    return bit;
}

/* read_uint: reads numbits bits LSB first from backward stream */
int read_uint(bytes[], *bp, *mask, numbits) {
    value = read_bit(bytes, bp, mask);
    for i = 1 to numbits−1:
        value += read_bit(bytes, bp, mask) << i;
    return value;
}

/* ac_dec_init: init arithmetic decoder, consuming first 3 payload bytes */
void ac_dec_init(bytes[], *bp, *st) {
    st->low = 0;  st->range = 0x00ffffff;
    for i = 0 to 2: { st->low = (st->low << 8) + bytes[(*bp)++]; }
}

/* ac_decode: decode one symbol using cumulative frequency table */
int ac_decode(bytes[], *bp, *st, cum_freq[], sym_freq[], numsym, *BEC) {
    tmp = st->range >> 10;
    if (st->low >= tmp << 10) *BEC = 1;
    val = numsym − 1;
    while (st->low < tmp * cum_freq[val]) val--;
    st->low -= tmp * cum_freq[val];
    st->range = tmp * sym_freq[val];
    while (st->range < 0x10000):
        st->low = ((st->low << 8) & 0xffffff) + bytes[(*bp)++];
        st->range <<= 8;
    return val;
}

Next in this Series

Sections 3.4.3–3.4.6 — Residual Decoding, Noise Filling, Global Gain Recovery, and TNS Decoder

Next Tutorial → All Tutorials

Leave a Reply

Your email address will not be published. Required fields are marked *